From python-checkins at python.org Fri May 1 03:21:47 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 01 May 2015 01:21:47 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_=22async/awai?= =?utf-8?q?t_in_CPython_code_base=22_section=2E?= Message-ID: <20150501012147.8139.8548@psf.io> https://hg.python.org/peps/rev/289f0f027cb2 changeset: 5814:289f0f027cb2 user: Yury Selivanov date: Thu Apr 30 21:21:44 2015 -0400 summary: pep-0492: Add "async/await in CPython code base" section. files: pep-0492.txt | 23 ++++++++++++++++++++--- 1 files changed, 20 insertions(+), 3 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -815,7 +815,7 @@ asyncio -------- +''''''' ``asyncio`` module was adapted and tested to work with coroutines and new statements. Backwards compatibility is 100% preserved, i.e. all @@ -832,8 +832,8 @@ Deprecate ``async()`` function. -Migration strategy -'''''''''''''''''' +asyncio migration strategy +'''''''''''''''''''''''''' Because *plain generators* cannot ``yield from`` *native coroutine objects* (see `Differences from generators`_ section for more details), @@ -842,6 +842,23 @@ syntax. +async/await in CPython code base +'''''''''''''''''''''''''''''''' + +There is no use of ``await`` names in CPython. + +``async`` is mostly used by asyncio. We are addressing this by +renaming ``async()`` function to ``ensure_task()`` (see `asyncio`_ +section for details.) + +Another use of ``async`` keyword is in ``Lib/xml/dom/xmlbuilder.py``, +class ``DocumentLS``. ``async`` property is not documented, not +tested, and is not used anywhere. Methods that were likely supposed to +work with it -- ``_set_async()`` and ``_get_async()`` -- are not used +anywhere either. These methods will be deprecated in 3.5 and removed +in 3.6. + + Grammar Updates --------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 1 08:09:12 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 01 May 2015 06:09:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Rename_ensure=5Ft?= =?utf-8?b?YXNrKCkgLT4gZW5zdXJlX2Z1dHVyZSgp?= Message-ID: <20150501060912.124196.99147@psf.io> https://hg.python.org/peps/rev/5d5b24603765 changeset: 5815:5d5b24603765 user: Yury Selivanov date: Fri May 01 02:09:09 2015 -0400 summary: pep-0492: Rename ensure_task() -> ensure_future() files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -828,7 +828,7 @@ 2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. -3. Add ``ensure_task()`` as an alias for ``async()`` function. +3. Add ``ensure_future()`` as an alias for ``async()`` function. Deprecate ``async()`` function. @@ -848,7 +848,7 @@ There is no use of ``await`` names in CPython. ``async`` is mostly used by asyncio. We are addressing this by -renaming ``async()`` function to ``ensure_task()`` (see `asyncio`_ +renaming ``async()`` function to ``ensure_future()`` (see `asyncio`_ section for details.) Another use of ``async`` keyword is in ``Lib/xml/dom/xmlbuilder.py``, -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 1 08:35:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 01 May 2015 06:35:09 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Reword_DocumentLS?= =?utf-8?q?=2Easync_deprecation_section?= Message-ID: <20150501063509.1941.2400@psf.io> https://hg.python.org/peps/rev/2fb66f25db2c changeset: 5816:2fb66f25db2c user: Yury Selivanov date: Fri May 01 02:35:06 2015 -0400 summary: pep-0492: Reword DocumentLS.async deprecation section files: pep-0492.txt | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -852,11 +852,12 @@ section for details.) Another use of ``async`` keyword is in ``Lib/xml/dom/xmlbuilder.py``, -class ``DocumentLS``. ``async`` property is not documented, not -tested, and is not used anywhere. Methods that were likely supposed to -work with it -- ``_set_async()`` and ``_get_async()`` -- are not used -anywhere either. These methods will be deprecated in 3.5 and removed -in 3.6. +to define an ``async = False`` attribute for ``DocumentLS`` class. +There is no documentation or tests for it, it is not used anywhere else +in CPython. It is replaced with a getter, that raises a +``DeprecationWarning``, advising to use ``async_`` attribute instead. +'async' attribute is not documented and is not used in CPython code +base. Grammar Updates -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Fri May 1 10:37:06 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 01 May 2015 08:37:06 +0000 Subject: [Python-checkins] Daily reference leaks (6f6e78931875): sum=-1 Message-ID: <20150501083705.85175.42743@psf.io> results for 6f6e78931875 on branch "default" -------------------------------------------- test_collections leaked [0, -2, -2] references, sum=-4 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogv0pro4', '--timeout', '7200'] From solipsis at pitrou.net Sat May 2 10:36:14 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 02 May 2015 08:36:14 +0000 Subject: [Python-checkins] Daily reference leaks (6f6e78931875): sum=3 Message-ID: <20150502083614.1919.49656@psf.io> results for 6f6e78931875 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog4Wy1hU', '--timeout', '7200'] From python-checkins at python.org Sat May 2 10:47:44 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 02 May 2015 08:47:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDYw?= =?utf-8?q?=3A_Made_logging=2EFormatter_documentation_a_little_clearer=2E?= Message-ID: <20150502084743.84494.44998@psf.io> https://hg.python.org/cpython/rev/88c141233d1e changeset: 95835:88c141233d1e branch: 3.4 parent: 95831:96e2c0101672 user: Vinay Sajip date: Sat May 02 09:46:05 2015 +0100 summary: Issue #24060: Made logging.Formatter documentation a little clearer. files: Doc/library/logging.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -481,7 +481,9 @@ responsible for converting a :class:`LogRecord` to (usually) a string which can be interpreted by either a human or an external system. The base :class:`Formatter` allows a formatting string to be specified. If none is -supplied, the default value of ``'%(message)s'`` is used. +supplied, the default value of ``'%(message)s'`` is used, which just includes +the message in the logging call. To have additional items of information in the +formatted output (such as a timestamp), keep reading. A Formatter can be initialized with a format string which makes use of knowledge of the :class:`LogRecord` attributes - such as the default value mentioned above -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 10:47:43 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 02 May 2015 08:47:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MDYw?= =?utf-8?q?=3A_Made_logging=2EFormatter_documentation_a_little_clearer=2E?= Message-ID: <20150502084743.1928.92752@psf.io> https://hg.python.org/cpython/rev/5ce760e2cc59 changeset: 95834:5ce760e2cc59 branch: 2.7 parent: 95832:c17e29454447 user: Vinay Sajip date: Sat May 02 09:42:24 2015 +0100 summary: Issue #24060: Made logging.Formatter documentation a little clearer. files: Doc/library/logging.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -440,7 +440,9 @@ responsible for converting a :class:`LogRecord` to (usually) a string which can be interpreted by either a human or an external system. The base :class:`Formatter` allows a formatting string to be specified. If none is -supplied, the default value of ``'%(message)s'`` is used. +supplied, the default value of ``'%(message)s'`` is used, which just includes +the message in the logging call. To have additional items of information in the +formatted output (such as a timestamp), keep reading. A Formatter can be initialized with a format string which makes use of knowledge of the :class:`LogRecord` attributes - such as the default value mentioned above -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 10:47:44 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 02 May 2015 08:47:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324060=3A_Merged_documentation_update_from_3=2E?= =?utf-8?q?4=2E?= Message-ID: <20150502084744.14350.64215@psf.io> https://hg.python.org/cpython/rev/1c72e9c1b3b4 changeset: 95836:1c72e9c1b3b4 parent: 95833:6f6e78931875 parent: 95835:88c141233d1e user: Vinay Sajip date: Sat May 02 09:47:28 2015 +0100 summary: Closes #24060: Merged documentation update from 3.4. files: Doc/library/logging.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -486,7 +486,9 @@ responsible for converting a :class:`LogRecord` to (usually) a string which can be interpreted by either a human or an external system. The base :class:`Formatter` allows a formatting string to be specified. If none is -supplied, the default value of ``'%(message)s'`` is used. +supplied, the default value of ``'%(message)s'`` is used, which just includes +the message in the logging call. To have additional items of information in the +formatted output (such as a timestamp), keep reading. A Formatter can be initialized with a format string which makes use of knowledge of the :class:`LogRecord` attributes - such as the default value mentioned above -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 18:25:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 02 May 2015 16:25:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_a_typo?= =?utf-8?q?=2E?= Message-ID: <20150502162521.1945.77698@psf.io> https://hg.python.org/cpython/rev/b53cfcfdfe47 changeset: 95837:b53cfcfdfe47 branch: 3.4 parent: 95835:88c141233d1e user: Serhiy Storchaka date: Sat May 02 19:24:41 2015 +0300 summary: Fixed a typo. files: Doc/c-api/object.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -203,7 +203,7 @@ i.e. contained in ``cls.__mro__``. Normally only class objects, i.e. instances of :class:`type` or a derived - class, are considered classes. However, objects can override this by haivng + class, are considered classes. However, objects can override this by having a :attr:`__bases__` attribute (which must be a tuple of base classes). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 18:25:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 02 May 2015 16:25:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_a_typo=2E?= Message-ID: <20150502162521.14364.4810@psf.io> https://hg.python.org/cpython/rev/82b48b408b04 changeset: 95838:82b48b408b04 parent: 95836:1c72e9c1b3b4 parent: 95837:b53cfcfdfe47 user: Serhiy Storchaka date: Sat May 02 19:25:02 2015 +0300 summary: Fixed a typo. files: Doc/c-api/object.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -203,7 +203,7 @@ i.e. contained in ``cls.__mro__``. Normally only class objects, i.e. instances of :class:`type` or a derived - class, are considered classes. However, objects can override this by haivng + class, are considered classes. However, objects can override this by having a :attr:`__bases__` attribute (which must be a tuple of base classes). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:07:42 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:07:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150502170742.84506.80978@psf.io> https://hg.python.org/cpython/rev/b61690ba9432 changeset: 95840:b61690ba9432 parent: 95838:82b48b408b04 parent: 95839:813854f49f9d user: Raymond Hettinger date: Sat May 02 10:07:08 2015 -0700 summary: merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:07:42 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:07:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWVzICMyNDA5?= =?utf-8?q?9=2C_=2324100=2C_and_=2324101=3A_Fix_free-after-use_bug_in_heap?= =?utf-8?q?q=2E?= Message-ID: <20150502170742.76619.84465@psf.io> https://hg.python.org/cpython/rev/813854f49f9d changeset: 95839:813854f49f9d branch: 3.4 parent: 95837:b53cfcfdfe47 user: Raymond Hettinger date: Sat May 02 10:00:22 2015 -0700 summary: Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq. files: Misc/NEWS | 3 + Modules/_heapqmodule.c | 73 +++++++++-------------------- 2 files changed, 25 insertions(+), 51 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. +- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup + and siftdown functions. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -11,10 +11,9 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent, *olditem; + PyObject *newitem, *parent; + Py_ssize_t parentpos, size; int cmp; - Py_ssize_t parentpos; - Py_ssize_t size; assert(PyList_Check(heap)); size = PyList_GET_SIZE(heap); @@ -23,39 +22,28 @@ return -1; } - newitem = PyList_GET_ITEM(heap, pos); - Py_INCREF(newitem); /* Follow the path to the root, moving parents down until finding a place newitem fits. */ - while (pos > startpos){ + newitem = PyList_GET_ITEM(heap, pos); + while (pos > startpos) { parentpos = (pos - 1) >> 1; parent = PyList_GET_ITEM(heap, parentpos); cmp = PyObject_RichCompareBool(newitem, parent, Py_LT); - if (cmp == -1) { - Py_DECREF(newitem); + if (cmp == -1) return -1; - } if (size != PyList_GET_SIZE(heap)) { - Py_DECREF(newitem); PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); return -1; } if (cmp == 0) break; - Py_INCREF(parent); - olditem = PyList_GET_ITEM(heap, pos); + parent = PyList_GET_ITEM(heap, parentpos); + newitem = PyList_GET_ITEM(heap, pos); + PyList_SET_ITEM(heap, parentpos, newitem); PyList_SET_ITEM(heap, pos, parent); - Py_DECREF(olditem); pos = parentpos; - if (size != PyList_GET_SIZE(heap)) { - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; - } } - Py_DECREF(PyList_GET_ITEM(heap, pos)); - PyList_SET_ITEM(heap, pos, newitem); return 0; } @@ -63,20 +51,16 @@ _siftup(PyListObject *heap, Py_ssize_t pos) { Py_ssize_t startpos, endpos, childpos, rightpos, limit; + PyObject *tmp1, *tmp2; int cmp; - PyObject *newitem, *tmp, *olditem; - Py_ssize_t size; assert(PyList_Check(heap)); - size = PyList_GET_SIZE(heap); - endpos = size; + endpos = PyList_GET_SIZE(heap); startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } - newitem = PyList_GET_ITEM(heap, pos); - Py_INCREF(newitem); /* Bubble up the smaller child until hitting a leaf. */ limit = endpos / 2; /* smallest pos that has no child */ @@ -89,37 +73,24 @@ PyList_GET_ITEM(heap, childpos), PyList_GET_ITEM(heap, rightpos), Py_LT); - if (cmp == -1) { - Py_DECREF(newitem); + if (cmp == -1) + return -1; + if (cmp == 0) + childpos = rightpos; + if (endpos != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); return -1; } - if (cmp == 0) - childpos = rightpos; - } - if (size != PyList_GET_SIZE(heap)) { - Py_DECREF(newitem); - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; } /* Move the smaller child up. */ - tmp = PyList_GET_ITEM(heap, childpos); - Py_INCREF(tmp); - olditem = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, pos, tmp); - Py_DECREF(olditem); + tmp1 = PyList_GET_ITEM(heap, childpos); + tmp2 = PyList_GET_ITEM(heap, pos); + PyList_SET_ITEM(heap, childpos, tmp2); + PyList_SET_ITEM(heap, pos, tmp1); pos = childpos; - if (size != PyList_GET_SIZE(heap)) { - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; - } } - - /* The leaf at pos is empty now. Put newitem there, and bubble - it up to its final resting place (by sifting its parents down). */ - Py_DECREF(PyList_GET_ITEM(heap, pos)); - PyList_SET_ITEM(heap, pos, newitem); + /* Bubble it up to its final resting place (by sifting its parents down). */ return _siftdown(heap, startpos, pos); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:27:04 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:27:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWVzICMyNDA5?= =?utf-8?q?9=2C_=2324100=2C_and_=2324101=3A_Fix_free-after-use_bug_in_heap?= =?utf-8?q?q=2E?= Message-ID: <20150502172704.98663.63252@psf.io> https://hg.python.org/cpython/rev/d356e68de236 changeset: 95841:d356e68de236 branch: 2.7 parent: 95834:5ce760e2cc59 user: Raymond Hettinger date: Sat May 02 10:26:57 2015 -0700 summary: Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq. files: Misc/NEWS | 3 + Modules/_heapqmodule.c | 73 +++++++++-------------------- 2 files changed, 25 insertions(+), 51 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,9 @@ - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. +- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup + and siftdown functions. + - Issue #23842: os.major(), os.minor() and os.makedev() now support ints again. - Issue #23811: Add missing newline to the PyCompileError error message. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -35,10 +35,9 @@ static int _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent, *olditem; + PyObject *newitem, *parent; + Py_ssize_t parentpos, size; int cmp; - Py_ssize_t parentpos; - Py_ssize_t size; assert(PyList_Check(heap)); size = PyList_GET_SIZE(heap); @@ -47,39 +46,28 @@ return -1; } - newitem = PyList_GET_ITEM(heap, pos); - Py_INCREF(newitem); /* Follow the path to the root, moving parents down until finding a place newitem fits. */ - while (pos > startpos){ + newitem = PyList_GET_ITEM(heap, pos); + while (pos > startpos) { parentpos = (pos - 1) >> 1; parent = PyList_GET_ITEM(heap, parentpos); cmp = cmp_lt(newitem, parent); - if (cmp == -1) { - Py_DECREF(newitem); + if (cmp == -1) return -1; - } if (size != PyList_GET_SIZE(heap)) { - Py_DECREF(newitem); PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); return -1; } if (cmp == 0) break; - Py_INCREF(parent); - olditem = PyList_GET_ITEM(heap, pos); + parent = PyList_GET_ITEM(heap, parentpos); + newitem = PyList_GET_ITEM(heap, pos); + PyList_SET_ITEM(heap, parentpos, newitem); PyList_SET_ITEM(heap, pos, parent); - Py_DECREF(olditem); pos = parentpos; - if (size != PyList_GET_SIZE(heap)) { - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; - } } - Py_DECREF(PyList_GET_ITEM(heap, pos)); - PyList_SET_ITEM(heap, pos, newitem); return 0; } @@ -87,20 +75,16 @@ _siftup(PyListObject *heap, Py_ssize_t pos) { Py_ssize_t startpos, endpos, childpos, rightpos, limit; + PyObject *tmp1, *tmp2; int cmp; - PyObject *newitem, *tmp, *olditem; - Py_ssize_t size; assert(PyList_Check(heap)); - size = PyList_GET_SIZE(heap); - endpos = size; + endpos = PyList_GET_SIZE(heap); startpos = pos; if (pos >= endpos) { PyErr_SetString(PyExc_IndexError, "index out of range"); return -1; } - newitem = PyList_GET_ITEM(heap, pos); - Py_INCREF(newitem); /* Bubble up the smaller child until hitting a leaf. */ limit = endpos / 2; /* smallest pos that has no child */ @@ -112,37 +96,24 @@ cmp = cmp_lt( PyList_GET_ITEM(heap, childpos), PyList_GET_ITEM(heap, rightpos)); - if (cmp == -1) { - Py_DECREF(newitem); + if (cmp == -1) + return -1; + if (cmp == 0) + childpos = rightpos; + if (endpos != PyList_GET_SIZE(heap)) { + PyErr_SetString(PyExc_RuntimeError, + "list changed size during iteration"); return -1; } - if (cmp == 0) - childpos = rightpos; - } - if (size != PyList_GET_SIZE(heap)) { - Py_DECREF(newitem); - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; } /* Move the smaller child up. */ - tmp = PyList_GET_ITEM(heap, childpos); - Py_INCREF(tmp); - olditem = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, pos, tmp); - Py_DECREF(olditem); + tmp1 = PyList_GET_ITEM(heap, childpos); + tmp2 = PyList_GET_ITEM(heap, pos); + PyList_SET_ITEM(heap, childpos, tmp2); + PyList_SET_ITEM(heap, pos, tmp1); pos = childpos; - if (size != PyList_GET_SIZE(heap)) { - PyErr_SetString(PyExc_RuntimeError, - "list changed size during iteration"); - return -1; - } } - - /* The leaf at pos is empty now. Put newitem there, and bubble - it up to its final resting place (by sifting its parents down). */ - Py_DECREF(PyList_GET_ITEM(heap, pos)); - PyList_SET_ITEM(heap, pos, newitem); + /* Bubble it up to its final resting place (by sifting its parents down). */ return _siftdown(heap, startpos, pos); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:45:41 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:45:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Defer_deleted_?= =?utf-8?q?item_decref_until_after_the_deque_is_restored_to_a_consistent?= Message-ID: <20150502174541.11940.57081@psf.io> https://hg.python.org/cpython/rev/2d26f0f92b11 changeset: 95842:2d26f0f92b11 branch: 3.4 parent: 95839:813854f49f9d user: Raymond Hettinger date: Sat May 02 10:44:17 2015 -0700 summary: Defer deleted item decref until after the deque is restored to a consistent state. files: Misc/NEWS | 4 ++++ Modules/_collectionsmodule.c | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,10 @@ - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup and siftdown functions. +- Backport collections.deque fixes from Python 3.5. Prevents reentrant badness + during deletion by deferring the decref until the container has been restored + to a consistent state. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -698,9 +698,9 @@ if (cmp > 0) { PyObject *tgt = deque_popleft(deque, NULL); assert (tgt != NULL); + if (_deque_rotate(deque, i)) + return NULL; Py_DECREF(tgt); - if (_deque_rotate(deque, i) == -1) - return NULL; Py_RETURN_NONE; } else if (cmp < 0) { @@ -781,16 +781,16 @@ deque_del_item(dequeobject *deque, Py_ssize_t i) { PyObject *item; + int rv; assert (i >= 0 && i < Py_SIZE(deque)); - if (_deque_rotate(deque, -i) == -1) + if (_deque_rotate(deque, -i)) return -1; - item = deque_popleft(deque, NULL); + rv = _deque_rotate(deque, i); assert (item != NULL); Py_DECREF(item); - - return _deque_rotate(deque, i); + return rv; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:45:41 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:45:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150502174541.98679.66754@psf.io> https://hg.python.org/cpython/rev/4121966ec301 changeset: 95843:4121966ec301 parent: 95840:b61690ba9432 parent: 95842:2d26f0f92b11 user: Raymond Hettinger date: Sat May 02 10:45:21 2015 -0700 summary: merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 19:53:33 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 02 May 2015 17:53:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Defer_deleted_?= =?utf-8?q?item_decref_until_after_the_deque_is_restored_to_a_consistent?= Message-ID: <20150502175333.76598.76895@psf.io> https://hg.python.org/cpython/rev/fb6c2fbbde34 changeset: 95844:fb6c2fbbde34 branch: 2.7 parent: 95841:d356e68de236 user: Raymond Hettinger date: Sat May 02 10:53:27 2015 -0700 summary: Defer deleted item decref until after the deque is restored to a consistent state. files: Misc/NEWS | 4 ++++ Modules/_collectionsmodule.c | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,10 @@ - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup and siftdown functions. +- Backport collections.deque fixes from Python 3.5. Prevents reentrant badness + during deletion by deferring the decref until the container has been restored + to a consistent state. + - Issue #23842: os.major(), os.minor() and os.makedev() now support ints again. - Issue #23811: Add missing newline to the PyCompileError error message. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -623,9 +623,9 @@ if (cmp > 0) { PyObject *tgt = deque_popleft(deque, NULL); assert (tgt != NULL); + if (_deque_rotate(deque, i)) + return NULL; Py_DECREF(tgt); - if (_deque_rotate(deque, i) == -1) - return NULL; Py_RETURN_NONE; } else if (cmp < 0) { @@ -706,16 +706,16 @@ deque_del_item(dequeobject *deque, Py_ssize_t i) { PyObject *item; + int rv; - assert (i >= 0 && i < deque->len); - if (_deque_rotate(deque, -i) == -1) + assert (i >= 0 && i < Py_SIZE(deque)); + if (_deque_rotate(deque, -i)) return -1; - item = deque_popleft(deque, NULL); + rv = _deque_rotate(deque, i); assert (item != NULL); Py_DECREF(item); - - return _deque_rotate(deque, i); + return rv; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:02:52 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:02:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzI0MDgxOiBSZW1v?= =?utf-8?q?ve_obsolete_caveat_from_import_docs=2E?= Message-ID: <20150502190252.25425.50659@psf.io> https://hg.python.org/cpython/rev/3cdeafd18e61 changeset: 95845:3cdeafd18e61 branch: 3.4 parent: 95842:2d26f0f92b11 user: R David Murray date: Sat May 02 14:57:54 2015 -0400 summary: #24081: Remove obsolete caveat from import docs. Per Eric Snow's research, this changed in Python 2.4 in changeset 331e60d8ce, but these docs were not updated. Patch by Peter Viktorin. files: Doc/library/imp.rst | 6 ------ Doc/library/importlib.rst | 6 ------ 2 files changed, 0 insertions(+), 12 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -149,12 +149,6 @@ There are a number of other caveats: - If a module is syntactically correct but its initialization fails, the first - :keyword:`import` statement for it does not bind its name locally, but does - store a (partially initialized) module object in ``sys.modules``. To reload the - module you must first :keyword:`import` it again (this will bind the name to the - partially initialized module object) before you can :func:`reload` it. - When a module is reloaded, its dictionary (containing the module's global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a module diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -152,12 +152,6 @@ There are a number of other caveats: - If a module is syntactically correct but its initialization fails, the first - :keyword:`import` statement for it does not bind its name locally, but does - store a (partially initialized) module object in ``sys.modules``. To reload - the module you must first :keyword:`import` it again (this will bind the name - to the partially initialized module object) before you can :func:`reload` it. - When a module is reloaded, its dictionary (containing the module's global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:02:54 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:02:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzI0MDgxOiBSZW1v?= =?utf-8?q?ve_obsolete_caveat_from_import_docs=2E?= Message-ID: <20150502190252.14366.49875@psf.io> https://hg.python.org/cpython/rev/fd1549dd8065 changeset: 95847:fd1549dd8065 branch: 2.7 parent: 95844:fb6c2fbbde34 user: R David Murray date: Sat May 02 15:02:30 2015 -0400 summary: #24081: Remove obsolete caveat from import docs. Per Eric Snow's research, this changed in Python 2.4 in changeset 331e60d8ce, but these docs were not updated. files: Doc/library/functions.rst | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1178,12 +1178,6 @@ There are a number of other caveats: - If a module is syntactically correct but its initialization fails, the first - :keyword:`import` statement for it does not bind its name locally, but does - store a (partially initialized) module object in ``sys.modules``. To reload the - module you must first :keyword:`import` it again (this will bind the name to the - partially initialized module object) before you can :func:`reload` it. - When a module is reloaded, its dictionary (containing the module's global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a module -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:02:54 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:02:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2324081=3A_Remove_obsolete_caveat_from_import_?= =?utf-8?q?docs=2E?= Message-ID: <20150502190252.98663.11960@psf.io> https://hg.python.org/cpython/rev/d57e0c6d292d changeset: 95846:d57e0c6d292d parent: 95843:4121966ec301 parent: 95845:3cdeafd18e61 user: R David Murray date: Sat May 02 14:58:32 2015 -0400 summary: Merge: #24081: Remove obsolete caveat from import docs. files: Doc/library/imp.rst | 6 ------ Doc/library/importlib.rst | 6 ------ 2 files changed, 0 insertions(+), 12 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -149,12 +149,6 @@ There are a number of other caveats: - If a module is syntactically correct but its initialization fails, the first - :keyword:`import` statement for it does not bind its name locally, but does - store a (partially initialized) module object in ``sys.modules``. To reload the - module you must first :keyword:`import` it again (this will bind the name to the - partially initialized module object) before you can :func:`reload` it. - When a module is reloaded, its dictionary (containing the module's global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a module diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -159,12 +159,6 @@ There are a number of other caveats: - If a module is syntactically correct but its initialization fails, the first - :keyword:`import` statement for it does not bind its name locally, but does - store a (partially initialized) module object in ``sys.modules``. To reload - the module you must first :keyword:`import` it again (this will bind the name - to the partially initialized module object) before you can :func:`reload` it. - When a module is reloaded, its dictionary (containing the module's global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:09:46 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:09:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2324108=3A_Update_fnmatch=2Etranslate_example_?= =?utf-8?q?to_show_correct_output=2E?= Message-ID: <20150502190946.25437.49356@psf.io> https://hg.python.org/cpython/rev/cc6aed8ecb0d changeset: 95849:cc6aed8ecb0d parent: 95846:d57e0c6d292d parent: 95848:c5c65ef84a77 user: R David Murray date: Sat May 02 15:08:50 2015 -0400 summary: Merge: #24108: Update fnmatch.translate example to show correct output. files: Doc/library/fnmatch.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -83,7 +83,7 @@ >>> >>> regex = fnmatch.translate('*.txt') >>> regex - '.*\\.txt$' + '.*\\.txt\\Z(?ms)' >>> reobj = re.compile(regex) >>> reobj.match('foobar.txt') <_sre.SRE_Match object; span=(0, 10), match='foobar.txt'> -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:09:46 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:09:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzI0MTA4OiBVcGRh?= =?utf-8?q?te_fnmatch=2Etranslate_example_to_show_correct_output=2E?= Message-ID: <20150502190946.8133.14874@psf.io> https://hg.python.org/cpython/rev/c5c65ef84a77 changeset: 95848:c5c65ef84a77 branch: 3.4 parent: 95845:3cdeafd18e61 user: R David Murray date: Sat May 02 15:08:22 2015 -0400 summary: #24108: Update fnmatch.translate example to show correct output. Patch by Merlijn van Deen. files: Doc/library/fnmatch.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -83,7 +83,7 @@ >>> >>> regex = fnmatch.translate('*.txt') >>> regex - '.*\\.txt$' + '.*\\.txt\\Z(?ms)' >>> reobj = re.compile(regex) >>> reobj.match('foobar.txt') <_sre.SRE_Match object; span=(0, 10), match='foobar.txt'> -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 2 21:09:46 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 02 May 2015 19:09:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzI0MTA4OiBVcGRh?= =?utf-8?q?te_fnmatch=2Etranslate_example_to_show_correct_output=2E?= Message-ID: <20150502190946.84498.64856@psf.io> https://hg.python.org/cpython/rev/5d356223f075 changeset: 95850:5d356223f075 branch: 2.7 parent: 95847:fd1549dd8065 user: R David Murray date: Sat May 02 15:09:22 2015 -0400 summary: #24108: Update fnmatch.translate example to show correct output. Patch by Merlijn van Deen. files: Doc/library/fnmatch.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -85,7 +85,7 @@ >>> >>> regex = fnmatch.translate('*.txt') >>> regex - '.*\\.txt$' + '.*\\.txt\\Z(?ms)' >>> reobj = re.compile(regex) >>> reobj.match('foobar.txt') <_sre.SRE_Match object at 0x...> -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 00:33:33 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 02 May 2015 22:33:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_Windows_installer_f?= =?utf-8?q?or_new_CRT_version=2E?= Message-ID: <20150502223333.8135.14837@psf.io> https://hg.python.org/cpython/rev/b232f29efe1a changeset: 95851:b232f29efe1a parent: 95849:cc6aed8ecb0d user: Steve Dower date: Sat May 02 15:22:51 2015 -0700 summary: Update Windows installer for new CRT version. files: Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -2343,7 +2343,7 @@ return FALSE; } - // Check whether at least CRT v10.0.9920.0 is available. + // Check whether at least CRT v10.0.9924.0 is available. // It should only be installed as a Windows Update package, which means // we don't need to worry about 32-bit/64-bit. // However, since the WU package does not include vcruntime140.dll, we @@ -2373,7 +2373,7 @@ BOOL result = FALSE; if (VerQueryValueW(pData, L"\\", (LPVOID*)&ffi, &cb) && - ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x26C00000) { + ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x26C40000) { result = TRUE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 00:33:33 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 02 May 2015 22:33:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixes_Python_failing_to_ru?= =?utf-8?q?n_during_Windows_release_build?= Message-ID: <20150502223333.1926.60570@psf.io> https://hg.python.org/cpython/rev/8cd7187b2815 changeset: 95852:8cd7187b2815 user: Steve Dower date: Sat May 02 15:23:27 2015 -0700 summary: Fixes Python failing to run during Windows release build files: Tools/msi/msi.props | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -147,7 +147,9 @@ <_GenerateCommand>import uuid; print('\n'.join('{}={}'.format(i, uuid.uuid5(uuid.UUID('c8d9733e-a70c-43ff-ab0c-e26456f11083'), '$(ReleaseUri)' + j)) for i,j in [$(_Uuids.Replace(`"`,`'`))])) - + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 00:33:33 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 02 May 2015 22:33:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Makes_embedded_distributio?= =?utf-8?q?n_a_plain_ZIP_file_and_corrects_pyd_exclusion=2E?= Message-ID: <20150502223333.14358.98274@psf.io> https://hg.python.org/cpython/rev/0b4f582c6e80 changeset: 95853:0b4f582c6e80 user: Steve Dower date: Sat May 02 15:32:14 2015 -0700 summary: Makes embedded distribution a plain ZIP file and corrects pyd exclusion. files: Tools/msi/make_zip.proj | 3 ++- Tools/msi/make_zip.py | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj --- a/Tools/msi/make_zip.proj +++ b/Tools/msi/make_zip.proj @@ -9,8 +9,9 @@ + false python-$(PythonVersion)-embed-$(ArchName) - .exe + .zip $(OutputPath)\en-us\$(TargetName)$(TargetExt) "$(PythonExe)" "$(MSBuildThisFileDirectory)\make_zip.py" $(Arguments) -e -o "$(TargetPath)" -t "$(IntermediateOutputPath)\zip_$(ArchName)" -a $(ArchName) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -14,7 +14,19 @@ PYTHON_DLL_RE = re.compile(r'python\d\d?\.dll$', re.IGNORECASE) def is_not_debug(p): - return not DEBUG_RE.search(p.name) and not TKTCL_RE.search(p.name) + if DEBUG_RE.search(p.name): + return False + + if TKTCL_RE.search(p.name): + return False + + return p.name.lower() not in { + '_ctypes_test.pyd', + '_testbuffer.pyd', + '_testcapi.pyd', + '_testimportmultiple.pyd', + 'xxlimited.pyd', + } def is_not_debug_or_python(p): return is_not_debug(p) and not PYTHON_DLL_RE.search(p.name) @@ -31,14 +43,6 @@ return True suffix = p.suffix.lower() - if suffix == '.pyd': - return name not in { - '_ctypes_test.pyd', - '_testbuffer.pyd', - '_testcapi.pyd', - '_testimportmultiple.pyd', - 'xxlimited.pyd', - } return suffix not in {'.pyc', '.pyo'} def include_in_tools(p): @@ -153,8 +157,7 @@ subprocess.check_call([ str(rar), "a", - "-m5", "-ed", "-ep1", "-s", "-r", - "-sfxwincon.sfx", + "-ed", "-ep1", "-s", "-r", str(out), str(temp / '*') ]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 03:23:55 2015 From: python-checkins at python.org (eric.snow) Date: Sun, 03 May 2015 01:23:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323911=3A_Move_pat?= =?utf-8?q?h-based_bootstrap_code_to_a_separate_frozen_module=2E?= Message-ID: <20150503012355.76614.44637@psf.io> https://hg.python.org/cpython/rev/02e3bf65b2f8 changeset: 95854:02e3bf65b2f8 user: Eric Snow date: Sat May 02 19:15:18 2015 -0600 summary: Issue #23911: Move path-based bootstrap code to a separate frozen module. files: Lib/ctypes/test/test_values.py | 19 +- Lib/imp.py | 3 +- Lib/importlib/__init__.py | 20 +- Lib/importlib/_bootstrap.py | 1343 +-- Lib/importlib/_bootstrap_external.py | 1462 ++ Lib/importlib/abc.py | 24 +- Lib/importlib/machinery.py | 18 +- Lib/importlib/util.py | 12 +- Lib/modulefinder.py | 4 +- Lib/py_compile.py | 8 +- Lib/pydoc.py | 5 +- Lib/runpy.py | 2 +- Lib/site.py | 4 +- Lib/test/test_import/__init__.py | 20 +- Lib/test/test_importlib/extension/test_case_sensitivity.py | 6 +- Lib/test/test_importlib/import_/test_path.py | 2 +- Lib/test/test_importlib/source/test_case_sensitivity.py | 4 +- Lib/test/test_site.py | 6 +- Makefile.pre.in | 7 +- Misc/NEWS | 3 + Programs/_freeze_importlib.c | 20 +- Python/frozen.c | 3 + Python/import.c | 36 +- Python/importlib.h | 6229 +++------ Python/importlib_external.h | 2633 ++++ Python/pythonrun.c | 9 +- Tools/freeze/freeze.py | 4 +- 27 files changed, 6193 insertions(+), 5713 deletions(-) diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py --- a/Lib/ctypes/test/test_values.py +++ b/Lib/ctypes/test/test_values.py @@ -59,8 +59,13 @@ items = [] # _frozen_importlib changes size whenever importlib._bootstrap # changes, so it gets a special case. We should make sure it's - # found, but don't worry about its size too much. - _fzn_implib_seen = False + # found, but don't worry about its size too much. The same + # applies to _frozen_importlib_external. + bootstrap_seen = [] + bootstrap_expected = ( + b'_frozen_importlib', + b'_frozen_importlib_external', + ) for entry in ft: # This is dangerous. We *can* iterate over a pointer, but # the loop will not terminate (maybe with an access @@ -68,10 +73,10 @@ if entry.name is None: break - if entry.name == b'_frozen_importlib': - _fzn_implib_seen = True + if entry.name in bootstrap_expected: + bootstrap_seen.append(entry.name) self.assertTrue(entry.size, - "_frozen_importlib was reported as having no size") + "{} was reported as having no size".format(entry.name)) continue items.append((entry.name, entry.size)) @@ -81,8 +86,8 @@ ] self.assertEqual(items, expected) - self.assertTrue(_fzn_implib_seen, - "_frozen_importlib wasn't found in PyImport_FrozenModules") + self.assertEqual(sorted(bootstrap_seen), bootstrap_expected, + "frozen bootstrap modules did not match PyImport_FrozenModules") from ctypes import _pointer_type_cache del _pointer_type_cache[struct_frozen] diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -16,7 +16,8 @@ # Platform doesn't support dynamic loading. load_dynamic = None -from importlib._bootstrap import SourcelessFileLoader, _ERR_MSG, _exec, _load +from importlib._bootstrap import _ERR_MSG, _exec, _load +from importlib._bootstrap_external import SourcelessFileLoader from importlib import machinery from importlib import util diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -30,9 +30,25 @@ pass sys.modules['importlib._bootstrap'] = _bootstrap +try: + import _frozen_importlib_external as _bootstrap_external +except ImportError: + from . import _bootstrap_external + _bootstrap_external._setup(_bootstrap) +else: + _bootstrap_external.__name__ = 'importlib._bootstrap_external' + _bootstrap_external.__package__ = 'importlib' + try: + _bootstrap_external.__file__ = __file__.replace('__init__.py', '_bootstrap_external.py') + except NameError: + # __file__ is not guaranteed to be defined, e.g. if this code gets + # frozen by a tool like cx_Freeze. + pass + sys.modules['importlib._bootstrap_external'] = _bootstrap_external + # To simplify imports in test code -_w_long = _bootstrap._w_long -_r_long = _bootstrap._r_long +_w_long = _bootstrap_external._w_long +_r_long = _bootstrap_external._r_long # Fully bootstrapped at this point, import whatever you like, circular # dependencies and startup overhead minimisation permitting :) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -22,102 +22,6 @@ # Bootstrap-related code ###################################################### -_CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'darwin' - - -def _make_relax_case(): - if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): - def _relax_case(): - """True if filenames must be checked case-insensitively.""" - return b'PYTHONCASEOK' in _os.environ - else: - def _relax_case(): - """True if filenames must be checked case-insensitively.""" - return False - return _relax_case - - -def _w_long(x): - """Convert a 32-bit integer to little-endian.""" - return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little') - - -def _r_long(int_bytes): - """Convert 4 bytes in little-endian to an integer.""" - return int.from_bytes(int_bytes, 'little') - - -def _path_join(*path_parts): - """Replacement for os.path.join().""" - return path_sep.join([part.rstrip(path_separators) - for part in path_parts if part]) - - -def _path_split(path): - """Replacement for os.path.split().""" - if len(path_separators) == 1: - front, _, tail = path.rpartition(path_sep) - return front, tail - for x in reversed(path): - if x in path_separators: - front, tail = path.rsplit(x, maxsplit=1) - return front, tail - return '', path - - -def _path_stat(path): - """Stat the path. - - Made a separate function to make it easier to override in experiments - (e.g. cache stat results). - - """ - return _os.stat(path) - - -def _path_is_mode_type(path, mode): - """Test whether the path is the specified mode type.""" - try: - stat_info = _path_stat(path) - except OSError: - return False - return (stat_info.st_mode & 0o170000) == mode - - -def _path_isfile(path): - """Replacement for os.path.isfile.""" - return _path_is_mode_type(path, 0o100000) - - -def _path_isdir(path): - """Replacement for os.path.isdir.""" - if not path: - path = _os.getcwd() - return _path_is_mode_type(path, 0o040000) - - -def _write_atomic(path, data, mode=0o666): - """Best-effort function to write data to a path atomically. - Be prepared to handle a FileExistsError if concurrent writing of the - temporary file is attempted.""" - # id() is used to generate a pseudo-random filename. - path_tmp = '{}.{}'.format(path, id(path)) - fd = _os.open(path_tmp, - _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, mode & 0o666) - try: - # We first write data to a temporary file, and then use os.replace() to - # perform an atomic rename. - with _io.FileIO(fd, 'wb') as file: - file.write(data) - _os.replace(path_tmp, path) - except OSError: - try: - _os.unlink(path_tmp) - except OSError: - pass - raise - - def _wrap(new, old): """Simple substitute for functools.update_wrapper.""" for replace in ['__module__', '__name__', '__qualname__', '__doc__']: @@ -130,10 +34,6 @@ return type(sys)(name) -_code_type = type(_wrap.__code__) - - - class _ManageReload: """Manages the possible clean-up of sys.modules for load_module().""" @@ -309,7 +209,6 @@ lock.release() # Frame stripping magic ############################################### - def _call_with_frames_removed(f, *args, **kwds): """remove_importlib_frames in import.c will always remove sequences of importlib frames that end with a call to this function @@ -321,230 +220,6 @@ return f(*args, **kwds) -# Finder/loader utility code ############################################### - -# Magic word to reject .pyc files generated by other Python versions. -# It should change for each incompatible change to the bytecode. -# -# The value of CR and LF is incorporated so if you ever read or write -# a .pyc file in text mode the magic number will be wrong; also, the -# Apple MPW compiler swaps their values, botching string constants. -# -# The magic numbers must be spaced apart at least 2 values, as the -# -U interpeter flag will cause MAGIC+1 being used. They have been -# odd numbers for some time now. -# -# There were a variety of old schemes for setting the magic number. -# The current working scheme is to increment the previous value by -# 10. -# -# Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic -# number also includes a new "magic tag", i.e. a human readable string used -# to represent the magic number in __pycache__ directories. When you change -# the magic number, you must also set a new unique magic tag. Generally this -# can be named after the Python major version of the magic number bump, but -# it can really be anything, as long as it's different than anything else -# that's come before. The tags are included in the following table, starting -# with Python 3.2a0. -# -# Known values: -# Python 1.5: 20121 -# Python 1.5.1: 20121 -# Python 1.5.2: 20121 -# Python 1.6: 50428 -# Python 2.0: 50823 -# Python 2.0.1: 50823 -# Python 2.1: 60202 -# Python 2.1.1: 60202 -# Python 2.1.2: 60202 -# Python 2.2: 60717 -# Python 2.3a0: 62011 -# Python 2.3a0: 62021 -# Python 2.3a0: 62011 (!) -# Python 2.4a0: 62041 -# Python 2.4a3: 62051 -# Python 2.4b1: 62061 -# Python 2.5a0: 62071 -# Python 2.5a0: 62081 (ast-branch) -# Python 2.5a0: 62091 (with) -# Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) -# Python 2.5b3: 62101 (fix wrong code: for x, in ...) -# Python 2.5b3: 62111 (fix wrong code: x += yield) -# Python 2.5c1: 62121 (fix wrong lnotab with for loops and -# storing constants that should have been removed) -# Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) -# Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) -# Python 2.6a1: 62161 (WITH_CLEANUP optimization) -# Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND) -# Python 2.7a0: 62181 (optimize conditional branches: -# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) -# Python 2.7a0 62191 (introduce SETUP_WITH) -# Python 2.7a0 62201 (introduce BUILD_SET) -# Python 2.7a0 62211 (introduce MAP_ADD and SET_ADD) -# Python 3000: 3000 -# 3010 (removed UNARY_CONVERT) -# 3020 (added BUILD_SET) -# 3030 (added keyword-only parameters) -# 3040 (added signature annotations) -# 3050 (print becomes a function) -# 3060 (PEP 3115 metaclass syntax) -# 3061 (string literals become unicode) -# 3071 (PEP 3109 raise changes) -# 3081 (PEP 3137 make __file__ and __name__ unicode) -# 3091 (kill str8 interning) -# 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) -# tag: cpython-32 -# Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) -# 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.4a1 3250 (evaluate positional default arguments before -# keyword-only defaults) -# 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) -# 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) -# -# MAGIC must change whenever the bytecode emitted by the compiler may no -# longer be understood by older implementations of the eval loop (usually -# due to the addition of new opcodes). - -MAGIC_NUMBER = (3320).to_bytes(2, 'little') + b'\r\n' -_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c - -_PYCACHE = '__pycache__' -_OPT = 'opt-' - -SOURCE_SUFFIXES = ['.py'] # _setup() adds .pyw as needed. - -BYTECODE_SUFFIXES = ['.pyc'] -# Deprecated. -DEBUG_BYTECODE_SUFFIXES = OPTIMIZED_BYTECODE_SUFFIXES = BYTECODE_SUFFIXES - -def cache_from_source(path, debug_override=None, *, optimization=None): - """Given the path to a .py file, return the path to its .pyc file. - - The .py file does not need to exist; this simply returns the path to the - .pyc file calculated as if the .py file were imported. - - The 'optimization' parameter controls the presumed optimization level of - the bytecode file. If 'optimization' is not None, the string representation - of the argument is taken and verified to be alphanumeric (else ValueError - is raised). - - The debug_override parameter is deprecated. If debug_override is not None, - a True value is the same as setting 'optimization' to the empty string - while a False value is equivalent to setting 'optimization' to '1'. - - If sys.implementation.cache_tag is None then NotImplementedError is raised. - - """ - if debug_override is not None: - _warnings.warn('the debug_override parameter is deprecated; use ' - "'optimization' instead", DeprecationWarning) - if optimization is not None: - message = 'debug_override or optimization must be set to None' - raise TypeError(message) - optimization = '' if debug_override else 1 - head, tail = _path_split(path) - base, sep, rest = tail.rpartition('.') - tag = sys.implementation.cache_tag - if tag is None: - raise NotImplementedError('sys.implementation.cache_tag is None') - almost_filename = ''.join([(base if base else rest), sep, tag]) - if optimization is None: - if sys.flags.optimize == 0: - optimization = '' - else: - optimization = sys.flags.optimize - optimization = str(optimization) - if optimization != '': - if not optimization.isalnum(): - raise ValueError('{!r} is not alphanumeric'.format(optimization)) - almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization) - return _path_join(head, _PYCACHE, almost_filename + BYTECODE_SUFFIXES[0]) - - -def source_from_cache(path): - """Given the path to a .pyc. file, return the path to its .py file. - - The .pyc file does not need to exist; this simply returns the path to - the .py file calculated to correspond to the .pyc file. If path does - not conform to PEP 3147/488 format, ValueError will be raised. If - sys.implementation.cache_tag is None then NotImplementedError is raised. - - """ - if sys.implementation.cache_tag is None: - raise NotImplementedError('sys.implementation.cache_tag is None') - head, pycache_filename = _path_split(path) - head, pycache = _path_split(head) - if pycache != _PYCACHE: - raise ValueError('{} not bottom-level directory in ' - '{!r}'.format(_PYCACHE, path)) - dot_count = pycache_filename.count('.') - if dot_count not in {2, 3}: - raise ValueError('expected only 2 or 3 dots in ' - '{!r}'.format(pycache_filename)) - elif dot_count == 3: - optimization = pycache_filename.rsplit('.', 2)[-2] - if not optimization.startswith(_OPT): - raise ValueError("optimization portion of filename does not start " - "with {!r}".format(_OPT)) - opt_level = optimization[len(_OPT):] - if not opt_level.isalnum(): - raise ValueError("optimization level {!r} is not an alphanumeric " - "value".format(optimization)) - base_filename = pycache_filename.partition('.')[0] - return _path_join(head, base_filename + SOURCE_SUFFIXES[0]) - - -def _get_sourcefile(bytecode_path): - """Convert a bytecode file path to a source path (if possible). - - This function exists purely for backwards-compatibility for - PyImport_ExecCodeModuleWithFilenames() in the C API. - - """ - if len(bytecode_path) == 0: - return None - rest, _, extension = bytecode_path.rpartition('.') - if not rest or extension.lower()[-3:-1] != 'py': - return bytecode_path - try: - source_path = source_from_cache(bytecode_path) - except (NotImplementedError, ValueError): - source_path = bytecode_path[:-1] - return source_path if _path_isfile(source_path) else bytecode_path - - -def _calc_mode(path): - """Calculate the mode permissions for a bytecode file.""" - try: - mode = _path_stat(path).st_mode - except OSError: - mode = 0o666 - # We always ensure write access so we can update cached files - # later even when the source files are read-only on Windows (#6074) - mode |= 0o200 - return mode - - def _verbose_message(message, *args, verbosity=1): """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" if sys.flags.verbose >= verbosity: @@ -553,24 +228,6 @@ print(message.format(*args), file=sys.stderr) -def _check_name(method): - """Decorator to verify that the module being requested matches the one the - loader can handle. - - The first argument (self) must define _name which the second argument is - compared against. If the comparison fails then ImportError is raised. - - """ - def _check_name_wrapper(self, name=None, *args, **kwargs): - if name is None: - name = self.name - elif self.name != name: - raise ImportError('loader cannot handle %s' % name, name=name) - return method(self, name, *args, **kwargs) - _wrap(_check_name_wrapper, method) - return _check_name_wrapper - - def _requires_builtin(fxn): """Decorator to verify the named module is built-in.""" def _requires_builtin_wrapper(self, fullname): @@ -593,23 +250,6 @@ return _requires_frozen_wrapper -def _find_module_shim(self, fullname): - """Try to find a loader for the specified module by delegating to - self.find_loader(). - - This method is deprecated in favor of finder.find_spec(). - - """ - # Call find_loader(). If it returns a string (indicating this - # is a namespace package portion), generate a warning and - # return None. - loader, portions = self.find_loader(fullname) - if loader is None and len(portions): - msg = 'Not importing directory {}: missing __init__' - _warnings.warn(msg.format(portions[0]), ImportWarning) - return loader - - # Typically used by loader classes as a method replacement. def _load_module_shim(self, fullname): """Load the specified module into sys.modules and return it. @@ -625,96 +265,6 @@ else: return _load(spec) - -def _validate_bytecode_header(data, source_stats=None, name=None, path=None): - """Validate the header of the passed-in bytecode against source_stats (if - given) and returning the bytecode that can be compiled by compile(). - - All other arguments are used to enhance error reporting. - - ImportError is raised when the magic number is incorrect or the bytecode is - found to be stale. EOFError is raised when the data is found to be - truncated. - - """ - exc_details = {} - if name is not None: - exc_details['name'] = name - else: - # To prevent having to make all messages have a conditional name. - name = '' - if path is not None: - exc_details['path'] = path - magic = data[:4] - raw_timestamp = data[4:8] - raw_size = data[8:12] - if magic != MAGIC_NUMBER: - message = 'bad magic number in {!r}: {!r}'.format(name, magic) - _verbose_message(message) - raise ImportError(message, **exc_details) - elif len(raw_timestamp) != 4: - message = 'reached EOF while reading timestamp in {!r}'.format(name) - _verbose_message(message) - raise EOFError(message) - elif len(raw_size) != 4: - message = 'reached EOF while reading size of source in {!r}'.format(name) - _verbose_message(message) - raise EOFError(message) - if source_stats is not None: - try: - source_mtime = int(source_stats['mtime']) - except KeyError: - pass - else: - if _r_long(raw_timestamp) != source_mtime: - message = 'bytecode is stale for {!r}'.format(name) - _verbose_message(message) - raise ImportError(message, **exc_details) - try: - source_size = source_stats['size'] & 0xFFFFFFFF - except KeyError: - pass - else: - if _r_long(raw_size) != source_size: - raise ImportError('bytecode is stale for {!r}'.format(name), - **exc_details) - return data[12:] - - -def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): - """Compile bytecode as returned by _validate_bytecode_header().""" - code = marshal.loads(data) - if isinstance(code, _code_type): - _verbose_message('code object from {!r}', bytecode_path) - if source_path is not None: - _imp._fix_co_filename(code, source_path) - return code - else: - raise ImportError('Non-code object in {!r}'.format(bytecode_path), - name=name, path=bytecode_path) - -def _code_to_bytecode(code, mtime=0, source_size=0): - """Compile a code object into bytecode for writing out to a byte-compiled - file.""" - data = bytearray(MAGIC_NUMBER) - data.extend(_w_long(mtime)) - data.extend(_w_long(source_size)) - data.extend(marshal.dumps(code)) - return data - - -def decode_source(source_bytes): - """Decode bytes representing source code and return the string. - - Universal newline support is used in the decoding. - """ - import tokenize # To avoid bootstrap issues. - source_bytes_readline = _io.BytesIO(source_bytes).readline - encoding = tokenize.detect_encoding(source_bytes_readline) - newline_decoder = _io.IncrementalNewlineDecoder(None, True) - return newline_decoder.decode(source_bytes.decode(encoding[0])) - - # Module specifications ####################################################### def _module_repr(module): @@ -855,14 +405,8 @@ def cached(self): if self._cached is None: if self.origin is not None and self._set_fileattr: - filename = self.origin - if filename.endswith(tuple(SOURCE_SUFFIXES)): - try: - self._cached = cache_from_source(filename) - except NotImplementedError: - pass - elif filename.endswith(tuple(BYTECODE_SUFFIXES)): - self._cached = filename + import _frozen_importlib_external as _bootstrap_external # XXX yuck + self._cached = _bootstrap_external._get_cached(self.origin) return self._cached @cached.setter @@ -889,6 +433,7 @@ def spec_from_loader(name, loader, *, origin=None, is_package=None): """Return a module spec based on various loader methods.""" if hasattr(loader, 'get_filename'): + from ._bootstrap_external import spec_from_file_location # XXX yuck if is_package is None: return spec_from_file_location(name, loader=loader) search = [] if is_package else None @@ -911,70 +456,6 @@ _POPULATE = object() -def spec_from_file_location(name, location=None, *, loader=None, - submodule_search_locations=_POPULATE): - """Return a module spec based on a file location. - - To indicate that the module is a package, set - submodule_search_locations to a list of directory paths. An - empty list is sufficient, though its not otherwise useful to the - import system. - - The loader must take a spec as its only __init__() arg. - - """ - if location is None: - # The caller may simply want a partially populated location- - # oriented spec. So we set the location to a bogus value and - # fill in as much as we can. - location = '' - if hasattr(loader, 'get_filename'): - # ExecutionLoader - try: - location = loader.get_filename(name) - except ImportError: - pass - - # If the location is on the filesystem, but doesn't actually exist, - # we could return None here, indicating that the location is not - # valid. However, we don't have a good way of testing since an - # indirect location (e.g. a zip file or URL) will look like a - # non-existent file relative to the filesystem. - - spec = ModuleSpec(name, loader, origin=location) - spec._set_fileattr = True - - # Pick a loader if one wasn't provided. - if loader is None: - for loader_class, suffixes in _get_supported_file_loaders(): - if location.endswith(tuple(suffixes)): - loader = loader_class(name, location) - spec.loader = loader - break - else: - return None - - # Set submodule_search_paths appropriately. - if submodule_search_locations is _POPULATE: - # Check the loader. - if hasattr(loader, 'is_package'): - try: - is_package = loader.is_package(name) - except ImportError: - pass - else: - if is_package: - spec.submodule_search_locations = [] - else: - spec.submodule_search_locations = submodule_search_locations - if spec.submodule_search_locations == []: - if location: - dirname = _path_split(location)[0] - spec.submodule_search_locations.append(dirname) - - return spec - - def _spec_from_module(module, loader=None, origin=None): # This function is meant for use in _setup(). try: @@ -1035,6 +516,7 @@ if loader is None: # A backward compatibility hack. if spec.submodule_search_locations is not None: + from ._bootstrap_external import _NamespaceLoader # XXX yuck loader = _NamespaceLoader.__new__(_NamespaceLoader) loader._path = spec.submodule_search_locations try: @@ -1202,29 +684,6 @@ return _load_unlocked(spec) -def _fix_up_module(ns, name, pathname, cpathname=None): - # This function is used by PyImport_ExecCodeModuleObject(). - loader = ns.get('__loader__') - spec = ns.get('__spec__') - if not loader: - if spec: - loader = spec.loader - elif pathname == cpathname: - loader = SourcelessFileLoader(name, pathname) - else: - loader = SourceFileLoader(name, pathname) - if not spec: - spec = spec_from_file_location(name, pathname, loader=loader) - try: - ns['__spec__'] = spec - ns['__loader__'] = loader - ns['__file__'] = pathname - ns['__cached__'] = cpathname - except Exception: - # Not important enough to report. - pass - - # Loaders ##################################################################### class BuiltinImporter: @@ -1351,6 +810,7 @@ This method is deprecated. Use exec_module() instead. """ + from ._bootstrap_external import _load_module_shim # XXX yuck return _load_module_shim(cls, fullname) @classmethod @@ -1372,742 +832,6 @@ return _imp.is_frozen_package(fullname) -class WindowsRegistryFinder: - - """Meta path finder for modules declared in the Windows registry.""" - - REGISTRY_KEY = ( - 'Software\\Python\\PythonCore\\{sys_version}' - '\\Modules\\{fullname}') - REGISTRY_KEY_DEBUG = ( - 'Software\\Python\\PythonCore\\{sys_version}' - '\\Modules\\{fullname}\\Debug') - DEBUG_BUILD = False # Changed in _setup() - - @classmethod - def _open_registry(cls, key): - try: - return _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key) - except OSError: - return _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key) - - @classmethod - def _search_registry(cls, fullname): - if cls.DEBUG_BUILD: - registry_key = cls.REGISTRY_KEY_DEBUG - else: - registry_key = cls.REGISTRY_KEY - key = registry_key.format(fullname=fullname, - sys_version=sys.version[:3]) - try: - with cls._open_registry(key) as hkey: - filepath = _winreg.QueryValue(hkey, '') - except OSError: - return None - return filepath - - @classmethod - def find_spec(cls, fullname, path=None, target=None): - filepath = cls._search_registry(fullname) - if filepath is None: - return None - try: - _path_stat(filepath) - except OSError: - return None - for loader, suffixes in _get_supported_file_loaders(): - if filepath.endswith(tuple(suffixes)): - spec = spec_from_loader(fullname, loader(fullname, filepath), - origin=filepath) - return spec - - @classmethod - def find_module(cls, fullname, path=None): - """Find module named in the registry. - - This method is deprecated. Use exec_module() instead. - - """ - spec = cls.find_spec(fullname, path) - if spec is not None: - return spec.loader - else: - return None - - -class _LoaderBasics: - - """Base class of common code needed by both SourceLoader and - SourcelessFileLoader.""" - - def is_package(self, fullname): - """Concrete implementation of InspectLoader.is_package by checking if - the path returned by get_filename has a filename of '__init__.py'.""" - filename = _path_split(self.get_filename(fullname))[1] - filename_base = filename.rsplit('.', 1)[0] - tail_name = fullname.rpartition('.')[2] - return filename_base == '__init__' and tail_name != '__init__' - - def create_module(self, spec): - """Use default semantics for module creation.""" - - def exec_module(self, module): - """Execute the module.""" - code = self.get_code(module.__name__) - if code is None: - raise ImportError('cannot load module {!r} when get_code() ' - 'returns None'.format(module.__name__)) - _call_with_frames_removed(exec, code, module.__dict__) - - load_module = _load_module_shim - - -class SourceLoader(_LoaderBasics): - - def path_mtime(self, path): - """Optional method that returns the modification time (an int) for the - specified path, where path is a str. - - Raises IOError when the path cannot be handled. - """ - raise IOError - - def path_stats(self, path): - """Optional method returning a metadata dict for the specified path - to by the path (str). - Possible keys: - - 'mtime' (mandatory) is the numeric timestamp of last source - code modification; - - 'size' (optional) is the size in bytes of the source code. - - Implementing this method allows the loader to read bytecode files. - Raises IOError when the path cannot be handled. - """ - return {'mtime': self.path_mtime(path)} - - def _cache_bytecode(self, source_path, cache_path, data): - """Optional method which writes data (bytes) to a file path (a str). - - Implementing this method allows for the writing of bytecode files. - - The source path is needed in order to correctly transfer permissions - """ - # For backwards compatibility, we delegate to set_data() - return self.set_data(cache_path, data) - - def set_data(self, path, data): - """Optional method which writes data (bytes) to a file path (a str). - - Implementing this method allows for the writing of bytecode files. - """ - - - def get_source(self, fullname): - """Concrete implementation of InspectLoader.get_source.""" - path = self.get_filename(fullname) - try: - source_bytes = self.get_data(path) - except OSError as exc: - raise ImportError('source not available through get_data()', - name=fullname) from exc - return decode_source(source_bytes) - - def source_to_code(self, data, path, *, _optimize=-1): - """Return the code object compiled from source. - - The 'data' argument can be any object type that compile() supports. - """ - return _call_with_frames_removed(compile, data, path, 'exec', - dont_inherit=True, optimize=_optimize) - - def get_code(self, fullname): - """Concrete implementation of InspectLoader.get_code. - - Reading of bytecode requires path_stats to be implemented. To write - bytecode, set_data must also be implemented. - - """ - source_path = self.get_filename(fullname) - source_mtime = None - try: - bytecode_path = cache_from_source(source_path) - except NotImplementedError: - bytecode_path = None - else: - try: - st = self.path_stats(source_path) - except IOError: - pass - else: - source_mtime = int(st['mtime']) - try: - data = self.get_data(bytecode_path) - except OSError: - pass - else: - try: - bytes_data = _validate_bytecode_header(data, - source_stats=st, name=fullname, - path=bytecode_path) - except (ImportError, EOFError): - pass - else: - _verbose_message('{} matches {}', bytecode_path, - source_path) - return _compile_bytecode(bytes_data, name=fullname, - bytecode_path=bytecode_path, - source_path=source_path) - source_bytes = self.get_data(source_path) - code_object = self.source_to_code(source_bytes, source_path) - _verbose_message('code object from {}', source_path) - if (not sys.dont_write_bytecode and bytecode_path is not None and - source_mtime is not None): - data = _code_to_bytecode(code_object, source_mtime, - len(source_bytes)) - try: - self._cache_bytecode(source_path, bytecode_path, data) - _verbose_message('wrote {!r}', bytecode_path) - except NotImplementedError: - pass - return code_object - - -class FileLoader: - - """Base file loader class which implements the loader protocol methods that - require file system usage.""" - - def __init__(self, fullname, path): - """Cache the module name and the path to the file found by the - finder.""" - self.name = fullname - self.path = path - - def __eq__(self, other): - return (self.__class__ == other.__class__ and - self.__dict__ == other.__dict__) - - def __hash__(self): - return hash(self.name) ^ hash(self.path) - - @_check_name - def load_module(self, fullname): - """Load a module from a file. - - This method is deprecated. Use exec_module() instead. - - """ - # The only reason for this method is for the name check. - # Issue #14857: Avoid the zero-argument form of super so the implementation - # of that form can be updated without breaking the frozen module - return super(FileLoader, self).load_module(fullname) - - @_check_name - def get_filename(self, fullname): - """Return the path to the source file as found by the finder.""" - return self.path - - def get_data(self, path): - """Return the data from path as raw bytes.""" - with _io.FileIO(path, 'r') as file: - return file.read() - - -class SourceFileLoader(FileLoader, SourceLoader): - - """Concrete implementation of SourceLoader using the file system.""" - - def path_stats(self, path): - """Return the metadata for the path.""" - st = _path_stat(path) - return {'mtime': st.st_mtime, 'size': st.st_size} - - def _cache_bytecode(self, source_path, bytecode_path, data): - # Adapt between the two APIs - mode = _calc_mode(source_path) - return self.set_data(bytecode_path, data, _mode=mode) - - def set_data(self, path, data, *, _mode=0o666): - """Write bytes data to a file.""" - parent, filename = _path_split(path) - path_parts = [] - # Figure out what directories are missing. - while parent and not _path_isdir(parent): - parent, part = _path_split(parent) - path_parts.append(part) - # Create needed directories. - for part in reversed(path_parts): - parent = _path_join(parent, part) - try: - _os.mkdir(parent) - except FileExistsError: - # Probably another Python process already created the dir. - continue - except OSError as exc: - # Could be a permission error, read-only filesystem: just forget - # about writing the data. - _verbose_message('could not create {!r}: {!r}', parent, exc) - return - try: - _write_atomic(path, data, _mode) - _verbose_message('created {!r}', path) - except OSError as exc: - # Same as above: just don't write the bytecode. - _verbose_message('could not create {!r}: {!r}', path, exc) - - -class SourcelessFileLoader(FileLoader, _LoaderBasics): - - """Loader which handles sourceless file imports.""" - - def get_code(self, fullname): - path = self.get_filename(fullname) - data = self.get_data(path) - bytes_data = _validate_bytecode_header(data, name=fullname, path=path) - return _compile_bytecode(bytes_data, name=fullname, bytecode_path=path) - - def get_source(self, fullname): - """Return None as there is no source code.""" - return None - - -# Filled in by _setup(). -EXTENSION_SUFFIXES = [] - - -class ExtensionFileLoader: - - """Loader for extension modules. - - The constructor is designed to work with FileFinder. - - """ - - def __init__(self, name, path): - self.name = name - self.path = path - - def __eq__(self, other): - return (self.__class__ == other.__class__ and - self.__dict__ == other.__dict__) - - def __hash__(self): - return hash(self.name) ^ hash(self.path) - - @_check_name - def load_module(self, fullname): - """Load an extension module.""" - # Once an exec_module() implementation is added we can also - # add a deprecation warning here. - with _ManageReload(fullname): - module = _call_with_frames_removed(_imp.load_dynamic, - fullname, self.path) - _verbose_message('extension module loaded from {!r}', self.path) - is_package = self.is_package(fullname) - if is_package and not hasattr(module, '__path__'): - module.__path__ = [_path_split(self.path)[0]] - module.__loader__ = self - module.__package__ = module.__name__ - if not is_package: - module.__package__ = module.__package__.rpartition('.')[0] - return module - - def is_package(self, fullname): - """Return True if the extension module is a package.""" - file_name = _path_split(self.path)[1] - return any(file_name == '__init__' + suffix - for suffix in EXTENSION_SUFFIXES) - - def get_code(self, fullname): - """Return None as an extension module cannot create a code object.""" - return None - - def get_source(self, fullname): - """Return None as extension modules have no source code.""" - return None - - @_check_name - def get_filename(self, fullname): - """Return the path to the source file as found by the finder.""" - return self.path - - -class _NamespacePath: - """Represents a namespace package's path. It uses the module name - to find its parent module, and from there it looks up the parent's - __path__. When this changes, the module's own path is recomputed, - using path_finder. For top-level modules, the parent module's path - is sys.path.""" - - def __init__(self, name, path, path_finder): - self._name = name - self._path = path - self._last_parent_path = tuple(self._get_parent_path()) - self._path_finder = path_finder - - def _find_parent_path_names(self): - """Returns a tuple of (parent-module-name, parent-path-attr-name)""" - parent, dot, me = self._name.rpartition('.') - if dot == '': - # This is a top-level module. sys.path contains the parent path. - return 'sys', 'path' - # Not a top-level module. parent-module.__path__ contains the - # parent path. - return parent, '__path__' - - def _get_parent_path(self): - parent_module_name, path_attr_name = self._find_parent_path_names() - return getattr(sys.modules[parent_module_name], path_attr_name) - - def _recalculate(self): - # If the parent's path has changed, recalculate _path - parent_path = tuple(self._get_parent_path()) # Make a copy - if parent_path != self._last_parent_path: - spec = self._path_finder(self._name, parent_path) - # Note that no changes are made if a loader is returned, but we - # do remember the new parent path - if spec is not None and spec.loader is None: - if spec.submodule_search_locations: - self._path = spec.submodule_search_locations - self._last_parent_path = parent_path # Save the copy - return self._path - - def __iter__(self): - return iter(self._recalculate()) - - def __len__(self): - return len(self._recalculate()) - - def __repr__(self): - return '_NamespacePath({!r})'.format(self._path) - - def __contains__(self, item): - return item in self._recalculate() - - def append(self, item): - self._path.append(item) - - -# We use this exclusively in module_from_spec() for backward-compatibility. -class _NamespaceLoader: - def __init__(self, name, path, path_finder): - self._path = _NamespacePath(name, path, path_finder) - - @classmethod - def module_repr(cls, module): - """Return repr for the module. - - The method is deprecated. The import machinery does the job itself. - - """ - return ''.format(module.__name__) - - def is_package(self, fullname): - return True - - def get_source(self, fullname): - return '' - - def get_code(self, fullname): - return compile('', '', 'exec', dont_inherit=True) - - def create_module(self, spec): - """Use default semantics for module creation.""" - - def exec_module(self, module): - pass - - def load_module(self, fullname): - """Load a namespace module. - - This method is deprecated. Use exec_module() instead. - - """ - # The import system never calls this method. - _verbose_message('namespace module loaded with path {!r}', self._path) - return _load_module_shim(self, fullname) - - -# Finders ##################################################################### - -class PathFinder: - - """Meta path finder for sys.path and package __path__ attributes.""" - - @classmethod - def invalidate_caches(cls): - """Call the invalidate_caches() method on all path entry finders - stored in sys.path_importer_caches (where implemented).""" - for finder in sys.path_importer_cache.values(): - if hasattr(finder, 'invalidate_caches'): - finder.invalidate_caches() - - @classmethod - def _path_hooks(cls, path): - """Search sequence of hooks for a finder for 'path'. - - If 'hooks' is false then use sys.path_hooks. - - """ - if sys.path_hooks is not None and not sys.path_hooks: - _warnings.warn('sys.path_hooks is empty', ImportWarning) - for hook in sys.path_hooks: - try: - return hook(path) - except ImportError: - continue - else: - return None - - @classmethod - def _path_importer_cache(cls, path): - """Get the finder for the path entry from sys.path_importer_cache. - - If the path entry is not in the cache, find the appropriate finder - and cache it. If no finder is available, store None. - - """ - if path == '': - try: - path = _os.getcwd() - except FileNotFoundError: - # Don't cache the failure as the cwd can easily change to - # a valid directory later on. - return None - try: - finder = sys.path_importer_cache[path] - except KeyError: - finder = cls._path_hooks(path) - sys.path_importer_cache[path] = finder - return finder - - @classmethod - def _legacy_get_spec(cls, fullname, finder): - # This would be a good place for a DeprecationWarning if - # we ended up going that route. - if hasattr(finder, 'find_loader'): - loader, portions = finder.find_loader(fullname) - else: - loader = finder.find_module(fullname) - portions = [] - if loader is not None: - return spec_from_loader(fullname, loader) - spec = ModuleSpec(fullname, None) - spec.submodule_search_locations = portions - return spec - - @classmethod - def _get_spec(cls, fullname, path, target=None): - """Find the loader or namespace_path for this module/package name.""" - # If this ends up being a namespace package, namespace_path is - # the list of paths that will become its __path__ - namespace_path = [] - for entry in path: - if not isinstance(entry, (str, bytes)): - continue - finder = cls._path_importer_cache(entry) - if finder is not None: - if hasattr(finder, 'find_spec'): - spec = finder.find_spec(fullname, target) - else: - spec = cls._legacy_get_spec(fullname, finder) - if spec is None: - continue - if spec.loader is not None: - return spec - portions = spec.submodule_search_locations - if portions is None: - raise ImportError('spec missing loader') - # This is possibly part of a namespace package. - # Remember these path entries (if any) for when we - # create a namespace package, and continue iterating - # on path. - namespace_path.extend(portions) - else: - spec = ModuleSpec(fullname, None) - spec.submodule_search_locations = namespace_path - return spec - - @classmethod - def find_spec(cls, fullname, path=None, target=None): - """find the module on sys.path or 'path' based on sys.path_hooks and - sys.path_importer_cache.""" - if path is None: - path = sys.path - spec = cls._get_spec(fullname, path, target) - if spec is None: - return 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' - spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) - return spec - else: - return None - else: - return spec - - @classmethod - def find_module(cls, fullname, path=None): - """find the module on sys.path or 'path' based on sys.path_hooks and - sys.path_importer_cache. - - This method is deprecated. Use find_spec() instead. - - """ - spec = cls.find_spec(fullname, path) - if spec is None: - return None - return spec.loader - - -class FileFinder: - - """File-based finder. - - Interactions with the file system are cached for performance, being - refreshed when the directory the finder is handling has been modified. - - """ - - def __init__(self, path, *loader_details): - """Initialize with the path to search on and a variable number of - 2-tuples containing the loader and the file suffixes the loader - recognizes.""" - loaders = [] - for loader, suffixes in loader_details: - loaders.extend((suffix, loader) for suffix in suffixes) - self._loaders = loaders - # Base (directory) path - self.path = path or '.' - self._path_mtime = -1 - self._path_cache = set() - self._relaxed_path_cache = set() - - def invalidate_caches(self): - """Invalidate the directory mtime.""" - self._path_mtime = -1 - - find_module = _find_module_shim - - def find_loader(self, fullname): - """Try to find a loader for the specified module, or the namespace - package portions. Returns (loader, list-of-portions). - - This method is deprecated. Use find_spec() instead. - - """ - spec = self.find_spec(fullname) - if spec is None: - return None, [] - return spec.loader, spec.submodule_search_locations or [] - - def _get_spec(self, loader_class, fullname, path, smsl, target): - loader = loader_class(fullname, path) - return spec_from_file_location(fullname, path, loader=loader, - submodule_search_locations=smsl) - - def find_spec(self, fullname, target=None): - """Try to find a loader for the specified module, or the namespace - package portions. Returns (loader, list-of-portions).""" - is_namespace = False - tail_module = fullname.rpartition('.')[2] - try: - mtime = _path_stat(self.path or _os.getcwd()).st_mtime - except OSError: - mtime = -1 - if mtime != self._path_mtime: - self._fill_cache() - self._path_mtime = mtime - # tail_module keeps the original casing, for __file__ and friends - if _relax_case(): - cache = self._relaxed_path_cache - cache_module = tail_module.lower() - else: - cache = self._path_cache - cache_module = tail_module - # Check if the module is the name of a directory (and thus a package). - if cache_module in cache: - base_path = _path_join(self.path, tail_module) - for suffix, loader_class in self._loaders: - init_filename = '__init__' + suffix - full_path = _path_join(base_path, init_filename) - if _path_isfile(full_path): - return self._get_spec(loader_class, fullname, full_path, [base_path], target) - else: - # If a namespace package, return the path if we don't - # find a module in the next section. - is_namespace = _path_isdir(base_path) - # Check for a file w/ a proper suffix exists. - for suffix, loader_class in self._loaders: - full_path = _path_join(self.path, tail_module + suffix) - _verbose_message('trying {}'.format(full_path), verbosity=2) - if cache_module + suffix in cache: - if _path_isfile(full_path): - return self._get_spec(loader_class, fullname, full_path, None, target) - if is_namespace: - _verbose_message('possible namespace for {}'.format(base_path)) - spec = ModuleSpec(fullname, None) - spec.submodule_search_locations = [base_path] - return spec - return None - - def _fill_cache(self): - """Fill the cache of potential modules and packages for this directory.""" - path = self.path - try: - contents = _os.listdir(path or _os.getcwd()) - except (FileNotFoundError, PermissionError, NotADirectoryError): - # Directory has either been removed, turned into a file, or made - # unreadable. - contents = [] - # We store two cached versions, to handle runtime changes of the - # PYTHONCASEOK environment variable. - if not sys.platform.startswith('win'): - self._path_cache = set(contents) - else: - # Windows users can import modules with case-insensitive file - # suffixes (for legacy reasons). Make the suffix lowercase here - # so it's done once instead of for every import. This is safe as - # the specified suffixes to check against are always specified in a - # case-sensitive manner. - lower_suffix_contents = set() - for item in contents: - name, dot, suffix = item.partition('.') - if dot: - new_name = '{}.{}'.format(name, suffix.lower()) - else: - new_name = name - lower_suffix_contents.add(new_name) - self._path_cache = lower_suffix_contents - if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): - self._relaxed_path_cache = {fn.lower() for fn in contents} - - @classmethod - def path_hook(cls, *loader_details): - """A class method which returns a closure to use on sys.path_hook - which will return an instance using the specified loaders and the path - called on the closure. - - If the path called on the closure is not a directory, ImportError is - raised. - - """ - def path_hook_for_FileFinder(path): - """Path hook for importlib.machinery.FileFinder.""" - if not _path_isdir(path): - raise ImportError('only directories are supported', path=path) - return cls(path, *loader_details) - - return path_hook_for_FileFinder - - def __repr__(self): - return 'FileFinder({!r})'.format(self.path) - - # Import itself ############################################################### class _ImportLockContext: @@ -2305,17 +1029,6 @@ return package -def _get_supported_file_loaders(): - """Returns a list of file-based module loaders. - - Each item is a tuple (loader, suffixes). - """ - extensions = ExtensionFileLoader, _imp.extension_suffixes() - source = SourceFileLoader, SOURCE_SUFFIXES - bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES - return [extensions, source, bytecode] - - def __import__(name, globals=None, locals=None, fromlist=(), level=0): """Import a module. @@ -2385,34 +1098,13 @@ # Directly load built-in modules needed during bootstrap. self_module = sys.modules[__name__] - for builtin_name in ('_io', '_warnings', 'builtins', 'marshal'): + for builtin_name in ('_warnings',): if builtin_name not in sys.modules: builtin_module = _builtin_from_name(builtin_name) else: builtin_module = sys.modules[builtin_name] setattr(self_module, builtin_name, builtin_module) - # Directly load the os module (needed during bootstrap). - os_details = ('posix', ['/']), ('nt', ['\\', '/']) - for builtin_os, path_separators in os_details: - # Assumption made in _path_join() - assert all(len(sep) == 1 for sep in path_separators) - path_sep = path_separators[0] - if builtin_os in sys.modules: - os_module = sys.modules[builtin_os] - break - else: - try: - os_module = _builtin_from_name(builtin_os) - break - except ImportError: - continue - else: - raise ImportError('importlib requires posix or nt') - setattr(self_module, '_os', os_module) - setattr(self_module, 'path_sep', path_sep) - setattr(self_module, 'path_separators', ''.join(path_separators)) - # Directly load the _thread module (needed during bootstrap). try: thread_module = _builtin_from_name('_thread') @@ -2425,27 +1117,14 @@ weakref_module = _builtin_from_name('_weakref') setattr(self_module, '_weakref', weakref_module) - # Directly load the winreg module (needed during bootstrap). - if builtin_os == 'nt': - winreg_module = _builtin_from_name('winreg') - setattr(self_module, '_winreg', winreg_module) - - # Constants - setattr(self_module, '_relax_case', _make_relax_case()) - EXTENSION_SUFFIXES.extend(_imp.extension_suffixes()) - if builtin_os == 'nt': - SOURCE_SUFFIXES.append('.pyw') - if '_d.pyd' in EXTENSION_SUFFIXES: - WindowsRegistryFinder.DEBUG_BUILD = True - def _install(sys_module, _imp_module): """Install importlib as the implementation of import.""" _setup(sys_module, _imp_module) - supported_loaders = _get_supported_file_loaders() - sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) + sys.meta_path.append(BuiltinImporter) sys.meta_path.append(FrozenImporter) - if _os.__name__ == 'nt': - sys.meta_path.append(WindowsRegistryFinder) - sys.meta_path.append(PathFinder) + + import _frozen_importlib_external + _frozen_importlib_external._install(sys.modules[__name__]) + sys.modules[__name__]._bootstrap_external = _frozen_importlib_external diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py new file mode 100644 --- /dev/null +++ b/Lib/importlib/_bootstrap_external.py @@ -0,0 +1,1462 @@ +"""Core implementation of path-based import. + +This module is NOT meant to be directly imported! It has been designed such +that it can be bootstrapped into Python as the implementation of import. As +such it requires the injection of specific modules and attributes in order to +work. One should use importlib as the public-facing version of this module. + +""" +# +# IMPORTANT: Whenever making changes to this module, be sure to run +# a top-level make in order to get the frozen version of the module +# updated. Not doing so will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module +# in the early stages of compilation. +# + +# See importlib._setup() for what is injected into the global namespace. + +# When editing this code be aware that code executed at import time CANNOT +# reference any injected objects! This includes not only global code but also +# anything specified at the class level. + +# Bootstrap-related code ###################################################### + +_CASE_INSENSITIVE_PLATFORMS = 'win', 'cygwin', 'darwin' + + +def _make_relax_case(): + if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): + def _relax_case(): + """True if filenames must be checked case-insensitively.""" + return b'PYTHONCASEOK' in _os.environ + else: + def _relax_case(): + """True if filenames must be checked case-insensitively.""" + return False + return _relax_case + + +def _w_long(x): + """Convert a 32-bit integer to little-endian.""" + return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little') + + +def _r_long(int_bytes): + """Convert 4 bytes in little-endian to an integer.""" + return int.from_bytes(int_bytes, 'little') + + +def _path_join(*path_parts): + """Replacement for os.path.join().""" + return path_sep.join([part.rstrip(path_separators) + for part in path_parts if part]) + + +def _path_split(path): + """Replacement for os.path.split().""" + if len(path_separators) == 1: + front, _, tail = path.rpartition(path_sep) + return front, tail + for x in reversed(path): + if x in path_separators: + front, tail = path.rsplit(x, maxsplit=1) + return front, tail + return '', path + + +def _path_stat(path): + """Stat the path. + + Made a separate function to make it easier to override in experiments + (e.g. cache stat results). + + """ + return _os.stat(path) + + +def _path_is_mode_type(path, mode): + """Test whether the path is the specified mode type.""" + try: + stat_info = _path_stat(path) + except OSError: + return False + return (stat_info.st_mode & 0o170000) == mode + + +def _path_isfile(path): + """Replacement for os.path.isfile.""" + return _path_is_mode_type(path, 0o100000) + + +def _path_isdir(path): + """Replacement for os.path.isdir.""" + if not path: + path = _os.getcwd() + return _path_is_mode_type(path, 0o040000) + + +def _write_atomic(path, data, mode=0o666): + """Best-effort function to write data to a path atomically. + Be prepared to handle a FileExistsError if concurrent writing of the + temporary file is attempted.""" + # id() is used to generate a pseudo-random filename. + path_tmp = '{}.{}'.format(path, id(path)) + fd = _os.open(path_tmp, + _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, mode & 0o666) + try: + # We first write data to a temporary file, and then use os.replace() to + # perform an atomic rename. + with _io.FileIO(fd, 'wb') as file: + file.write(data) + _os.replace(path_tmp, path) + except OSError: + try: + _os.unlink(path_tmp) + except OSError: + pass + raise + + +_code_type = type(_write_atomic.__code__) + + +# Finder/loader utility code ############################################### + +# Magic word to reject .pyc files generated by other Python versions. +# It should change for each incompatible change to the bytecode. +# +# The value of CR and LF is incorporated so if you ever read or write +# a .pyc file in text mode the magic number will be wrong; also, the +# Apple MPW compiler swaps their values, botching string constants. +# +# The magic numbers must be spaced apart at least 2 values, as the +# -U interpeter flag will cause MAGIC+1 being used. They have been +# odd numbers for some time now. +# +# There were a variety of old schemes for setting the magic number. +# The current working scheme is to increment the previous value by +# 10. +# +# Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic +# number also includes a new "magic tag", i.e. a human readable string used +# to represent the magic number in __pycache__ directories. When you change +# the magic number, you must also set a new unique magic tag. Generally this +# can be named after the Python major version of the magic number bump, but +# it can really be anything, as long as it's different than anything else +# that's come before. The tags are included in the following table, starting +# with Python 3.2a0. +# +# Known values: +# Python 1.5: 20121 +# Python 1.5.1: 20121 +# Python 1.5.2: 20121 +# Python 1.6: 50428 +# Python 2.0: 50823 +# Python 2.0.1: 50823 +# Python 2.1: 60202 +# Python 2.1.1: 60202 +# Python 2.1.2: 60202 +# Python 2.2: 60717 +# Python 2.3a0: 62011 +# Python 2.3a0: 62021 +# Python 2.3a0: 62011 (!) +# Python 2.4a0: 62041 +# Python 2.4a3: 62051 +# Python 2.4b1: 62061 +# Python 2.5a0: 62071 +# Python 2.5a0: 62081 (ast-branch) +# Python 2.5a0: 62091 (with) +# Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) +# Python 2.5b3: 62101 (fix wrong code: for x, in ...) +# Python 2.5b3: 62111 (fix wrong code: x += yield) +# Python 2.5c1: 62121 (fix wrong lnotab with for loops and +# storing constants that should have been removed) +# Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) +# Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) +# Python 2.6a1: 62161 (WITH_CLEANUP optimization) +# Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND) +# Python 2.7a0: 62181 (optimize conditional branches: +# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) +# Python 2.7a0 62191 (introduce SETUP_WITH) +# Python 2.7a0 62201 (introduce BUILD_SET) +# Python 2.7a0 62211 (introduce MAP_ADD and SET_ADD) +# Python 3000: 3000 +# 3010 (removed UNARY_CONVERT) +# 3020 (added BUILD_SET) +# 3030 (added keyword-only parameters) +# 3040 (added signature annotations) +# 3050 (print becomes a function) +# 3060 (PEP 3115 metaclass syntax) +# 3061 (string literals become unicode) +# 3071 (PEP 3109 raise changes) +# 3081 (PEP 3137 make __file__ and __name__ unicode) +# 3091 (kill str8 interning) +# 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) +# tag: cpython-32 +# Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) +# 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.4a1 3250 (evaluate positional default arguments before +# keyword-only defaults) +# 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) +# 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) +# +# MAGIC must change whenever the bytecode emitted by the compiler may no +# longer be understood by older implementations of the eval loop (usually +# due to the addition of new opcodes). + +MAGIC_NUMBER = (3320).to_bytes(2, 'little') + b'\r\n' +_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c + +_PYCACHE = '__pycache__' +_OPT = 'opt-' + +SOURCE_SUFFIXES = ['.py'] # _setup() adds .pyw as needed. + +BYTECODE_SUFFIXES = ['.pyc'] +# Deprecated. +DEBUG_BYTECODE_SUFFIXES = OPTIMIZED_BYTECODE_SUFFIXES = BYTECODE_SUFFIXES + +def cache_from_source(path, debug_override=None, *, optimization=None): + """Given the path to a .py file, return the path to its .pyc file. + + The .py file does not need to exist; this simply returns the path to the + .pyc file calculated as if the .py file were imported. + + The 'optimization' parameter controls the presumed optimization level of + the bytecode file. If 'optimization' is not None, the string representation + of the argument is taken and verified to be alphanumeric (else ValueError + is raised). + + The debug_override parameter is deprecated. If debug_override is not None, + a True value is the same as setting 'optimization' to the empty string + while a False value is equivalent to setting 'optimization' to '1'. + + If sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + if debug_override is not None: + _warnings.warn('the debug_override parameter is deprecated; use ' + "'optimization' instead", DeprecationWarning) + if optimization is not None: + message = 'debug_override or optimization must be set to None' + raise TypeError(message) + optimization = '' if debug_override else 1 + head, tail = _path_split(path) + base, sep, rest = tail.rpartition('.') + tag = sys.implementation.cache_tag + if tag is None: + raise NotImplementedError('sys.implementation.cache_tag is None') + almost_filename = ''.join([(base if base else rest), sep, tag]) + if optimization is None: + if sys.flags.optimize == 0: + optimization = '' + else: + optimization = sys.flags.optimize + optimization = str(optimization) + if optimization != '': + if not optimization.isalnum(): + raise ValueError('{!r} is not alphanumeric'.format(optimization)) + almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization) + return _path_join(head, _PYCACHE, almost_filename + BYTECODE_SUFFIXES[0]) + + +def source_from_cache(path): + """Given the path to a .pyc. file, return the path to its .py file. + + The .pyc file does not need to exist; this simply returns the path to + the .py file calculated to correspond to the .pyc file. If path does + not conform to PEP 3147/488 format, ValueError will be raised. If + sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + if sys.implementation.cache_tag is None: + raise NotImplementedError('sys.implementation.cache_tag is None') + head, pycache_filename = _path_split(path) + head, pycache = _path_split(head) + if pycache != _PYCACHE: + raise ValueError('{} not bottom-level directory in ' + '{!r}'.format(_PYCACHE, path)) + dot_count = pycache_filename.count('.') + if dot_count not in {2, 3}: + raise ValueError('expected only 2 or 3 dots in ' + '{!r}'.format(pycache_filename)) + elif dot_count == 3: + optimization = pycache_filename.rsplit('.', 2)[-2] + if not optimization.startswith(_OPT): + raise ValueError("optimization portion of filename does not start " + "with {!r}".format(_OPT)) + opt_level = optimization[len(_OPT):] + if not opt_level.isalnum(): + raise ValueError("optimization level {!r} is not an alphanumeric " + "value".format(optimization)) + base_filename = pycache_filename.partition('.')[0] + return _path_join(head, base_filename + SOURCE_SUFFIXES[0]) + + +def _get_sourcefile(bytecode_path): + """Convert a bytecode file path to a source path (if possible). + + This function exists purely for backwards-compatibility for + PyImport_ExecCodeModuleWithFilenames() in the C API. + + """ + if len(bytecode_path) == 0: + return None + rest, _, extension = bytecode_path.rpartition('.') + if not rest or extension.lower()[-3:-1] != 'py': + return bytecode_path + try: + source_path = source_from_cache(bytecode_path) + except (NotImplementedError, ValueError): + source_path = bytecode_path[:-1] + return source_path if _path_isfile(source_path) else bytecode_path + + +def _get_cached(filename): + if filename.endswith(tuple(SOURCE_SUFFIXES)): + try: + return cache_from_source(filename) + except NotImplementedError: + pass + elif filename.endswith(tuple(BYTECODE_SUFFIXES)): + return filename + else: + return None + + +def _calc_mode(path): + """Calculate the mode permissions for a bytecode file.""" + try: + mode = _path_stat(path).st_mode + except OSError: + mode = 0o666 + # We always ensure write access so we can update cached files + # later even when the source files are read-only on Windows (#6074) + mode |= 0o200 + return mode + + +def _verbose_message(message, *args, verbosity=1): + """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" + if sys.flags.verbose >= verbosity: + if not message.startswith(('#', 'import ')): + message = '# ' + message + print(message.format(*args), file=sys.stderr) + + +def _check_name(method): + """Decorator to verify that the module being requested matches the one the + loader can handle. + + The first argument (self) must define _name which the second argument is + compared against. If the comparison fails then ImportError is raised. + + """ + def _check_name_wrapper(self, name=None, *args, **kwargs): + if name is None: + name = self.name + elif self.name != name: + raise ImportError('loader cannot handle %s' % name, name=name) + return method(self, name, *args, **kwargs) + try: + _wrap = _bootstrap._wrap + except NameError: + # XXX yuck + def _wrap(new, old): + for replace in ['__module__', '__name__', '__qualname__', '__doc__']: + if hasattr(old, replace): + setattr(new, replace, getattr(old, replace)) + new.__dict__.update(old.__dict__) + _wrap(_check_name_wrapper, method) + return _check_name_wrapper + + +def _find_module_shim(self, fullname): + """Try to find a loader for the specified module by delegating to + self.find_loader(). + + This method is deprecated in favor of finder.find_spec(). + + """ + # Call find_loader(). If it returns a string (indicating this + # is a namespace package portion), generate a warning and + # return None. + loader, portions = self.find_loader(fullname) + if loader is None and len(portions): + msg = 'Not importing directory {}: missing __init__' + _warnings.warn(msg.format(portions[0]), ImportWarning) + return loader + + +# Typically used by loader classes as a method replacement. +def _load_module_shim(self, fullname): + """Load the specified module into sys.modules and return it. + + This method is deprecated. Use loader.exec_module instead. + + """ + spec = spec_from_loader(fullname, self) + if fullname in sys.modules: + module = sys.modules[fullname] + _bootstrap._exec(spec, module) + return sys.modules[fullname] + else: + return _bootstrap._load(spec) + + +def _validate_bytecode_header(data, source_stats=None, name=None, path=None): + """Validate the header of the passed-in bytecode against source_stats (if + given) and returning the bytecode that can be compiled by compile(). + + All other arguments are used to enhance error reporting. + + ImportError is raised when the magic number is incorrect or the bytecode is + found to be stale. EOFError is raised when the data is found to be + truncated. + + """ + exc_details = {} + if name is not None: + exc_details['name'] = name + else: + # To prevent having to make all messages have a conditional name. + name = '' + if path is not None: + exc_details['path'] = path + magic = data[:4] + raw_timestamp = data[4:8] + raw_size = data[8:12] + if magic != MAGIC_NUMBER: + message = 'bad magic number in {!r}: {!r}'.format(name, magic) + _verbose_message(message) + raise ImportError(message, **exc_details) + elif len(raw_timestamp) != 4: + message = 'reached EOF while reading timestamp in {!r}'.format(name) + _verbose_message(message) + raise EOFError(message) + elif len(raw_size) != 4: + message = 'reached EOF while reading size of source in {!r}'.format(name) + _verbose_message(message) + raise EOFError(message) + if source_stats is not None: + try: + source_mtime = int(source_stats['mtime']) + except KeyError: + pass + else: + if _r_long(raw_timestamp) != source_mtime: + message = 'bytecode is stale for {!r}'.format(name) + _verbose_message(message) + raise ImportError(message, **exc_details) + try: + source_size = source_stats['size'] & 0xFFFFFFFF + except KeyError: + pass + else: + if _r_long(raw_size) != source_size: + raise ImportError('bytecode is stale for {!r}'.format(name), + **exc_details) + return data[12:] + + +def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): + """Compile bytecode as returned by _validate_bytecode_header().""" + code = marshal.loads(data) + if isinstance(code, _code_type): + _verbose_message('code object from {!r}', bytecode_path) + if source_path is not None: + _imp._fix_co_filename(code, source_path) + return code + else: + raise ImportError('Non-code object in {!r}'.format(bytecode_path), + name=name, path=bytecode_path) + +def _code_to_bytecode(code, mtime=0, source_size=0): + """Compile a code object into bytecode for writing out to a byte-compiled + file.""" + data = bytearray(MAGIC_NUMBER) + data.extend(_w_long(mtime)) + data.extend(_w_long(source_size)) + data.extend(marshal.dumps(code)) + return data + + +def decode_source(source_bytes): + """Decode bytes representing source code and return the string. + + Universal newline support is used in the decoding. + """ + import tokenize # To avoid bootstrap issues. + source_bytes_readline = _io.BytesIO(source_bytes).readline + encoding = tokenize.detect_encoding(source_bytes_readline) + newline_decoder = _io.IncrementalNewlineDecoder(None, True) + return newline_decoder.decode(source_bytes.decode(encoding[0])) + + +# Module specifications ####################################################### + +def spec_from_loader(name, loader, *, origin=None, is_package=None): + """Return a module spec based on various loader methods.""" + if hasattr(loader, 'get_filename'): + if is_package is None: + return spec_from_file_location(name, loader=loader) + search = [] if is_package else None + return spec_from_file_location(name, loader=loader, + submodule_search_locations=search) + + if is_package is None: + if hasattr(loader, 'is_package'): + try: + is_package = loader.is_package(name) + except ImportError: + is_package = None # aka, undefined + else: + # the default + is_package = False + + return _bootstrap.ModuleSpec(name, loader, origin=origin, is_package=is_package) + + +_POPULATE = object() + + +def spec_from_file_location(name, location=None, *, loader=None, + submodule_search_locations=_POPULATE): + """Return a module spec based on a file location. + + To indicate that the module is a package, set + submodule_search_locations to a list of directory paths. An + empty list is sufficient, though its not otherwise useful to the + import system. + + The loader must take a spec as its only __init__() arg. + + """ + if location is None: + # The caller may simply want a partially populated location- + # oriented spec. So we set the location to a bogus value and + # fill in as much as we can. + location = '' + if hasattr(loader, 'get_filename'): + # ExecutionLoader + try: + location = loader.get_filename(name) + except ImportError: + pass + + # If the location is on the filesystem, but doesn't actually exist, + # we could return None here, indicating that the location is not + # valid. However, we don't have a good way of testing since an + # indirect location (e.g. a zip file or URL) will look like a + # non-existent file relative to the filesystem. + + spec = _bootstrap.ModuleSpec(name, loader, origin=location) + spec._set_fileattr = True + + # Pick a loader if one wasn't provided. + if loader is None: + for loader_class, suffixes in _get_supported_file_loaders(): + if location.endswith(tuple(suffixes)): + loader = loader_class(name, location) + spec.loader = loader + break + else: + return None + + # Set submodule_search_paths appropriately. + if submodule_search_locations is _POPULATE: + # Check the loader. + if hasattr(loader, 'is_package'): + try: + is_package = loader.is_package(name) + except ImportError: + pass + else: + if is_package: + spec.submodule_search_locations = [] + else: + spec.submodule_search_locations = submodule_search_locations + if spec.submodule_search_locations == []: + if location: + dirname = _path_split(location)[0] + spec.submodule_search_locations.append(dirname) + + return spec + + +# Loaders ##################################################################### + +class WindowsRegistryFinder: + + """Meta path finder for modules declared in the Windows registry.""" + + REGISTRY_KEY = ( + 'Software\\Python\\PythonCore\\{sys_version}' + '\\Modules\\{fullname}') + REGISTRY_KEY_DEBUG = ( + 'Software\\Python\\PythonCore\\{sys_version}' + '\\Modules\\{fullname}\\Debug') + DEBUG_BUILD = False # Changed in _setup() + + @classmethod + def _open_registry(cls, key): + try: + return _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key) + except OSError: + return _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key) + + @classmethod + def _search_registry(cls, fullname): + if cls.DEBUG_BUILD: + registry_key = cls.REGISTRY_KEY_DEBUG + else: + registry_key = cls.REGISTRY_KEY + key = registry_key.format(fullname=fullname, + sys_version=sys.version[:3]) + try: + with cls._open_registry(key) as hkey: + filepath = _winreg.QueryValue(hkey, '') + except OSError: + return None + return filepath + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + filepath = cls._search_registry(fullname) + if filepath is None: + return None + try: + _path_stat(filepath) + except OSError: + return None + for loader, suffixes in _get_supported_file_loaders(): + if filepath.endswith(tuple(suffixes)): + spec = spec_from_loader(fullname, loader(fullname, filepath), + origin=filepath) + return spec + + @classmethod + def find_module(cls, fullname, path=None): + """Find module named in the registry. + + This method is deprecated. Use exec_module() instead. + + """ + spec = cls.find_spec(fullname, path) + if spec is not None: + return spec.loader + else: + return None + + +class _LoaderBasics: + + """Base class of common code needed by both SourceLoader and + SourcelessFileLoader.""" + + def is_package(self, fullname): + """Concrete implementation of InspectLoader.is_package by checking if + the path returned by get_filename has a filename of '__init__.py'.""" + filename = _path_split(self.get_filename(fullname))[1] + filename_base = filename.rsplit('.', 1)[0] + tail_name = fullname.rpartition('.')[2] + return filename_base == '__init__' and tail_name != '__init__' + + def create_module(self, spec): + """Use default semantics for module creation.""" + + def exec_module(self, module): + """Execute the module.""" + code = self.get_code(module.__name__) + if code is None: + raise ImportError('cannot load module {!r} when get_code() ' + 'returns None'.format(module.__name__)) + _bootstrap._call_with_frames_removed(exec, code, module.__dict__) + + load_module = _load_module_shim + + +class SourceLoader(_LoaderBasics): + + def path_mtime(self, path): + """Optional method that returns the modification time (an int) for the + specified path, where path is a str. + + Raises IOError when the path cannot be handled. + """ + raise IOError + + def path_stats(self, path): + """Optional method returning a metadata dict for the specified path + to by the path (str). + Possible keys: + - 'mtime' (mandatory) is the numeric timestamp of last source + code modification; + - 'size' (optional) is the size in bytes of the source code. + + Implementing this method allows the loader to read bytecode files. + Raises IOError when the path cannot be handled. + """ + return {'mtime': self.path_mtime(path)} + + def _cache_bytecode(self, source_path, cache_path, data): + """Optional method which writes data (bytes) to a file path (a str). + + Implementing this method allows for the writing of bytecode files. + + The source path is needed in order to correctly transfer permissions + """ + # For backwards compatibility, we delegate to set_data() + return self.set_data(cache_path, data) + + def set_data(self, path, data): + """Optional method which writes data (bytes) to a file path (a str). + + Implementing this method allows for the writing of bytecode files. + """ + + + def get_source(self, fullname): + """Concrete implementation of InspectLoader.get_source.""" + path = self.get_filename(fullname) + try: + source_bytes = self.get_data(path) + except OSError as exc: + raise ImportError('source not available through get_data()', + name=fullname) from exc + return decode_source(source_bytes) + + def source_to_code(self, data, path, *, _optimize=-1): + """Return the code object compiled from source. + + The 'data' argument can be any object type that compile() supports. + """ + return _bootstrap._call_with_frames_removed(compile, data, path, 'exec', + dont_inherit=True, optimize=_optimize) + + def get_code(self, fullname): + """Concrete implementation of InspectLoader.get_code. + + Reading of bytecode requires path_stats to be implemented. To write + bytecode, set_data must also be implemented. + + """ + source_path = self.get_filename(fullname) + source_mtime = None + try: + bytecode_path = cache_from_source(source_path) + except NotImplementedError: + bytecode_path = None + else: + try: + st = self.path_stats(source_path) + except IOError: + pass + else: + source_mtime = int(st['mtime']) + try: + data = self.get_data(bytecode_path) + except OSError: + pass + else: + try: + bytes_data = _validate_bytecode_header(data, + source_stats=st, name=fullname, + path=bytecode_path) + except (ImportError, EOFError): + pass + else: + _verbose_message('{} matches {}', bytecode_path, + source_path) + return _compile_bytecode(bytes_data, name=fullname, + bytecode_path=bytecode_path, + source_path=source_path) + source_bytes = self.get_data(source_path) + code_object = self.source_to_code(source_bytes, source_path) + _verbose_message('code object from {}', source_path) + if (not sys.dont_write_bytecode and bytecode_path is not None and + source_mtime is not None): + data = _code_to_bytecode(code_object, source_mtime, + len(source_bytes)) + try: + self._cache_bytecode(source_path, bytecode_path, data) + _verbose_message('wrote {!r}', bytecode_path) + except NotImplementedError: + pass + return code_object + + +class FileLoader: + + """Base file loader class which implements the loader protocol methods that + require file system usage.""" + + def __init__(self, fullname, path): + """Cache the module name and the path to the file found by the + finder.""" + self.name = fullname + self.path = path + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self.__dict__ == other.__dict__) + + def __hash__(self): + return hash(self.name) ^ hash(self.path) + + @_check_name + def load_module(self, fullname): + """Load a module from a file. + + This method is deprecated. Use exec_module() instead. + + """ + # The only reason for this method is for the name check. + # Issue #14857: Avoid the zero-argument form of super so the implementation + # of that form can be updated without breaking the frozen module + return super(FileLoader, self).load_module(fullname) + + @_check_name + def get_filename(self, fullname): + """Return the path to the source file as found by the finder.""" + return self.path + + def get_data(self, path): + """Return the data from path as raw bytes.""" + with _io.FileIO(path, 'r') as file: + return file.read() + + +class SourceFileLoader(FileLoader, SourceLoader): + + """Concrete implementation of SourceLoader using the file system.""" + + def path_stats(self, path): + """Return the metadata for the path.""" + st = _path_stat(path) + return {'mtime': st.st_mtime, 'size': st.st_size} + + def _cache_bytecode(self, source_path, bytecode_path, data): + # Adapt between the two APIs + mode = _calc_mode(source_path) + return self.set_data(bytecode_path, data, _mode=mode) + + def set_data(self, path, data, *, _mode=0o666): + """Write bytes data to a file.""" + parent, filename = _path_split(path) + path_parts = [] + # Figure out what directories are missing. + while parent and not _path_isdir(parent): + parent, part = _path_split(parent) + path_parts.append(part) + # Create needed directories. + for part in reversed(path_parts): + parent = _path_join(parent, part) + try: + _os.mkdir(parent) + except FileExistsError: + # Probably another Python process already created the dir. + continue + except OSError as exc: + # Could be a permission error, read-only filesystem: just forget + # about writing the data. + _verbose_message('could not create {!r}: {!r}', parent, exc) + return + try: + _write_atomic(path, data, _mode) + _verbose_message('created {!r}', path) + except OSError as exc: + # Same as above: just don't write the bytecode. + _verbose_message('could not create {!r}: {!r}', path, exc) + + +class SourcelessFileLoader(FileLoader, _LoaderBasics): + + """Loader which handles sourceless file imports.""" + + def get_code(self, fullname): + path = self.get_filename(fullname) + data = self.get_data(path) + bytes_data = _validate_bytecode_header(data, name=fullname, path=path) + return _compile_bytecode(bytes_data, name=fullname, bytecode_path=path) + + def get_source(self, fullname): + """Return None as there is no source code.""" + return None + + +# Filled in by _setup(). +EXTENSION_SUFFIXES = [] + + +class ExtensionFileLoader: + + """Loader for extension modules. + + The constructor is designed to work with FileFinder. + + """ + + def __init__(self, name, path): + self.name = name + self.path = path + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self.__dict__ == other.__dict__) + + def __hash__(self): + return hash(self.name) ^ hash(self.path) + + @_check_name + def load_module(self, fullname): + """Load an extension module.""" + # Once an exec_module() implementation is added we can also + # add a deprecation warning here. + with _bootstrap._ManageReload(fullname): + module = _bootstrap._call_with_frames_removed(_imp.load_dynamic, + fullname, self.path) + _verbose_message('extension module loaded from {!r}', self.path) + is_package = self.is_package(fullname) + if is_package and not hasattr(module, '__path__'): + module.__path__ = [_path_split(self.path)[0]] + module.__loader__ = self + module.__package__ = module.__name__ + if not is_package: + module.__package__ = module.__package__.rpartition('.')[0] + return module + + def is_package(self, fullname): + """Return True if the extension module is a package.""" + file_name = _path_split(self.path)[1] + return any(file_name == '__init__' + suffix + for suffix in EXTENSION_SUFFIXES) + + def get_code(self, fullname): + """Return None as an extension module cannot create a code object.""" + return None + + def get_source(self, fullname): + """Return None as extension modules have no source code.""" + return None + + @_check_name + def get_filename(self, fullname): + """Return the path to the source file as found by the finder.""" + return self.path + + +class _NamespacePath: + """Represents a namespace package's path. It uses the module name + to find its parent module, and from there it looks up the parent's + __path__. When this changes, the module's own path is recomputed, + using path_finder. For top-level modules, the parent module's path + is sys.path.""" + + def __init__(self, name, path, path_finder): + self._name = name + self._path = path + self._last_parent_path = tuple(self._get_parent_path()) + self._path_finder = path_finder + + def _find_parent_path_names(self): + """Returns a tuple of (parent-module-name, parent-path-attr-name)""" + parent, dot, me = self._name.rpartition('.') + if dot == '': + # This is a top-level module. sys.path contains the parent path. + return 'sys', 'path' + # Not a top-level module. parent-module.__path__ contains the + # parent path. + return parent, '__path__' + + def _get_parent_path(self): + parent_module_name, path_attr_name = self._find_parent_path_names() + return getattr(sys.modules[parent_module_name], path_attr_name) + + def _recalculate(self): + # If the parent's path has changed, recalculate _path + parent_path = tuple(self._get_parent_path()) # Make a copy + if parent_path != self._last_parent_path: + spec = self._path_finder(self._name, parent_path) + # Note that no changes are made if a loader is returned, but we + # do remember the new parent path + if spec is not None and spec.loader is None: + if spec.submodule_search_locations: + self._path = spec.submodule_search_locations + self._last_parent_path = parent_path # Save the copy + return self._path + + def __iter__(self): + return iter(self._recalculate()) + + def __len__(self): + return len(self._recalculate()) + + def __repr__(self): + return '_NamespacePath({!r})'.format(self._path) + + def __contains__(self, item): + return item in self._recalculate() + + def append(self, item): + self._path.append(item) + + +# We use this exclusively in module_from_spec() for backward-compatibility. +class _NamespaceLoader: + def __init__(self, name, path, path_finder): + self._path = _NamespacePath(name, path, path_finder) + + @classmethod + def module_repr(cls, module): + """Return repr for the module. + + The method is deprecated. The import machinery does the job itself. + + """ + return ''.format(module.__name__) + + def is_package(self, fullname): + return True + + def get_source(self, fullname): + return '' + + def get_code(self, fullname): + return compile('', '', 'exec', dont_inherit=True) + + def create_module(self, spec): + """Use default semantics for module creation.""" + + def exec_module(self, module): + pass + + def load_module(self, fullname): + """Load a namespace module. + + This method is deprecated. Use exec_module() instead. + + """ + # The import system never calls this method. + _verbose_message('namespace module loaded with path {!r}', self._path) + return _load_module_shim(self, fullname) + + +# Finders ##################################################################### + +class PathFinder: + + """Meta path finder for sys.path and package __path__ attributes.""" + + @classmethod + def invalidate_caches(cls): + """Call the invalidate_caches() method on all path entry finders + stored in sys.path_importer_caches (where implemented).""" + for finder in sys.path_importer_cache.values(): + if hasattr(finder, 'invalidate_caches'): + finder.invalidate_caches() + + @classmethod + def _path_hooks(cls, path): + """Search sequence of hooks for a finder for 'path'. + + If 'hooks' is false then use sys.path_hooks. + + """ + if sys.path_hooks is not None and not sys.path_hooks: + _warnings.warn('sys.path_hooks is empty', ImportWarning) + for hook in sys.path_hooks: + try: + return hook(path) + except ImportError: + continue + else: + return None + + @classmethod + def _path_importer_cache(cls, path): + """Get the finder for the path entry from sys.path_importer_cache. + + If the path entry is not in the cache, find the appropriate finder + and cache it. If no finder is available, store None. + + """ + if path == '': + try: + path = _os.getcwd() + except FileNotFoundError: + # Don't cache the failure as the cwd can easily change to + # a valid directory later on. + return None + try: + finder = sys.path_importer_cache[path] + except KeyError: + finder = cls._path_hooks(path) + sys.path_importer_cache[path] = finder + return finder + + @classmethod + def _legacy_get_spec(cls, fullname, finder): + # This would be a good place for a DeprecationWarning if + # we ended up going that route. + if hasattr(finder, 'find_loader'): + loader, portions = finder.find_loader(fullname) + else: + loader = finder.find_module(fullname) + portions = [] + if loader is not None: + return spec_from_loader(fullname, loader) + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = portions + return spec + + @classmethod + def _get_spec(cls, fullname, path, target=None): + """Find the loader or namespace_path for this module/package name.""" + # If this ends up being a namespace package, namespace_path is + # the list of paths that will become its __path__ + namespace_path = [] + for entry in path: + if not isinstance(entry, (str, bytes)): + continue + finder = cls._path_importer_cache(entry) + if finder is not None: + if hasattr(finder, 'find_spec'): + spec = finder.find_spec(fullname, target) + else: + spec = cls._legacy_get_spec(fullname, finder) + if spec is None: + continue + if spec.loader is not None: + return spec + portions = spec.submodule_search_locations + if portions is None: + raise ImportError('spec missing loader') + # This is possibly part of a namespace package. + # Remember these path entries (if any) for when we + # create a namespace package, and continue iterating + # on path. + namespace_path.extend(portions) + else: + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = namespace_path + return spec + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + """find the module on sys.path or 'path' based on sys.path_hooks and + sys.path_importer_cache.""" + if path is None: + path = sys.path + spec = cls._get_spec(fullname, path, target) + if spec is None: + return 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' + spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) + return spec + else: + return None + else: + return spec + + @classmethod + def find_module(cls, fullname, path=None): + """find the module on sys.path or 'path' based on sys.path_hooks and + sys.path_importer_cache. + + This method is deprecated. Use find_spec() instead. + + """ + spec = cls.find_spec(fullname, path) + if spec is None: + return None + return spec.loader + + +class FileFinder: + + """File-based finder. + + Interactions with the file system are cached for performance, being + refreshed when the directory the finder is handling has been modified. + + """ + + def __init__(self, path, *loader_details): + """Initialize with the path to search on and a variable number of + 2-tuples containing the loader and the file suffixes the loader + recognizes.""" + loaders = [] + for loader, suffixes in loader_details: + loaders.extend((suffix, loader) for suffix in suffixes) + self._loaders = loaders + # Base (directory) path + self.path = path or '.' + self._path_mtime = -1 + self._path_cache = set() + self._relaxed_path_cache = set() + + def invalidate_caches(self): + """Invalidate the directory mtime.""" + self._path_mtime = -1 + + find_module = _find_module_shim + + def find_loader(self, fullname): + """Try to find a loader for the specified module, or the namespace + package portions. Returns (loader, list-of-portions). + + This method is deprecated. Use find_spec() instead. + + """ + spec = self.find_spec(fullname) + if spec is None: + return None, [] + return spec.loader, spec.submodule_search_locations or [] + + def _get_spec(self, loader_class, fullname, path, smsl, target): + loader = loader_class(fullname, path) + return spec_from_file_location(fullname, path, loader=loader, + submodule_search_locations=smsl) + + def find_spec(self, fullname, target=None): + """Try to find a loader for the specified module, or the namespace + package portions. Returns (loader, list-of-portions).""" + is_namespace = False + tail_module = fullname.rpartition('.')[2] + try: + mtime = _path_stat(self.path or _os.getcwd()).st_mtime + except OSError: + mtime = -1 + if mtime != self._path_mtime: + self._fill_cache() + self._path_mtime = mtime + # tail_module keeps the original casing, for __file__ and friends + if _relax_case(): + cache = self._relaxed_path_cache + cache_module = tail_module.lower() + else: + cache = self._path_cache + cache_module = tail_module + # Check if the module is the name of a directory (and thus a package). + if cache_module in cache: + base_path = _path_join(self.path, tail_module) + for suffix, loader_class in self._loaders: + init_filename = '__init__' + suffix + full_path = _path_join(base_path, init_filename) + if _path_isfile(full_path): + return self._get_spec(loader_class, fullname, full_path, [base_path], target) + else: + # If a namespace package, return the path if we don't + # find a module in the next section. + is_namespace = _path_isdir(base_path) + # Check for a file w/ a proper suffix exists. + for suffix, loader_class in self._loaders: + full_path = _path_join(self.path, tail_module + suffix) + _verbose_message('trying {}'.format(full_path), verbosity=2) + if cache_module + suffix in cache: + if _path_isfile(full_path): + return self._get_spec(loader_class, fullname, full_path, None, target) + if is_namespace: + _verbose_message('possible namespace for {}'.format(base_path)) + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = [base_path] + return spec + return None + + def _fill_cache(self): + """Fill the cache of potential modules and packages for this directory.""" + path = self.path + try: + contents = _os.listdir(path or _os.getcwd()) + except (FileNotFoundError, PermissionError, NotADirectoryError): + # Directory has either been removed, turned into a file, or made + # unreadable. + contents = [] + # We store two cached versions, to handle runtime changes of the + # PYTHONCASEOK environment variable. + if not sys.platform.startswith('win'): + self._path_cache = set(contents) + else: + # Windows users can import modules with case-insensitive file + # suffixes (for legacy reasons). Make the suffix lowercase here + # so it's done once instead of for every import. This is safe as + # the specified suffixes to check against are always specified in a + # case-sensitive manner. + lower_suffix_contents = set() + for item in contents: + name, dot, suffix = item.partition('.') + if dot: + new_name = '{}.{}'.format(name, suffix.lower()) + else: + new_name = name + lower_suffix_contents.add(new_name) + self._path_cache = lower_suffix_contents + if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): + self._relaxed_path_cache = {fn.lower() for fn in contents} + + @classmethod + def path_hook(cls, *loader_details): + """A class method which returns a closure to use on sys.path_hook + which will return an instance using the specified loaders and the path + called on the closure. + + If the path called on the closure is not a directory, ImportError is + raised. + + """ + def path_hook_for_FileFinder(path): + """Path hook for importlib.machinery.FileFinder.""" + if not _path_isdir(path): + raise ImportError('only directories are supported', path=path) + return cls(path, *loader_details) + + return path_hook_for_FileFinder + + def __repr__(self): + return 'FileFinder({!r})'.format(self.path) + + +# Import setup ############################################################### + +def _fix_up_module(ns, name, pathname, cpathname=None): + # This function is used by PyImport_ExecCodeModuleObject(). + loader = ns.get('__loader__') + spec = ns.get('__spec__') + if not loader: + if spec: + loader = spec.loader + elif pathname == cpathname: + loader = SourcelessFileLoader(name, pathname) + else: + loader = SourceFileLoader(name, pathname) + if not spec: + spec = spec_from_file_location(name, pathname, loader=loader) + try: + ns['__spec__'] = spec + ns['__loader__'] = loader + ns['__file__'] = pathname + ns['__cached__'] = cpathname + except Exception: + # Not important enough to report. + pass + + +def _get_supported_file_loaders(): + """Returns a list of file-based module loaders. + + Each item is a tuple (loader, suffixes). + """ + extensions = ExtensionFileLoader, _imp.extension_suffixes() + source = SourceFileLoader, SOURCE_SUFFIXES + bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES + return [extensions, source, bytecode] + + +def _setup(_bootstrap_module): + """Setup the path-based importers for importlib by importing needed + built-in modules and injecting them into the global namespace. + + Other components are extracted from the core bootstrap module. + + """ + global sys, _imp, _bootstrap + _bootstrap = _bootstrap_module + sys = _bootstrap.sys + _imp = _bootstrap._imp + + # Directly load built-in modules needed during bootstrap. + self_module = sys.modules[__name__] + for builtin_name in ('_io', '_warnings', 'builtins', 'marshal'): + if builtin_name not in sys.modules: + builtin_module = _bootstrap._builtin_from_name(builtin_name) + else: + builtin_module = sys.modules[builtin_name] + setattr(self_module, builtin_name, builtin_module) + + # Directly load the os module (needed during bootstrap). + os_details = ('posix', ['/']), ('nt', ['\\', '/']) + for builtin_os, path_separators in os_details: + # Assumption made in _path_join() + assert all(len(sep) == 1 for sep in path_separators) + path_sep = path_separators[0] + if builtin_os in sys.modules: + os_module = sys.modules[builtin_os] + break + else: + try: + os_module = _bootstrap._builtin_from_name(builtin_os) + break + except ImportError: + continue + else: + raise ImportError('importlib requires posix or nt') + setattr(self_module, '_os', os_module) + setattr(self_module, 'path_sep', path_sep) + setattr(self_module, 'path_separators', ''.join(path_separators)) + + # Directly load the _thread module (needed during bootstrap). + try: + thread_module = _bootstrap._builtin_from_name('_thread') + except ImportError: + # Python was built without threads + thread_module = None + setattr(self_module, '_thread', thread_module) + + # Directly load the _weakref module (needed during bootstrap). + weakref_module = _bootstrap._builtin_from_name('_weakref') + setattr(self_module, '_weakref', weakref_module) + + # Directly load the winreg module (needed during bootstrap). + if builtin_os == 'nt': + winreg_module = _bootstrap._builtin_from_name('winreg') + setattr(self_module, '_winreg', winreg_module) + + # Constants + setattr(self_module, '_relax_case', _make_relax_case()) + EXTENSION_SUFFIXES.extend(_imp.extension_suffixes()) + if builtin_os == 'nt': + SOURCE_SUFFIXES.append('.pyw') + if '_d.pyd' in EXTENSION_SUFFIXES: + WindowsRegistryFinder.DEBUG_BUILD = True + + +def _install(_bootstrap_module): + """Install the path-based import components.""" + _setup(_bootstrap_module) + supported_loaders = _get_supported_file_loaders() + sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) + if _os.__name__ == 'nt': + sys.meta_path.append(WindowsRegistryFinder) + sys.meta_path.append(PathFinder) + + # XXX We expose a couple of classes in _bootstrap for the sake of + # a setuptools bug (https://bitbucket.org/pypa/setuptools/issue/378). + _bootstrap_module.FileFinder = FileFinder + _bootstrap_module.SourceFileLoader = SourceFileLoader diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -1,12 +1,17 @@ """Abstract base classes related to import.""" -from . import _bootstrap +from . import _bootstrap_external from . import machinery try: import _frozen_importlib +# import _frozen_importlib_external except ImportError as exc: if exc.name != '_frozen_importlib': raise _frozen_importlib = None +try: + import _frozen_importlib_external +except ImportError as exc: + _frozen_importlib_external = _bootstrap_external import abc @@ -14,7 +19,10 @@ for cls in classes: abstract_cls.register(cls) if _frozen_importlib is not None: - frozen_cls = getattr(_frozen_importlib, cls.__name__) + try: + frozen_cls = getattr(_frozen_importlib, cls.__name__) + except AttributeError: + frozen_cls = getattr(_frozen_importlib_external, cls.__name__) abstract_cls.register(frozen_cls) @@ -102,7 +110,7 @@ else: return None, [] - find_module = _bootstrap._find_module_shim + find_module = _bootstrap_external._find_module_shim def invalidate_caches(self): """An optional method for clearing the finder's cache, if any. @@ -144,7 +152,7 @@ """ if not hasattr(self, 'exec_module'): raise ImportError - return _bootstrap._load_module_shim(self, fullname) + return _bootstrap_external._load_module_shim(self, fullname) def module_repr(self, module): """Return a module's repr. @@ -222,8 +230,8 @@ argument should be where the data was retrieved (when applicable).""" return compile(data, path, 'exec', dont_inherit=True) - exec_module = _bootstrap._LoaderBasics.exec_module - load_module = _bootstrap._LoaderBasics.load_module + exec_module = _bootstrap_external._LoaderBasics.exec_module + load_module = _bootstrap_external._LoaderBasics.load_module _register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter) @@ -265,7 +273,7 @@ _register(ExecutionLoader, machinery.ExtensionFileLoader) -class FileLoader(_bootstrap.FileLoader, ResourceLoader, ExecutionLoader): +class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader): """Abstract base class partially implementing the ResourceLoader and ExecutionLoader ABCs.""" @@ -274,7 +282,7 @@ machinery.SourcelessFileLoader) -class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): +class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader): """Abstract base class for loading source code (and optionally any corresponding bytecode). diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -2,18 +2,18 @@ import _imp -from ._bootstrap import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES, - OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES, - EXTENSION_SUFFIXES) from ._bootstrap import ModuleSpec from ._bootstrap import BuiltinImporter from ._bootstrap import FrozenImporter -from ._bootstrap import WindowsRegistryFinder -from ._bootstrap import PathFinder -from ._bootstrap import FileFinder -from ._bootstrap import SourceFileLoader -from ._bootstrap import SourcelessFileLoader -from ._bootstrap import ExtensionFileLoader +from ._bootstrap_external import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES, + OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES, + EXTENSION_SUFFIXES) +from ._bootstrap_external import WindowsRegistryFinder +from ._bootstrap_external import PathFinder +from ._bootstrap_external import FileFinder +from ._bootstrap_external import SourceFileLoader +from ._bootstrap_external import SourcelessFileLoader +from ._bootstrap_external import ExtensionFileLoader def all_suffixes(): diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -1,14 +1,14 @@ """Utility code for constructing importers, etc.""" from . import abc -from ._bootstrap import MAGIC_NUMBER -from ._bootstrap import cache_from_source -from ._bootstrap import decode_source from ._bootstrap import module_from_spec -from ._bootstrap import source_from_cache +from ._bootstrap import _resolve_name from ._bootstrap import spec_from_loader -from ._bootstrap import spec_from_file_location -from ._bootstrap import _resolve_name from ._bootstrap import _find_spec +from ._bootstrap_external import MAGIC_NUMBER +from ._bootstrap_external import cache_from_source +from ._bootstrap_external import decode_source +from ._bootstrap_external import source_from_cache +from ._bootstrap_external import spec_from_file_location from contextlib import contextmanager import functools diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -1,7 +1,7 @@ """Find modules used by a script, using introspection.""" import dis -import importlib._bootstrap +import importlib._bootstrap_external import importlib.machinery import marshal import os @@ -289,7 +289,7 @@ co = compile(fp.read()+'\n', pathname, 'exec') elif type == imp.PY_COMPILED: try: - marshal_data = importlib._bootstrap._validate_bytecode_header(fp.read()) + marshal_data = importlib._bootstrap_external._validate_bytecode_header(fp.read()) except ImportError as exc: self.msgout(2, "raise ImportError: " + str(exc), pathname) raise diff --git a/Lib/py_compile.py b/Lib/py_compile.py --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -3,7 +3,7 @@ This module has intimate knowledge of the format of .pyc files. """ -import importlib._bootstrap +import importlib._bootstrap_external import importlib.machinery import importlib.util import os @@ -137,10 +137,10 @@ except FileExistsError: pass source_stats = loader.path_stats(file) - bytecode = importlib._bootstrap._code_to_bytecode( + bytecode = importlib._bootstrap_external._code_to_bytecode( code, source_stats['mtime'], source_stats['size']) - mode = importlib._bootstrap._calc_mode(file) - importlib._bootstrap._write_atomic(cfile, bytecode, mode) + mode = importlib._bootstrap_external._calc_mode(file) + importlib._bootstrap_external._write_atomic(cfile, bytecode, mode) return cfile diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -53,6 +53,7 @@ import builtins import importlib._bootstrap +import importlib._bootstrap_external import importlib.machinery import importlib.util import inspect @@ -292,9 +293,9 @@ filename = os.path.basename(path) name, ext = os.path.splitext(filename) if is_bytecode: - loader = importlib._bootstrap.SourcelessFileLoader(name, path) + loader = importlib._bootstrap_external.SourcelessFileLoader(name, path) else: - loader = importlib._bootstrap.SourceFileLoader(name, path) + loader = importlib._bootstrap_external.SourceFileLoader(name, path) # XXX We probably don't need to pass in the loader here. spec = importlib.util.spec_from_file_location(name, path, loader=loader) try: diff --git a/Lib/runpy.py b/Lib/runpy.py --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -58,7 +58,7 @@ self.value = self._sentinel sys.argv[0] = self._saved_value -# TODO: Replace these helpers with importlib._bootstrap functions +# TODO: Replace these helpers with importlib._bootstrap_external functions. def _run_code(code, run_globals, init_globals=None, mod_name=None, mod_spec=None, pkg_name=None, script_name=None): diff --git a/Lib/site.py b/Lib/site.py --- a/Lib/site.py +++ b/Lib/site.py @@ -98,8 +98,8 @@ def abs_paths(): """Set all module __file__ and __cached__ attributes to an absolute path""" for m in set(sys.modules.values()): - if (getattr(getattr(m, '__loader__', None), '__module__', None) != - '_frozen_importlib'): + if (getattr(getattr(m, '__loader__', None), '__module__', None) not in + ('_frozen_importlib', '_frozen_importlib_external')): continue # don't mess with a PEP 302-supplied __file__ try: m.__file__ = os.path.abspath(m.__file__) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1,7 +1,7 @@ # We import importlib *ASAP* in order to test #15386 import importlib import importlib.util -from importlib._bootstrap import _get_sourcefile +from importlib._bootstrap_external import _get_sourcefile import builtins import marshal import os @@ -845,19 +845,27 @@ self.assertEqual(mod.__package__, 'importlib') self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__) + def test_frozen_importlib_external_is_bootstrap_external(self): + from importlib import _bootstrap_external + mod = sys.modules['_frozen_importlib_external'] + self.assertIs(mod, _bootstrap_external) + self.assertEqual(mod.__name__, 'importlib._bootstrap_external') + self.assertEqual(mod.__package__, 'importlib') + self.assertTrue(mod.__file__.endswith('_bootstrap_external.py'), mod.__file__) + def test_there_can_be_only_one(self): # Issue #15386 revealed a tricky loophole in the bootstrapping # This test is technically redundant, since the bug caused importing # this test module to crash completely, but it helps prove the point from importlib import machinery mod = sys.modules['_frozen_importlib'] - self.assertIs(machinery.FileFinder, mod.FileFinder) + self.assertIs(machinery.ModuleSpec, mod.ModuleSpec) @cpython_only class GetSourcefileTests(unittest.TestCase): - """Test importlib._bootstrap._get_sourcefile() as used by the C API. + """Test importlib._bootstrap_external._get_sourcefile() as used by the C API. Because of the peculiarities of the need of this function, the tests are knowingly whitebox tests. @@ -867,7 +875,7 @@ def test_get_sourcefile(self): # Given a valid bytecode path, return the path to the corresponding # source file if it exists. - with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile: + with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: _path_isfile.return_value = True; path = TESTFN + '.pyc' expect = TESTFN + '.py' @@ -876,7 +884,7 @@ def test_get_sourcefile_no_source(self): # Given a valid bytecode path without a corresponding source path, # return the original bytecode path. - with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile: + with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: _path_isfile.return_value = False; path = TESTFN + '.pyc' self.assertEqual(_get_sourcefile(path), path) @@ -1031,7 +1039,7 @@ # We simulate a bug in importlib and check that it's not stripped # away from the traceback. self.create_module("foo", "") - importlib = sys.modules['_frozen_importlib'] + importlib = sys.modules['_frozen_importlib_external'] if 'load_module' in vars(importlib.SourceLoader): old_exec_module = importlib.SourceLoader.exec_module else: diff --git a/Lib/test/test_importlib/extension/test_case_sensitivity.py b/Lib/test/test_importlib/extension/test_case_sensitivity.py --- a/Lib/test/test_importlib/extension/test_case_sensitivity.py +++ b/Lib/test/test_importlib/extension/test_case_sensitivity.py @@ -1,4 +1,4 @@ -from importlib import _bootstrap +from importlib import _bootstrap_external import sys from test import support import unittest @@ -26,7 +26,7 @@ def test_case_sensitive(self): with support.EnvironmentVarGuard() as env: env.unset('PYTHONCASEOK') - if b'PYTHONCASEOK' in _bootstrap._os.environ: + if b'PYTHONCASEOK' in _bootstrap_external._os.environ: self.skipTest('os.environ changes not reflected in ' '_os.environ') loader = self.find_module() @@ -35,7 +35,7 @@ def test_case_insensitivity(self): with support.EnvironmentVarGuard() as env: env.set('PYTHONCASEOK', '1') - if b'PYTHONCASEOK' not in _bootstrap._os.environ: + if b'PYTHONCASEOK' not in _bootstrap_external._os.environ: self.skipTest('os.environ changes not reflected in ' '_os.environ') loader = self.find_module() diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py --- a/Lib/test/test_importlib/import_/test_path.py +++ b/Lib/test/test_importlib/import_/test_path.py @@ -99,7 +99,7 @@ new_path_importer_cache.pop(None, None) new_path_hooks = [zipimport.zipimporter, self.machinery.FileFinder.path_hook( - *self.importlib._bootstrap._get_supported_file_loaders())] + *self.importlib._bootstrap_external._get_supported_file_loaders())] missing = object() email = sys.modules.pop('email', missing) try: diff --git a/Lib/test/test_importlib/source/test_case_sensitivity.py b/Lib/test/test_importlib/source/test_case_sensitivity.py --- a/Lib/test/test_importlib/source/test_case_sensitivity.py +++ b/Lib/test/test_importlib/source/test_case_sensitivity.py @@ -42,7 +42,7 @@ def test_sensitive(self): with test_support.EnvironmentVarGuard() as env: env.unset('PYTHONCASEOK') - if b'PYTHONCASEOK' in self.importlib._bootstrap._os.environ: + if b'PYTHONCASEOK' in self.importlib._bootstrap_external._os.environ: self.skipTest('os.environ changes not reflected in ' '_os.environ') sensitive, insensitive = self.sensitivity_test() @@ -53,7 +53,7 @@ def test_insensitive(self): with test_support.EnvironmentVarGuard() as env: env.set('PYTHONCASEOK', '1') - if b'PYTHONCASEOK' not in self.importlib._bootstrap._os.environ: + if b'PYTHONCASEOK' not in self.importlib._bootstrap_external._os.environ: self.skipTest('os.environ changes not reflected in ' '_os.environ') sensitive, insensitive = self.sensitivity_test() diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -355,8 +355,10 @@ stdout, stderr = proc.communicate() self.assertEqual(proc.returncode, 0) os__file__, os__cached__ = stdout.splitlines()[:2] - self.assertTrue(os.path.isabs(os__file__)) - self.assertTrue(os.path.isabs(os__cached__)) + self.assertTrue(os.path.isabs(os__file__), + "expected absolute path, got {}".format(os__file__)) + self.assertTrue(os.path.isabs(os__cached__), + "expected absolute path, got {}".format(os__cached__)) def test_no_duplicate_paths(self): # No duplicate paths should exist in sys.path diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -533,6 +533,7 @@ : # force rebuilding of parser and importlib @touch $(GRAMMAR_INPUT) @touch $(srcdir)/Lib/importlib/_bootstrap.py + @touch $(srcdir)/Lib/importlib/_bootstrap_external.py : # build with coverage info $(MAKE) coverage : # run tests, ignore failures @@ -694,6 +695,10 @@ Programs/_freeze_importlib: Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LINKCC) $(PY_LDFLAGS) -o $@ Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) +Python/importlib_external.h: $(srcdir)/Lib/importlib/_bootstrap_external.py Programs/_freeze_importlib + ./Programs/_freeze_importlib \ + $(srcdir)/Lib/importlib/_bootstrap_external.py Python/importlib_external.h + Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py Programs/_freeze_importlib ./Programs/_freeze_importlib \ $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h @@ -841,7 +846,7 @@ Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h -Python/frozen.o: Python/importlib.h +Python/frozen.o: Python/importlib.h Python/importlib_external.h Objects/typeobject.o: Objects/typeslots.inc Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ - Issue #23910: Optimize property() getter calls. Patch by Joe Jevnik. +- Issue #23911: Move path-based importlib bootstrap code to a separate + frozen module. + - Issue #24022: Fix tokenizer crash when processing undecodable source code. - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -12,6 +12,7 @@ #include #endif +int Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ /* To avoid a circular dependency on frozen.o, we create our own structure of frozen modules instead, left deliberately blank so as to avoid @@ -33,13 +34,14 @@ int main(int argc, char *argv[]) { - char *inpath, *outpath; + char *inpath, *outpath, *code_name; FILE *infile = NULL, *outfile = NULL; struct _Py_stat_struct status; size_t text_size, data_size, n; char *text = NULL; unsigned char *data; PyObject *code = NULL, *marshalled = NULL; + int is_bootstrap = 1; PyImport_FrozenModules = _PyImport_FrozenModules; @@ -82,8 +84,14 @@ /* Don't install importlib, since it could execute outdated bytecode. */ _Py_InitializeEx_Private(1, 0); - code = Py_CompileStringExFlags(text, "", - Py_file_input, NULL, 0); + if (strstr(inpath, "_external") != NULL) { + is_bootstrap = 0; + } + + code_name = is_bootstrap ? + "" : + ""; + code = Py_CompileStringExFlags(text, code_name, Py_file_input, NULL, 0); if (code == NULL) goto error; free(text); @@ -106,7 +114,11 @@ goto error; } fprintf(outfile, "%s\n", header); - fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n"); + if (is_bootstrap) + fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n"); + else + fprintf(outfile, + "const unsigned char _Py_M__importlib_external[] = {\n"); for (n = 0; n < data_size; n += 16) { size_t i, end = Py_MIN(n + 16, data_size); fprintf(outfile, " "); diff --git a/Python/frozen.c b/Python/frozen.c --- a/Python/frozen.c +++ b/Python/frozen.c @@ -3,6 +3,7 @@ #include "Python.h" #include "importlib.h" +#include "importlib_external.h" /* In order to test the support for frozen modules, by default we define a single frozen module, __hello__. Loading it will print @@ -31,6 +32,8 @@ static const struct _frozen _PyImport_FrozenModules[] = { /* importlib */ {"_frozen_importlib", _Py_M__importlib, (int)sizeof(_Py_M__importlib)}, + {"_frozen_importlib_external", _Py_M__importlib_external, + (int)sizeof(_Py_M__importlib_external)}, /* Test module */ {"__hello__", M___hello__, SIZE}, /* Test package (negative size indicates package-ness) */ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -491,8 +491,13 @@ { long res; PyInterpreterState *interp = PyThreadState_Get()->interp; - PyObject *pyc_magic = PyObject_GetAttrString(interp->importlib, - "_RAW_MAGIC_NUMBER"); + PyObject *external, *pyc_magic; + + external = PyObject_GetAttrString(interp->importlib, "_bootstrap_external"); + if (external == NULL) + return -1; + pyc_magic = PyObject_GetAttrString(external, "_RAW_MAGIC_NUMBER"); + Py_DECREF(external); if (pyc_magic == NULL) return -1; res = PyLong_AsLong(pyc_magic); @@ -737,7 +742,7 @@ const char *cpathname) { PyObject *m = NULL; - PyObject *nameobj, *pathobj = NULL, *cpathobj = NULL; + PyObject *nameobj, *pathobj = NULL, *cpathobj = NULL, *external= NULL; nameobj = PyUnicode_FromString(name); if (nameobj == NULL) @@ -765,9 +770,14 @@ "no interpreter!"); } - pathobj = _PyObject_CallMethodIdObjArgs(interp->importlib, - &PyId__get_sourcefile, cpathobj, - NULL); + external= PyObject_GetAttrString(interp->importlib, + "_bootstrap_external"); + if (external != NULL) { + pathobj = _PyObject_CallMethodIdObjArgs(external, + &PyId__get_sourcefile, cpathobj, + NULL); + Py_DECREF(external); + } if (pathobj == NULL) PyErr_Clear(); } @@ -833,7 +843,7 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, PyObject *cpathname) { - PyObject *d, *res; + PyObject *d, *external, *res; PyInterpreterState *interp = PyThreadState_GET()->interp; _Py_IDENTIFIER(_fix_up_module); @@ -845,9 +855,13 @@ if (pathname == NULL) { pathname = ((PyCodeObject *)co)->co_filename; } - res = _PyObject_CallMethodIdObjArgs(interp->importlib, + external = PyObject_GetAttrString(interp->importlib, "_bootstrap_external"); + if (external == NULL) + return NULL; + res = _PyObject_CallMethodIdObjArgs(external, &PyId__fix_up_module, d, name, pathname, cpathname, NULL); + Py_DECREF(external); if (res != NULL) { Py_DECREF(res); res = exec_code_in_module(name, d, co); @@ -1245,6 +1259,7 @@ remove_importlib_frames(void) { const char *importlib_filename = ""; + const char *external_filename = ""; const char *remove_frames = "_call_with_frames_removed"; int always_trim = 0; int in_importlib = 0; @@ -1274,7 +1289,10 @@ assert(PyTraceBack_Check(tb)); now_in_importlib = (PyUnicode_CompareWithASCIIString( code->co_filename, - importlib_filename) == 0); + importlib_filename) == 0) || + (PyUnicode_CompareWithASCIIString( + code->co_filename, + external_filename) == 0); if (now_in_importlib && !in_importlib) { /* This is the link to this chunk of importlib tracebacks */ outer_link = prev_link; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/Python/importlib_external.h b/Python/importlib_external.h new file mode 100644 --- /dev/null +++ b/Python/importlib_external.h @@ -0,0 +1,2633 @@ +/* Auto-generated by Programs/_freeze_importlib.c */ +const unsigned char _Py_M__importlib_external[] = { + 99,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, + 0,64,0,0,0,115,2,3,0,0,100,0,0,90,0,0, + 100,102,0,90,1,0,100,4,0,100,5,0,132,0,0,90, + 2,0,100,6,0,100,7,0,132,0,0,90,3,0,100,8, + 0,100,9,0,132,0,0,90,4,0,100,10,0,100,11,0, + 132,0,0,90,5,0,100,12,0,100,13,0,132,0,0,90, + 6,0,100,14,0,100,15,0,132,0,0,90,7,0,100,16, + 0,100,17,0,132,0,0,90,8,0,100,18,0,100,19,0, + 132,0,0,90,9,0,100,20,0,100,21,0,132,0,0,90, + 10,0,100,22,0,100,23,0,100,24,0,132,1,0,90,11, + 0,101,12,0,101,11,0,106,13,0,131,1,0,90,14,0, + 100,25,0,106,15,0,100,26,0,100,27,0,131,2,0,100, + 28,0,23,90,16,0,101,17,0,106,18,0,101,16,0,100, + 27,0,131,2,0,90,19,0,100,29,0,90,20,0,100,30, + 0,90,21,0,100,31,0,103,1,0,90,22,0,100,32,0, + 103,1,0,90,23,0,101,23,0,4,90,24,0,90,25,0, + 100,33,0,100,34,0,100,33,0,100,35,0,100,36,0,132, + 1,1,90,26,0,100,37,0,100,38,0,132,0,0,90,27, + 0,100,39,0,100,40,0,132,0,0,90,28,0,100,41,0, + 100,42,0,132,0,0,90,29,0,100,43,0,100,44,0,132, + 0,0,90,30,0,100,45,0,100,46,0,100,47,0,100,48, + 0,132,0,1,90,31,0,100,49,0,100,50,0,132,0,0, + 90,32,0,100,51,0,100,52,0,132,0,0,90,33,0,100, + 53,0,100,54,0,132,0,0,90,34,0,100,33,0,100,33, + 0,100,33,0,100,55,0,100,56,0,132,3,0,90,35,0, + 100,33,0,100,33,0,100,33,0,100,57,0,100,58,0,132, + 3,0,90,36,0,100,59,0,100,59,0,100,60,0,100,61, + 0,132,2,0,90,37,0,100,62,0,100,63,0,132,0,0, + 90,38,0,100,64,0,100,33,0,100,65,0,100,33,0,100, + 66,0,100,67,0,132,0,2,90,39,0,101,40,0,131,0, + 0,90,41,0,100,33,0,100,68,0,100,33,0,100,69,0, + 101,41,0,100,70,0,100,71,0,132,1,2,90,42,0,71, + 100,72,0,100,73,0,132,0,0,100,73,0,131,2,0,90, + 43,0,71,100,74,0,100,75,0,132,0,0,100,75,0,131, + 2,0,90,44,0,71,100,76,0,100,77,0,132,0,0,100, + 77,0,101,44,0,131,3,0,90,45,0,71,100,78,0,100, + 79,0,132,0,0,100,79,0,131,2,0,90,46,0,71,100, + 80,0,100,81,0,132,0,0,100,81,0,101,46,0,101,45, + 0,131,4,0,90,47,0,71,100,82,0,100,83,0,132,0, + 0,100,83,0,101,46,0,101,44,0,131,4,0,90,48,0, + 103,0,0,90,49,0,71,100,84,0,100,85,0,132,0,0, + 100,85,0,131,2,0,90,50,0,71,100,86,0,100,87,0, + 132,0,0,100,87,0,131,2,0,90,51,0,71,100,88,0, + 100,89,0,132,0,0,100,89,0,131,2,0,90,52,0,71, + 100,90,0,100,91,0,132,0,0,100,91,0,131,2,0,90, + 53,0,71,100,92,0,100,93,0,132,0,0,100,93,0,131, + 2,0,90,54,0,100,33,0,100,94,0,100,95,0,132,1, + 0,90,55,0,100,96,0,100,97,0,132,0,0,90,56,0, + 100,98,0,100,99,0,132,0,0,90,57,0,100,100,0,100, + 101,0,132,0,0,90,58,0,100,33,0,83,41,103,97,94, + 1,0,0,67,111,114,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,112,97,116,104,45,98, + 97,115,101,100,32,105,109,112,111,114,116,46,10,10,84,104, + 105,115,32,109,111,100,117,108,101,32,105,115,32,78,79,84, + 32,109,101,97,110,116,32,116,111,32,98,101,32,100,105,114, + 101,99,116,108,121,32,105,109,112,111,114,116,101,100,33,32, + 73,116,32,104,97,115,32,98,101,101,110,32,100,101,115,105, + 103,110,101,100,32,115,117,99,104,10,116,104,97,116,32,105, + 116,32,99,97,110,32,98,101,32,98,111,111,116,115,116,114, + 97,112,112,101,100,32,105,110,116,111,32,80,121,116,104,111, + 110,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,114, + 116,46,32,65,115,10,115,117,99,104,32,105,116,32,114,101, + 113,117,105,114,101,115,32,116,104,101,32,105,110,106,101,99, + 116,105,111,110,32,111,102,32,115,112,101,99,105,102,105,99, + 32,109,111,100,117,108,101,115,32,97,110,100,32,97,116,116, + 114,105,98,117,116,101,115,32,105,110,32,111,114,100,101,114, + 32,116,111,10,119,111,114,107,46,32,79,110,101,32,115,104, + 111,117,108,100,32,117,115,101,32,105,109,112,111,114,116,108, + 105,98,32,97,115,32,116,104,101,32,112,117,98,108,105,99, + 45,102,97,99,105,110,103,32,118,101,114,115,105,111,110,32, + 111,102,32,116,104,105,115,32,109,111,100,117,108,101,46,10, + 10,218,3,119,105,110,218,6,99,121,103,119,105,110,218,6, + 100,97,114,119,105,110,99,0,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,67,0,0,0,115,49,0,0,0, + 116,0,0,106,1,0,106,2,0,116,3,0,131,1,0,114, + 33,0,100,1,0,100,2,0,132,0,0,125,0,0,110,12, + 0,100,3,0,100,2,0,132,0,0,125,0,0,124,0,0, + 83,41,4,78,99,0,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,83,0,0,0,115,13,0,0,0,100,1, + 0,116,0,0,106,1,0,107,6,0,83,41,2,122,53,84, + 114,117,101,32,105,102,32,102,105,108,101,110,97,109,101,115, + 32,109,117,115,116,32,98,101,32,99,104,101,99,107,101,100, + 32,99,97,115,101,45,105,110,115,101,110,115,105,116,105,118, + 101,108,121,46,115,12,0,0,0,80,89,84,72,79,78,67, + 65,83,69,79,75,41,2,218,3,95,111,115,90,7,101,110, + 118,105,114,111,110,169,0,114,4,0,0,0,114,4,0,0, + 0,250,38,60,102,114,111,122,101,110,32,105,109,112,111,114, + 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,95, + 101,120,116,101,114,110,97,108,62,218,11,95,114,101,108,97, + 120,95,99,97,115,101,30,0,0,0,115,2,0,0,0,0, + 2,122,37,95,109,97,107,101,95,114,101,108,97,120,95,99, + 97,115,101,46,60,108,111,99,97,108,115,62,46,95,114,101, + 108,97,120,95,99,97,115,101,99,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,83,0,0,0,115,4,0, + 0,0,100,1,0,83,41,2,122,53,84,114,117,101,32,105, + 102,32,102,105,108,101,110,97,109,101,115,32,109,117,115,116, + 32,98,101,32,99,104,101,99,107,101,100,32,99,97,115,101, + 45,105,110,115,101,110,115,105,116,105,118,101,108,121,46,70, + 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,6,0,0,0,34,0, + 0,0,115,2,0,0,0,0,2,41,4,218,3,115,121,115, + 218,8,112,108,97,116,102,111,114,109,218,10,115,116,97,114, + 116,115,119,105,116,104,218,27,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,41,1,114,6,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,16,95,109,97,107,101, + 95,114,101,108,97,120,95,99,97,115,101,28,0,0,0,115, + 8,0,0,0,0,1,18,1,15,4,12,3,114,11,0,0, + 0,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, + 0,0,67,0,0,0,115,26,0,0,0,116,0,0,124,0, + 0,131,1,0,100,1,0,64,106,1,0,100,2,0,100,3, + 0,131,2,0,83,41,4,122,42,67,111,110,118,101,114,116, + 32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101, + 114,32,116,111,32,108,105,116,116,108,101,45,101,110,100,105, + 97,110,46,108,3,0,0,0,255,127,255,127,3,0,233,4, + 0,0,0,218,6,108,105,116,116,108,101,41,2,218,3,105, + 110,116,218,8,116,111,95,98,121,116,101,115,41,1,218,1, + 120,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,7,95,119,95,108,111,110,103,40,0,0,0,115,2,0, + 0,0,0,2,114,17,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,16, + 0,0,0,116,0,0,106,1,0,124,0,0,100,1,0,131, + 2,0,83,41,2,122,47,67,111,110,118,101,114,116,32,52, + 32,98,121,116,101,115,32,105,110,32,108,105,116,116,108,101, + 45,101,110,100,105,97,110,32,116,111,32,97,110,32,105,110, + 116,101,103,101,114,46,114,13,0,0,0,41,2,114,14,0, + 0,0,218,10,102,114,111,109,95,98,121,116,101,115,41,1, + 90,9,105,110,116,95,98,121,116,101,115,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,7,95,114,95,108, + 111,110,103,45,0,0,0,115,2,0,0,0,0,2,114,19, + 0,0,0,99,0,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,71,0,0,0,115,26,0,0,0,116,0,0, + 106,1,0,100,1,0,100,2,0,132,0,0,124,0,0,68, + 131,1,0,131,1,0,83,41,3,122,31,82,101,112,108,97, + 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, + 116,104,46,106,111,105,110,40,41,46,99,1,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,83,0,0,0,115, + 37,0,0,0,103,0,0,124,0,0,93,27,0,125,1,0, + 124,1,0,114,6,0,124,1,0,106,0,0,116,1,0,131, + 1,0,145,2,0,113,6,0,83,114,4,0,0,0,41,2, + 218,6,114,115,116,114,105,112,218,15,112,97,116,104,95,115, + 101,112,97,114,97,116,111,114,115,41,2,218,2,46,48,218, + 4,112,97,114,116,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,250,10,60,108,105,115,116,99,111,109,112,62, + 52,0,0,0,115,2,0,0,0,9,1,122,30,95,112,97, + 116,104,95,106,111,105,110,46,60,108,111,99,97,108,115,62, + 46,60,108,105,115,116,99,111,109,112,62,41,2,218,8,112, + 97,116,104,95,115,101,112,218,4,106,111,105,110,41,1,218, + 10,112,97,116,104,95,112,97,114,116,115,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,10,95,112,97,116, + 104,95,106,111,105,110,50,0,0,0,115,4,0,0,0,0, + 2,15,1,114,28,0,0,0,99,1,0,0,0,0,0,0, + 0,5,0,0,0,5,0,0,0,67,0,0,0,115,134,0, + 0,0,116,0,0,116,1,0,131,1,0,100,1,0,107,2, + 0,114,52,0,124,0,0,106,2,0,116,3,0,131,1,0, + 92,3,0,125,1,0,125,2,0,125,3,0,124,1,0,124, + 3,0,102,2,0,83,120,69,0,116,4,0,124,0,0,131, + 1,0,68,93,55,0,125,4,0,124,4,0,116,1,0,107, + 6,0,114,65,0,124,0,0,106,5,0,124,4,0,100,2, + 0,100,1,0,131,1,1,92,2,0,125,1,0,125,3,0, + 124,1,0,124,3,0,102,2,0,83,113,65,0,87,100,3, + 0,124,0,0,102,2,0,83,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,90,8,109,97,120,115,112,108,105,116,218,0,41,6,218, + 3,108,101,110,114,21,0,0,0,218,10,114,112,97,114,116, + 105,116,105,111,110,114,25,0,0,0,218,8,114,101,118,101, + 114,115,101,100,218,6,114,115,112,108,105,116,41,5,218,4, + 112,97,116,104,90,5,102,114,111,110,116,218,1,95,218,4, + 116,97,105,108,114,16,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,11,95,112,97,116,104,95, + 115,112,108,105,116,56,0,0,0,115,16,0,0,0,0,2, + 18,1,24,1,10,1,19,1,12,1,27,1,14,1,114,38, + 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,13,0,0,0,116,0,0, + 106,1,0,124,0,0,131,1,0,83,41,1,122,126,83,116, + 97,116,32,116,104,101,32,112,97,116,104,46,10,10,32,32, + 32,32,77,97,100,101,32,97,32,115,101,112,97,114,97,116, + 101,32,102,117,110,99,116,105,111,110,32,116,111,32,109,97, + 107,101,32,105,116,32,101,97,115,105,101,114,32,116,111,32, + 111,118,101,114,114,105,100,101,32,105,110,32,101,120,112,101, + 114,105,109,101,110,116,115,10,32,32,32,32,40,101,46,103, + 46,32,99,97,99,104,101,32,115,116,97,116,32,114,101,115, + 117,108,116,115,41,46,10,10,32,32,32,32,41,2,114,3, + 0,0,0,90,4,115,116,97,116,41,1,114,35,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 10,95,112,97,116,104,95,115,116,97,116,68,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,11,0,0,0,67,0,0,0, + 115,58,0,0,0,121,16,0,116,0,0,124,0,0,131,1, + 0,125,2,0,87,110,22,0,4,116,1,0,107,10,0,114, + 40,0,1,1,1,100,1,0,83,89,110,1,0,88,124,2, + 0,106,2,0,100,2,0,64,124,1,0,107,2,0,83,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,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,18,95,112,97,116, + 104,95,105,115,95,109,111,100,101,95,116,121,112,101,78,0, + 0,0,115,10,0,0,0,0,2,3,1,16,1,13,1,9, + 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,13,0,0,0, + 116,0,0,124,0,0,100,1,0,131,2,0,83,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,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,12,95,112,97,116,104,95,105,115,102,105,108,101, + 87,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,31,0,0,0,124,0,0,115,18,0, + 116,0,0,106,1,0,131,0,0,125,0,0,116,2,0,124, + 0,0,100,1,0,131,2,0,83,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,3,0,0,0,218,6,103,101,116,99,119,100,114, + 43,0,0,0,41,1,114,35,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,11,95,112,97,116, + 104,95,105,115,100,105,114,92,0,0,0,115,6,0,0,0, + 0,2,6,1,12,1,114,46,0,0,0,105,182,1,0,0, + 99,3,0,0,0,0,0,0,0,6,0,0,0,17,0,0, + 0,67,0,0,0,115,192,0,0,0,100,1,0,106,0,0, + 124,0,0,116,1,0,124,0,0,131,1,0,131,2,0,125, + 3,0,116,2,0,106,3,0,124,3,0,116,2,0,106,4, + 0,116,2,0,106,5,0,66,116,2,0,106,6,0,66,124, + 2,0,100,2,0,64,131,3,0,125,4,0,121,60,0,116, + 7,0,106,8,0,124,4,0,100,3,0,131,2,0,143,20, + 0,125,5,0,124,5,0,106,9,0,124,1,0,131,1,0, + 1,87,100,4,0,81,88,116,2,0,106,10,0,124,3,0, + 124,0,0,131,2,0,1,87,110,59,0,4,116,11,0,107, + 10,0,114,187,0,1,1,1,121,17,0,116,2,0,106,12, + 0,124,3,0,131,1,0,1,87,110,18,0,4,116,11,0, + 107,10,0,114,179,0,1,1,1,89,110,1,0,88,130,0, + 0,89,110,1,0,88,100,4,0,83,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, + 3,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,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,13,95,119,114,105,116,101,95,97,116,111, + 109,105,99,99,0,0,0,115,26,0,0,0,0,5,24,1, + 9,1,33,1,3,3,21,1,19,1,20,1,13,1,3,1, + 17,1,13,1,5,1,114,55,0,0,0,105,248,12,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, + 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,87,1,0,0,124,1,0,100,1,0,107,9, + 0,114,76,0,116,0,0,106,1,0,100,2,0,116,2,0, + 131,2,0,1,124,2,0,100,1,0,107,9,0,114,58,0, + 100,3,0,125,3,0,116,3,0,124,3,0,131,1,0,130, + 1,0,124,1,0,114,70,0,100,4,0,110,3,0,100,5, + 0,125,2,0,116,4,0,124,0,0,131,1,0,92,2,0, + 125,4,0,125,5,0,124,5,0,106,5,0,100,6,0,131, + 1,0,92,3,0,125,6,0,125,7,0,125,8,0,116,6, + 0,106,7,0,106,8,0,125,9,0,124,9,0,100,1,0, + 107,8,0,114,154,0,116,9,0,100,7,0,131,1,0,130, + 1,0,100,4,0,106,10,0,124,6,0,114,172,0,124,6, + 0,110,3,0,124,8,0,124,7,0,124,9,0,103,3,0, + 131,1,0,125,10,0,124,2,0,100,1,0,107,8,0,114, + 241,0,116,6,0,106,11,0,106,12,0,100,8,0,107,2, + 0,114,229,0,100,4,0,125,2,0,110,12,0,116,6,0, + 106,11,0,106,12,0,125,2,0,116,13,0,124,2,0,131, + 1,0,125,2,0,124,2,0,100,4,0,107,3,0,114,63, + 1,124,2,0,106,14,0,131,0,0,115,42,1,116,15,0, + 100,9,0,106,16,0,124,2,0,131,1,0,131,1,0,130, + 1,0,100,10,0,106,16,0,124,10,0,116,17,0,124,2, + 0,131,3,0,125,10,0,116,18,0,124,4,0,116,19,0, + 124,10,0,116,20,0,100,8,0,25,23,131,3,0,83,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,21,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,38, + 0,0,0,114,32,0,0,0,114,7,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,47,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,57,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,17,99,97,99,104,101,95,102,114,111,109,95,115,111,117, + 114,99,101,240,0,0,0,115,46,0,0,0,0,18,12,1, + 9,1,7,1,12,1,6,1,12,1,18,1,18,1,24,1, + 12,1,12,1,12,1,36,1,12,1,18,1,9,2,12,1, + 12,1,12,1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0,106, + 2,0,100,1,0,107,8,0,114,30,0,116,3,0,100,2, + 0,131,1,0,130,1,0,116,4,0,124,0,0,131,1,0, + 92,2,0,125,1,0,125,2,0,116,4,0,124,1,0,131, + 1,0,92,2,0,125,1,0,125,3,0,124,3,0,116,5, + 0,107,3,0,114,102,0,116,6,0,100,3,0,106,7,0, + 116,5,0,124,0,0,131,2,0,131,1,0,130,1,0,124, + 2,0,106,8,0,100,4,0,131,1,0,125,4,0,124,4, + 0,100,11,0,107,7,0,114,153,0,116,6,0,100,7,0, + 106,7,0,124,2,0,131,1,0,131,1,0,130,1,0,110, + 125,0,124,4,0,100,6,0,107,2,0,114,22,1,124,2, + 0,106,9,0,100,4,0,100,5,0,131,2,0,100,12,0, + 25,125,5,0,124,5,0,106,10,0,116,11,0,131,1,0, + 115,223,0,116,6,0,100,8,0,106,7,0,116,11,0,131, + 1,0,131,1,0,130,1,0,124,5,0,116,12,0,116,11, + 0,131,1,0,100,1,0,133,2,0,25,125,6,0,124,6, + 0,106,13,0,131,0,0,115,22,1,116,6,0,100,9,0, + 106,7,0,124,5,0,131,1,0,131,1,0,130,1,0,124, + 2,0,106,14,0,100,4,0,131,1,0,100,10,0,25,125, + 7,0,116,15,0,124,1,0,124,7,0,116,16,0,100,10, + 0,25,23,131,2,0,83,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,58,0,0,0,114, + 56,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,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,59,0, + 0,0,62,2,0,0,0,114,56,0,0,0,114,80,0,0, + 0,233,254,255,255,255,41,17,114,7,0,0,0,114,64,0, + 0,0,114,65,0,0,0,114,66,0,0,0,114,38,0,0, + 0,114,73,0,0,0,114,71,0,0,0,114,47,0,0,0, + 218,5,99,111,117,110,116,114,34,0,0,0,114,9,0,0, + 0,114,72,0,0,0,114,31,0,0,0,114,70,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,76,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,57,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,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,17,115,111,117,114,99,101,95,102,114,111,109,95,99, + 97,99,104,101,28,1,0,0,115,44,0,0,0,0,9,18, + 1,12,1,18,1,18,1,12,1,9,1,15,1,15,1,12, + 1,9,1,15,1,12,1,22,1,15,1,9,1,12,1,22, + 1,12,1,9,1,12,1,19,1,114,85,0,0,0,99,1, + 0,0,0,0,0,0,0,5,0,0,0,12,0,0,0,67, + 0,0,0,115,164,0,0,0,116,0,0,124,0,0,131,1, + 0,100,1,0,107,2,0,114,22,0,100,2,0,83,124,0, + 0,106,1,0,100,3,0,131,1,0,92,3,0,125,1,0, + 125,2,0,125,3,0,124,1,0,12,115,81,0,124,3,0, + 106,2,0,131,0,0,100,7,0,100,8,0,133,2,0,25, + 100,6,0,107,3,0,114,85,0,124,0,0,83,121,16,0, + 116,3,0,124,0,0,131,1,0,125,4,0,87,110,40,0, + 4,116,4,0,116,5,0,102,2,0,107,10,0,114,143,0, + 1,1,1,124,0,0,100,2,0,100,9,0,133,2,0,25, + 125,4,0,89,110,1,0,88,116,6,0,124,4,0,131,1, + 0,114,160,0,124,4,0,83,124,0,0,83,41,10,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,59,0,0, + 0,78,114,58,0,0,0,114,80,0,0,0,114,29,0,0, + 0,90,2,112,121,233,253,255,255,255,233,255,255,255,255,114, + 87,0,0,0,41,7,114,31,0,0,0,114,32,0,0,0, + 218,5,108,111,119,101,114,114,85,0,0,0,114,66,0,0, + 0,114,71,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,78,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,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,15,95, + 103,101,116,95,115,111,117,114,99,101,102,105,108,101,61,1, + 0,0,115,20,0,0,0,0,7,18,1,4,1,24,1,35, + 1,4,1,3,1,16,1,19,1,21,1,114,91,0,0,0, + 99,1,0,0,0,0,0,0,0,1,0,0,0,11,0,0, + 0,67,0,0,0,115,92,0,0,0,124,0,0,106,0,0, + 116,1,0,116,2,0,131,1,0,131,1,0,114,59,0,121, + 14,0,116,3,0,124,0,0,131,1,0,83,87,113,88,0, + 4,116,4,0,107,10,0,114,55,0,1,1,1,89,113,88, + 0,88,110,29,0,124,0,0,106,0,0,116,1,0,116,5, + 0,131,1,0,131,1,0,114,84,0,124,0,0,83,100,0, + 0,83,100,0,0,83,41,1,78,41,6,218,8,101,110,100, + 115,119,105,116,104,218,5,116,117,112,108,101,114,84,0,0, + 0,114,79,0,0,0,114,66,0,0,0,114,74,0,0,0, + 41,1,218,8,102,105,108,101,110,97,109,101,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,11,95,103,101, + 116,95,99,97,99,104,101,100,80,1,0,0,115,16,0,0, + 0,0,1,21,1,3,1,14,1,13,1,8,1,21,1,4, + 2,114,95,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,60,0,0,0, + 121,19,0,116,0,0,124,0,0,131,1,0,106,1,0,125, + 1,0,87,110,24,0,4,116,2,0,107,10,0,114,45,0, + 1,1,1,100,1,0,125,1,0,89,110,1,0,88,124,1, + 0,100,2,0,79,125,1,0,124,1,0,83,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,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,10,95,99,97,108,99, + 95,109,111,100,101,92,1,0,0,115,12,0,0,0,0,2, + 3,1,19,1,13,1,11,3,10,1,114,97,0,0,0,218, + 9,118,101,114,98,111,115,105,116,121,114,29,0,0,0,99, + 1,0,0,0,1,0,0,0,3,0,0,0,4,0,0,0, + 71,0,0,0,115,75,0,0,0,116,0,0,106,1,0,106, + 2,0,124,1,0,107,5,0,114,71,0,124,0,0,106,3, + 0,100,6,0,131,1,0,115,43,0,100,3,0,124,0,0, + 23,125,0,0,116,4,0,124,0,0,106,5,0,124,2,0, + 140,0,0,100,4,0,116,0,0,106,6,0,131,1,1,1, + 100,5,0,83,41,7,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,250,1,35,250,7,105,109,112,111,114,116, + 32,122,2,35,32,114,54,0,0,0,78,41,2,114,99,0, + 0,0,114,100,0,0,0,41,7,114,7,0,0,0,114,67, + 0,0,0,218,7,118,101,114,98,111,115,101,114,9,0,0, + 0,218,5,112,114,105,110,116,114,47,0,0,0,218,6,115, + 116,100,101,114,114,41,3,114,75,0,0,0,114,98,0,0, + 0,218,4,97,114,103,115,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,16,95,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,104,1,0,0,115,8,0,0, + 0,0,2,18,1,15,1,10,1,114,105,0,0,0,99,1, + 0,0,0,0,0,0,0,3,0,0,0,11,0,0,0,3, + 0,0,0,115,84,0,0,0,100,1,0,135,0,0,102,1, + 0,100,2,0,100,3,0,134,1,0,125,1,0,121,13,0, + 116,0,0,106,1,0,125,2,0,87,110,30,0,4,116,2, + 0,107,10,0,114,66,0,1,1,1,100,4,0,100,5,0, + 132,0,0,125,2,0,89,110,1,0,88,124,2,0,124,1, + 0,136,0,0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31,0, + 0,0,115,80,0,0,0,124,1,0,100,0,0,107,8,0, + 114,24,0,124,0,0,106,0,0,125,1,0,110,37,0,124, + 0,0,106,0,0,124,1,0,107,3,0,114,61,0,116,1, + 0,100,1,0,124,1,0,22,100,2,0,124,1,0,131,1, + 1,130,1,0,136,0,0,124,0,0,124,1,0,124,2,0, + 124,3,0,142,2,0,83,41,3,78,122,23,108,111,97,100, + 101,114,32,99,97,110,110,111,116,32,104,97,110,100,108,101, + 32,37,115,218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0,90, + 6,107,119,97,114,103,115,41,1,218,6,109,101,116,104,111, + 100,114,4,0,0,0,114,5,0,0,0,218,19,95,99,104, + 101,99,107,95,110,97,109,101,95,119,114,97,112,112,101,114, + 120,1,0,0,115,10,0,0,0,0,1,12,1,12,1,15, + 1,22,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,92,0,0,0,120,66,0,100,1,0,100,2,0, + 100,3,0,100,4,0,103,4,0,68,93,46,0,125,2,0, + 116,0,0,124,1,0,124,2,0,131,2,0,114,19,0,116, + 1,0,124,0,0,124,2,0,116,2,0,124,1,0,124,2, + 0,131,2,0,131,3,0,1,113,19,0,87,124,0,0,106, + 3,0,106,4,0,124,1,0,106,3,0,131,1,0,1,100, + 0,0,83,41,5,78,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,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,114,52, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,5,95,119,114,97,112,130,1,0,0,115,8,0, + 0,0,0,1,25,1,15,1,29,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,3,218,10,95,98,111,111,116,115, + 116,114,97,112,114,120,0,0,0,218,9,78,97,109,101,69, + 114,114,111,114,41,3,114,109,0,0,0,114,110,0,0,0, + 114,120,0,0,0,114,4,0,0,0,41,1,114,109,0,0, + 0,114,5,0,0,0,218,11,95,99,104,101,99,107,95,110, + 97,109,101,112,1,0,0,115,14,0,0,0,0,8,21,6, + 3,1,13,1,13,2,17,5,13,1,114,123,0,0,0,99, + 2,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, + 67,0,0,0,115,84,0,0,0,124,0,0,106,0,0,124, + 1,0,131,1,0,92,2,0,125,2,0,125,3,0,124,2, + 0,100,1,0,107,8,0,114,80,0,116,1,0,124,3,0, + 131,1,0,114,80,0,100,2,0,125,4,0,116,2,0,106, + 3,0,124,4,0,106,4,0,124,3,0,100,3,0,25,131, + 1,0,116,5,0,131,2,0,1,124,2,0,83,41,4,122, + 155,84,114,121,32,116,111,32,102,105,110,100,32,97,32,108, + 111,97,100,101,114,32,102,111,114,32,116,104,101,32,115,112, + 101,99,105,102,105,101,100,32,109,111,100,117,108,101,32,98, + 121,32,100,101,108,101,103,97,116,105,110,103,32,116,111,10, + 32,32,32,32,115,101,108,102,46,102,105,110,100,95,108,111, + 97,100,101,114,40,41,46,10,10,32,32,32,32,84,104,105, + 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,32,105,110,32,102,97,118,111,114,32, + 111,102,32,102,105,110,100,101,114,46,102,105,110,100,95,115, + 112,101,99,40,41,46,10,10,32,32,32,32,78,122,44,78, + 111,116,32,105,109,112,111,114,116,105,110,103,32,100,105,114, + 101,99,116,111,114,121,32,123,125,58,32,109,105,115,115,105, + 110,103,32,95,95,105,110,105,116,95,95,114,59,0,0,0, + 41,6,218,11,102,105,110,100,95,108,111,97,100,101,114,114, + 31,0,0,0,114,60,0,0,0,114,61,0,0,0,114,47, + 0,0,0,218,13,73,109,112,111,114,116,87,97,114,110,105, + 110,103,41,5,114,108,0,0,0,218,8,102,117,108,108,110, + 97,109,101,218,6,108,111,97,100,101,114,218,8,112,111,114, + 116,105,111,110,115,218,3,109,115,103,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,17,95,102,105,110,100, + 95,109,111,100,117,108,101,95,115,104,105,109,139,1,0,0, + 115,10,0,0,0,0,10,21,1,24,1,6,1,29,1,114, + 130,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,87,0,0,0,116,0, + 0,124,1,0,124,0,0,131,2,0,125,2,0,124,1,0, + 116,1,0,106,2,0,107,6,0,114,70,0,116,1,0,106, + 2,0,124,1,0,25,125,3,0,116,3,0,106,4,0,124, + 2,0,124,3,0,131,2,0,1,116,1,0,106,2,0,124, + 1,0,25,83,116,3,0,106,5,0,124,2,0,131,1,0, + 83,100,1,0,83,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,6,218,16,115,112, + 101,99,95,102,114,111,109,95,108,111,97,100,101,114,114,7, + 0,0,0,218,7,109,111,100,117,108,101,115,114,121,0,0, + 0,90,5,95,101,120,101,99,90,5,95,108,111,97,100,41, + 4,114,108,0,0,0,114,126,0,0,0,218,4,115,112,101, + 99,218,6,109,111,100,117,108,101,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,17,95,108,111,97,100,95, + 109,111,100,117,108,101,95,115,104,105,109,157,1,0,0,115, + 12,0,0,0,0,6,15,1,15,1,13,1,16,1,11,2, + 114,135,0,0,0,99,4,0,0,0,0,0,0,0,11,0, + 0,0,19,0,0,0,67,0,0,0,115,228,1,0,0,105, + 0,0,125,4,0,124,2,0,100,1,0,107,9,0,114,31, + 0,124,2,0,124,4,0,100,2,0,60,110,6,0,100,3, + 0,125,2,0,124,3,0,100,1,0,107,9,0,114,59,0, + 124,3,0,124,4,0,100,4,0,60,124,0,0,100,1,0, + 100,5,0,133,2,0,25,125,5,0,124,0,0,100,5,0, + 100,6,0,133,2,0,25,125,6,0,124,0,0,100,6,0, + 100,7,0,133,2,0,25,125,7,0,124,5,0,116,0,0, + 107,3,0,114,165,0,100,8,0,106,1,0,124,2,0,124, + 5,0,131,2,0,125,8,0,116,2,0,124,8,0,131,1, + 0,1,116,3,0,124,8,0,124,4,0,141,1,0,130,1, + 0,110,113,0,116,4,0,124,6,0,131,1,0,100,5,0, + 107,3,0,114,223,0,100,9,0,106,1,0,124,2,0,131, + 1,0,125,8,0,116,2,0,124,8,0,131,1,0,1,116, + 5,0,124,8,0,131,1,0,130,1,0,110,55,0,116,4, + 0,124,7,0,131,1,0,100,5,0,107,3,0,114,22,1, + 100,10,0,106,1,0,124,2,0,131,1,0,125,8,0,116, + 2,0,124,8,0,131,1,0,1,116,5,0,124,8,0,131, + 1,0,130,1,0,124,1,0,100,1,0,107,9,0,114,214, + 1,121,20,0,116,6,0,124,1,0,100,11,0,25,131,1, + 0,125,9,0,87,110,18,0,4,116,7,0,107,10,0,114, + 74,1,1,1,1,89,110,59,0,88,116,8,0,124,6,0, + 131,1,0,124,9,0,107,3,0,114,133,1,100,12,0,106, + 1,0,124,2,0,131,1,0,125,8,0,116,2,0,124,8, + 0,131,1,0,1,116,3,0,124,8,0,124,4,0,141,1, + 0,130,1,0,121,18,0,124,1,0,100,13,0,25,100,14, + 0,64,125,10,0,87,110,18,0,4,116,7,0,107,10,0, + 114,171,1,1,1,1,89,110,43,0,88,116,8,0,124,7, + 0,131,1,0,124,10,0,107,3,0,114,214,1,116,3,0, + 100,12,0,106,1,0,124,2,0,131,1,0,124,4,0,141, + 1,0,130,1,0,124,0,0,100,7,0,100,1,0,133,2, + 0,25,83,41,15,97,122,1,0,0,86,97,108,105,100,97, + 116,101,32,116,104,101,32,104,101,97,100,101,114,32,111,102, + 32,116,104,101,32,112,97,115,115,101,100,45,105,110,32,98, + 121,116,101,99,111,100,101,32,97,103,97,105,110,115,116,32, + 115,111,117,114,99,101,95,115,116,97,116,115,32,40,105,102, + 10,32,32,32,32,103,105,118,101,110,41,32,97,110,100,32, + 114,101,116,117,114,110,105,110,103,32,116,104,101,32,98,121, + 116,101,99,111,100,101,32,116,104,97,116,32,99,97,110,32, + 98,101,32,99,111,109,112,105,108,101,100,32,98,121,32,99, + 111,109,112,105,108,101,40,41,46,10,10,32,32,32,32,65, + 108,108,32,111,116,104,101,114,32,97,114,103,117,109,101,110, + 116,115,32,97,114,101,32,117,115,101,100,32,116,111,32,101, + 110,104,97,110,99,101,32,101,114,114,111,114,32,114,101,112, + 111,114,116,105,110,103,46,10,10,32,32,32,32,73,109,112, + 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,32,119,104,101,110,32,116,104,101,32,109,97,103,105, + 99,32,110,117,109,98,101,114,32,105,115,32,105,110,99,111, + 114,114,101,99,116,32,111,114,32,116,104,101,32,98,121,116, + 101,99,111,100,101,32,105,115,10,32,32,32,32,102,111,117, + 110,100,32,116,111,32,98,101,32,115,116,97,108,101,46,32, + 69,79,70,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,32,119,104,101,110,32,116,104,101,32,100,97,116,97, + 32,105,115,32,102,111,117,110,100,32,116,111,32,98,101,10, + 32,32,32,32,116,114,117,110,99,97,116,101,100,46,10,10, + 32,32,32,32,78,114,106,0,0,0,122,10,60,98,121,116, + 101,99,111,100,101,62,114,35,0,0,0,114,12,0,0,0, + 233,8,0,0,0,233,12,0,0,0,122,30,98,97,100,32, + 109,97,103,105,99,32,110,117,109,98,101,114,32,105,110,32, + 123,33,114,125,58,32,123,33,114,125,122,43,114,101,97,99, + 104,101,100,32,69,79,70,32,119,104,105,108,101,32,114,101, + 97,100,105,110,103,32,116,105,109,101,115,116,97,109,112,32, + 105,110,32,123,33,114,125,122,48,114,101,97,99,104,101,100, + 32,69,79,70,32,119,104,105,108,101,32,114,101,97,100,105, + 110,103,32,115,105,122,101,32,111,102,32,115,111,117,114,99, + 101,32,105,110,32,123,33,114,125,218,5,109,116,105,109,101, + 122,26,98,121,116,101,99,111,100,101,32,105,115,32,115,116, + 97,108,101,32,102,111,114,32,123,33,114,125,218,4,115,105, + 122,101,108,3,0,0,0,255,127,255,127,3,0,41,9,218, + 12,77,65,71,73,67,95,78,85,77,66,69,82,114,47,0, + 0,0,114,105,0,0,0,114,107,0,0,0,114,31,0,0, + 0,218,8,69,79,70,69,114,114,111,114,114,14,0,0,0, + 218,8,75,101,121,69,114,114,111,114,114,19,0,0,0,41, + 11,114,53,0,0,0,218,12,115,111,117,114,99,101,95,115, + 116,97,116,115,114,106,0,0,0,114,35,0,0,0,90,11, + 101,120,99,95,100,101,116,97,105,108,115,90,5,109,97,103, + 105,99,90,13,114,97,119,95,116,105,109,101,115,116,97,109, + 112,90,8,114,97,119,95,115,105,122,101,114,75,0,0,0, + 218,12,115,111,117,114,99,101,95,109,116,105,109,101,218,11, + 115,111,117,114,99,101,95,115,105,122,101,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,25,95,118,97,108, + 105,100,97,116,101,95,98,121,116,101,99,111,100,101,95,104, + 101,97,100,101,114,172,1,0,0,115,76,0,0,0,0,11, + 6,1,12,1,13,3,6,1,12,1,10,1,16,1,16,1, + 16,1,12,1,18,1,10,1,18,1,18,1,15,1,10,1, + 15,1,18,1,15,1,10,1,12,1,12,1,3,1,20,1, + 13,1,5,2,18,1,15,1,10,1,15,1,3,1,18,1, + 13,1,5,2,18,1,15,1,9,1,114,146,0,0,0,99, + 4,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0, + 67,0,0,0,115,112,0,0,0,116,0,0,106,1,0,124, + 0,0,131,1,0,125,4,0,116,2,0,124,4,0,116,3, + 0,131,2,0,114,75,0,116,4,0,100,1,0,124,2,0, + 131,2,0,1,124,3,0,100,2,0,107,9,0,114,71,0, + 116,5,0,106,6,0,124,4,0,124,3,0,131,2,0,1, + 124,4,0,83,116,7,0,100,3,0,106,8,0,124,2,0, + 131,1,0,100,4,0,124,1,0,100,5,0,124,2,0,131, + 1,2,130,1,0,100,2,0,83,41,6,122,60,67,111,109, + 112,105,108,101,32,98,121,116,101,99,111,100,101,32,97,115, + 32,114,101,116,117,114,110,101,100,32,98,121,32,95,118,97, + 108,105,100,97,116,101,95,98,121,116,101,99,111,100,101,95, + 104,101,97,100,101,114,40,41,46,122,21,99,111,100,101,32, + 111,98,106,101,99,116,32,102,114,111,109,32,123,33,114,125, + 78,122,23,78,111,110,45,99,111,100,101,32,111,98,106,101, + 99,116,32,105,110,32,123,33,114,125,114,106,0,0,0,114, + 35,0,0,0,41,9,218,7,109,97,114,115,104,97,108,90, + 5,108,111,97,100,115,218,10,105,115,105,110,115,116,97,110, + 99,101,218,10,95,99,111,100,101,95,116,121,112,101,114,105, + 0,0,0,218,4,95,105,109,112,90,16,95,102,105,120,95, + 99,111,95,102,105,108,101,110,97,109,101,114,107,0,0,0, + 114,47,0,0,0,41,5,114,53,0,0,0,114,106,0,0, + 0,114,89,0,0,0,114,90,0,0,0,218,4,99,111,100, + 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,17,95,99,111,109,112,105,108,101,95,98,121,116,101,99, + 111,100,101,227,1,0,0,115,16,0,0,0,0,2,15,1, + 15,1,13,1,12,1,16,1,4,2,18,1,114,152,0,0, + 0,114,59,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,76,0,0,0, + 116,0,0,116,1,0,131,1,0,125,3,0,124,3,0,106, + 2,0,116,3,0,124,1,0,131,1,0,131,1,0,1,124, + 3,0,106,2,0,116,3,0,124,2,0,131,1,0,131,1, + 0,1,124,3,0,106,2,0,116,4,0,106,5,0,124,0, + 0,131,1,0,131,1,0,1,124,3,0,83,41,1,122,80, + 67,111,109,112,105,108,101,32,97,32,99,111,100,101,32,111, + 98,106,101,99,116,32,105,110,116,111,32,98,121,116,101,99, + 111,100,101,32,102,111,114,32,119,114,105,116,105,110,103,32, + 111,117,116,32,116,111,32,97,32,98,121,116,101,45,99,111, + 109,112,105,108,101,100,10,32,32,32,32,102,105,108,101,46, + 41,6,218,9,98,121,116,101,97,114,114,97,121,114,140,0, + 0,0,218,6,101,120,116,101,110,100,114,17,0,0,0,114, + 147,0,0,0,90,5,100,117,109,112,115,41,4,114,151,0, + 0,0,114,138,0,0,0,114,145,0,0,0,114,53,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,17,95,99,111,100,101,95,116,111,95,98,121,116,101,99, + 111,100,101,239,1,0,0,115,10,0,0,0,0,3,12,1, + 19,1,19,1,22,1,114,155,0,0,0,99,1,0,0,0, + 0,0,0,0,5,0,0,0,4,0,0,0,67,0,0,0, + 115,89,0,0,0,100,1,0,100,2,0,108,0,0,125,1, + 0,116,1,0,106,2,0,124,0,0,131,1,0,106,3,0, + 125,2,0,124,1,0,106,4,0,124,2,0,131,1,0,125, + 3,0,116,1,0,106,5,0,100,2,0,100,3,0,131,2, + 0,125,4,0,124,4,0,106,6,0,124,0,0,106,6,0, + 124,3,0,100,1,0,25,131,1,0,131,1,0,83,41,4, + 122,121,68,101,99,111,100,101,32,98,121,116,101,115,32,114, + 101,112,114,101,115,101,110,116,105,110,103,32,115,111,117,114, + 99,101,32,99,111,100,101,32,97,110,100,32,114,101,116,117, + 114,110,32,116,104,101,32,115,116,114,105,110,103,46,10,10, + 32,32,32,32,85,110,105,118,101,114,115,97,108,32,110,101, + 119,108,105,110,101,32,115,117,112,112,111,114,116,32,105,115, + 32,117,115,101,100,32,105,110,32,116,104,101,32,100,101,99, + 111,100,105,110,103,46,10,32,32,32,32,114,59,0,0,0, + 78,84,41,7,218,8,116,111,107,101,110,105,122,101,114,49, + 0,0,0,90,7,66,121,116,101,115,73,79,90,8,114,101, + 97,100,108,105,110,101,90,15,100,101,116,101,99,116,95,101, + 110,99,111,100,105,110,103,90,25,73,110,99,114,101,109,101, + 110,116,97,108,78,101,119,108,105,110,101,68,101,99,111,100, + 101,114,218,6,100,101,99,111,100,101,41,5,218,12,115,111, + 117,114,99,101,95,98,121,116,101,115,114,156,0,0,0,90, + 21,115,111,117,114,99,101,95,98,121,116,101,115,95,114,101, + 97,100,108,105,110,101,218,8,101,110,99,111,100,105,110,103, + 90,15,110,101,119,108,105,110,101,95,100,101,99,111,100,101, + 114,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,13,100,101,99,111,100,101,95,115,111,117,114,99,101,249, + 1,0,0,115,10,0,0,0,0,5,12,1,18,1,15,1, + 18,1,114,160,0,0,0,218,6,111,114,105,103,105,110,218, + 10,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, + 2,0,0,0,5,0,0,0,15,0,0,0,67,0,0,0, + 115,193,0,0,0,116,0,0,124,1,0,100,1,0,131,2, + 0,114,83,0,124,3,0,100,2,0,107,8,0,114,43,0, + 116,1,0,124,0,0,100,3,0,124,1,0,131,1,1,83, + 124,3,0,114,55,0,103,0,0,110,3,0,100,2,0,125, + 4,0,116,1,0,124,0,0,100,3,0,124,1,0,100,4, + 0,124,4,0,131,1,2,83,124,3,0,100,2,0,107,8, + 0,114,165,0,116,0,0,124,1,0,100,5,0,131,2,0, + 114,159,0,121,19,0,124,1,0,106,2,0,124,0,0,131, + 1,0,125,3,0,87,113,165,0,4,116,3,0,107,10,0, + 114,155,0,1,1,1,100,2,0,125,3,0,89,113,165,0, + 88,110,6,0,100,6,0,125,3,0,116,4,0,106,5,0, + 124,0,0,124,1,0,100,7,0,124,2,0,100,5,0,124, + 3,0,131,2,2,83,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,218, + 12,103,101,116,95,102,105,108,101,110,97,109,101,78,114,127, + 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,114, + 162,0,0,0,70,114,161,0,0,0,41,6,114,115,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,162,0,0,0,114, + 107,0,0,0,114,121,0,0,0,218,10,77,111,100,117,108, + 101,83,112,101,99,41,5,114,106,0,0,0,114,127,0,0, + 0,114,161,0,0,0,114,162,0,0,0,90,6,115,101,97, + 114,99,104,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,131,0,0,0,7,2,0,0,115,28,0,0,0, + 0,2,15,1,12,1,16,1,18,1,15,1,7,2,12,1, + 15,1,3,1,19,1,13,1,14,3,6,2,114,131,0,0, + 0,114,127,0,0,0,114,164,0,0,0,99,2,0,0,0, + 2,0,0,0,9,0,0,0,19,0,0,0,67,0,0,0, + 115,89,1,0,0,124,1,0,100,1,0,107,8,0,114,73, + 0,100,2,0,125,1,0,116,0,0,124,2,0,100,3,0, + 131,2,0,114,73,0,121,19,0,124,2,0,106,1,0,124, + 0,0,131,1,0,125,1,0,87,110,18,0,4,116,2,0, + 107,10,0,114,72,0,1,1,1,89,110,1,0,88,116,3, + 0,106,4,0,124,0,0,124,2,0,100,4,0,124,1,0, + 131,2,1,125,4,0,100,5,0,124,4,0,95,5,0,124, + 2,0,100,1,0,107,8,0,114,194,0,120,73,0,116,6, + 0,131,0,0,68,93,58,0,92,2,0,125,5,0,125,6, + 0,124,1,0,106,7,0,116,8,0,124,6,0,131,1,0, + 131,1,0,114,128,0,124,5,0,124,0,0,124,1,0,131, + 2,0,125,2,0,124,2,0,124,4,0,95,9,0,80,113, + 128,0,87,100,1,0,83,124,3,0,116,10,0,107,8,0, + 114,23,1,116,0,0,124,2,0,100,6,0,131,2,0,114, + 32,1,121,19,0,124,2,0,106,11,0,124,0,0,131,1, + 0,125,7,0,87,110,18,0,4,116,2,0,107,10,0,114, + 4,1,1,1,1,89,113,32,1,88,124,7,0,114,32,1, + 103,0,0,124,4,0,95,12,0,110,9,0,124,3,0,124, + 4,0,95,12,0,124,4,0,106,12,0,103,0,0,107,2, + 0,114,85,1,124,1,0,114,85,1,116,13,0,124,1,0, + 131,1,0,100,7,0,25,125,8,0,124,4,0,106,12,0, + 106,14,0,124,8,0,131,1,0,1,124,4,0,83,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,114,163, + 0,0,0,114,161,0,0,0,84,114,162,0,0,0,114,59, + 0,0,0,41,15,114,115,0,0,0,114,163,0,0,0,114, + 107,0,0,0,114,121,0,0,0,114,166,0,0,0,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,92,0,0,0,114, + 93,0,0,0,114,127,0,0,0,218,9,95,80,79,80,85, + 76,65,84,69,114,162,0,0,0,114,164,0,0,0,114,38, + 0,0,0,218,6,97,112,112,101,110,100,41,9,114,106,0, + 0,0,90,8,108,111,99,97,116,105,111,110,114,127,0,0, + 0,114,164,0,0,0,114,133,0,0,0,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,162,0,0,0,90,7,100,105,114,110,97,109, + 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,165,0,0,0,32,2,0,0,115,60,0,0,0,0,12, + 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, + 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, + 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, + 9,1,15,1,6,1,16,1,16,2,114,165,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 64,0,0,0,115,121,0,0,0,101,0,0,90,1,0,100, + 0,0,90,2,0,100,1,0,90,3,0,100,2,0,90,4, + 0,100,3,0,90,5,0,100,4,0,90,6,0,101,7,0, + 100,5,0,100,6,0,132,0,0,131,1,0,90,8,0,101, + 7,0,100,7,0,100,8,0,132,0,0,131,1,0,90,9, + 0,101,7,0,100,9,0,100,9,0,100,10,0,100,11,0, + 132,2,0,131,1,0,90,10,0,101,7,0,100,9,0,100, + 12,0,100,13,0,132,1,0,131,1,0,90,11,0,100,9, + 0,83,41,14,218,21,87,105,110,100,111,119,115,82,101,103, + 105,115,116,114,121,70,105,110,100,101,114,122,62,77,101,116, + 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, + 114,32,109,111,100,117,108,101,115,32,100,101,99,108,97,114, + 101,100,32,105,110,32,116,104,101,32,87,105,110,100,111,119, + 115,32,114,101,103,105,115,116,114,121,46,122,59,83,111,102, + 116,119,97,114,101,92,80,121,116,104,111,110,92,80,121,116, + 104,111,110,67,111,114,101,92,123,115,121,115,95,118,101,114, + 115,105,111,110,125,92,77,111,100,117,108,101,115,92,123,102, + 117,108,108,110,97,109,101,125,122,65,83,111,102,116,119,97, + 114,101,92,80,121,116,104,111,110,92,80,121,116,104,111,110, + 67,111,114,101,92,123,115,121,115,95,118,101,114,115,105,111, + 110,125,92,77,111,100,117,108,101,115,92,123,102,117,108,108, + 110,97,109,101,125,92,68,101,98,117,103,70,99,2,0,0, + 0,0,0,0,0,2,0,0,0,11,0,0,0,67,0,0, + 0,115,67,0,0,0,121,23,0,116,0,0,106,1,0,116, + 0,0,106,2,0,124,1,0,131,2,0,83,87,110,37,0, + 4,116,3,0,107,10,0,114,62,0,1,1,1,116,0,0, + 106,1,0,116,0,0,106,4,0,124,1,0,131,2,0,83, + 89,110,1,0,88,100,0,0,83,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,218,3,107,101,121,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, + 101,103,105,115,116,114,121,110,2,0,0,115,8,0,0,0, + 0,2,3,1,23,1,13,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,16,0,0,0,67, + 0,0,0,115,142,0,0,0,124,0,0,106,0,0,114,21, + 0,124,0,0,106,1,0,125,2,0,110,9,0,124,0,0, + 106,2,0,125,2,0,124,2,0,106,3,0,100,1,0,124, + 1,0,100,2,0,116,4,0,106,5,0,100,0,0,100,3, + 0,133,2,0,25,131,0,2,125,3,0,121,46,0,124,0, + 0,106,6,0,124,3,0,131,1,0,143,25,0,125,4,0, + 116,7,0,106,8,0,124,4,0,100,4,0,131,2,0,125, + 5,0,87,100,0,0,81,88,87,110,22,0,4,116,9,0, + 107,10,0,114,137,0,1,1,1,100,0,0,83,89,110,1, + 0,88,124,5,0,83,41,5,78,114,126,0,0,0,90,11, + 115,121,115,95,118,101,114,115,105,111,110,114,80,0,0,0, + 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,47,0,0,0,114,7,0,0,0, + 218,7,118,101,114,115,105,111,110,114,176,0,0,0,114,173, + 0,0,0,90,10,81,117,101,114,121,86,97,108,117,101,114, + 40,0,0,0,41,6,114,174,0,0,0,114,126,0,0,0, + 90,12,114,101,103,105,115,116,114,121,95,107,101,121,114,175, + 0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,112, + 97,116,104,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,105, + 115,116,114,121,117,2,0,0,115,22,0,0,0,0,2,9, + 1,12,2,9,1,15,1,22,1,3,1,18,1,28,1,13, + 1,9,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,14,0,0,0,67,0,0, + 0,115,155,0,0,0,124,0,0,106,0,0,124,1,0,131, + 1,0,125,4,0,124,4,0,100,0,0,107,8,0,114,31, + 0,100,0,0,83,121,14,0,116,1,0,124,4,0,131,1, + 0,1,87,110,22,0,4,116,2,0,107,10,0,114,69,0, + 1,1,1,100,0,0,83,89,110,1,0,88,120,78,0,116, + 3,0,131,0,0,68,93,67,0,92,2,0,125,5,0,125, + 6,0,124,4,0,106,4,0,116,5,0,124,6,0,131,1, + 0,131,1,0,114,80,0,116,6,0,124,1,0,124,5,0, + 124,1,0,124,4,0,131,2,0,100,1,0,124,4,0,131, + 2,1,125,7,0,124,7,0,83,113,80,0,87,100,0,0, + 83,41,2,78,114,161,0,0,0,41,7,114,182,0,0,0, + 114,39,0,0,0,114,40,0,0,0,114,167,0,0,0,114, + 92,0,0,0,114,93,0,0,0,114,131,0,0,0,41,8, + 114,174,0,0,0,114,126,0,0,0,114,35,0,0,0,218, + 6,116,97,114,103,101,116,114,181,0,0,0,114,127,0,0, + 0,114,171,0,0,0,114,133,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,9,102,105,110,100, + 95,115,112,101,99,132,2,0,0,115,24,0,0,0,0,2, + 15,1,12,1,4,1,3,1,14,1,13,1,9,1,22,1, + 21,1,21,1,9,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,3,0,0,0,67,0,0,0,115,45,0,0, + 0,124,0,0,106,0,0,124,1,0,124,2,0,131,2,0, + 125,3,0,124,3,0,100,1,0,107,9,0,114,37,0,124, + 3,0,106,1,0,83,100,1,0,83,100,1,0,83,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,184,0,0,0,114,127,0,0,0,41,4,114,174,0, + 0,0,114,126,0,0,0,114,35,0,0,0,114,133,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,11,102,105,110,100,95,109,111,100,117,108,101,147,2,0, + 0,115,8,0,0,0,0,7,18,1,12,1,7,2,122,33, + 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, + 105,110,100,101,114,46,102,105,110,100,95,109,111,100,117,108, + 101,41,12,114,112,0,0,0,114,111,0,0,0,114,113,0, + 0,0,114,114,0,0,0,114,179,0,0,0,114,178,0,0, + 0,114,177,0,0,0,218,11,99,108,97,115,115,109,101,116, + 104,111,100,114,176,0,0,0,114,182,0,0,0,114,184,0, + 0,0,114,185,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,172,0,0,0, + 98,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, + 2,6,2,18,7,18,15,3,1,21,14,3,1,114,172,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,64,0,0,0,101,0,0,90, + 1,0,100,0,0,90,2,0,100,1,0,90,3,0,100,2, + 0,100,3,0,132,0,0,90,4,0,100,4,0,100,5,0, + 132,0,0,90,5,0,100,6,0,100,7,0,132,0,0,90, + 6,0,101,7,0,90,8,0,100,8,0,83,41,9,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,3, + 0,0,0,67,0,0,0,115,88,0,0,0,116,0,0,124, + 0,0,106,1,0,124,1,0,131,1,0,131,1,0,100,1, + 0,25,125,2,0,124,2,0,106,2,0,100,2,0,100,1, + 0,131,2,0,100,3,0,25,125,3,0,124,1,0,106,3, + 0,100,2,0,131,1,0,100,4,0,25,125,4,0,124,3, + 0,100,5,0,107,2,0,111,87,0,124,4,0,100,5,0, + 107,3,0,83,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,58,0,0,0,114, + 59,0,0,0,114,56,0,0,0,218,8,95,95,105,110,105, + 116,95,95,41,4,114,38,0,0,0,114,163,0,0,0,114, + 34,0,0,0,114,32,0,0,0,41,5,114,108,0,0,0, + 114,126,0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,162,0,0,0,166,2,0,0,115,8,0,0, + 0,0,3,25,1,22,1,19,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,0, + 83,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,4,0,0,0,41,2,114,108,0,0,0,114,133,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,174, + 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,4,0,0,0,67,0,0,0,115,80,0,0,0,124, + 0,0,106,0,0,124,1,0,106,1,0,131,1,0,125,2, + 0,124,2,0,100,1,0,107,8,0,114,54,0,116,2,0, + 100,2,0,106,3,0,124,1,0,106,1,0,131,1,0,131, + 1,0,130,1,0,116,4,0,106,5,0,116,6,0,124,2, + 0,124,1,0,106,7,0,131,3,0,1,100,1,0,83,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,112,0,0,0,114,107, + 0,0,0,114,47,0,0,0,114,121,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,118, + 0,0,0,41,3,114,108,0,0,0,114,134,0,0,0,114, + 151,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,101, + 177,2,0,0,115,10,0,0,0,0,2,18,1,12,1,9, + 1,15,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,78,41, + 9,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, + 114,114,0,0,0,114,162,0,0,0,114,189,0,0,0,114, + 193,0,0,0,114,135,0,0,0,218,11,108,111,97,100,95, + 109,111,100,117,108,101,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,187,0,0,0,161, + 2,0,0,115,10,0,0,0,12,3,6,2,12,8,12,3, + 12,8,114,187,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,106,0,0, + 0,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 100,2,0,132,0,0,90,3,0,100,3,0,100,4,0,132, + 0,0,90,4,0,100,5,0,100,6,0,132,0,0,90,5, + 0,100,7,0,100,8,0,132,0,0,90,6,0,100,9,0, + 100,10,0,132,0,0,90,7,0,100,11,0,100,18,0,100, + 13,0,100,14,0,132,0,1,90,8,0,100,15,0,100,16, + 0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0,83,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,73,79,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,218,7,73,79,69,114,114,111, + 114,41,2,114,108,0,0,0,114,35,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,10,112,97, + 116,104,95,109,116,105,109,101,190,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,3,0,0,0,67,0,0, + 0,115,20,0,0,0,105,1,0,124,0,0,106,0,0,124, + 1,0,131,1,0,100,1,0,54,83,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,73,79,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,138,0,0,0, + 41,1,114,197,0,0,0,41,2,114,108,0,0,0,114,35, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,10,112,97,116,104,95,115,116,97,116,115,198,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,3, + 0,0,0,67,0,0,0,115,16,0,0,0,124,0,0,106, + 0,0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99,97, + 99,104,101,95,112,97,116,104,114,53,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,15,95,99, + 97,99,104,101,95,98,121,116,101,99,111,100,101,211,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,0,83,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, + 4,0,0,0,41,3,114,108,0,0,0,114,35,0,0,0, + 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,199,0,0,0,221,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,16,0,0,0,67,0,0,0,115,105, + 0,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, + 2,0,121,19,0,124,0,0,106,1,0,124,2,0,131,1, + 0,125,3,0,87,110,58,0,4,116,2,0,107,10,0,114, + 94,0,1,125,4,0,1,122,26,0,116,3,0,100,1,0, + 100,2,0,124,1,0,131,1,1,124,4,0,130,2,0,87, + 89,100,3,0,100,3,0,125,4,0,126,4,0,88,110,1, + 0,88,116,4,0,124,3,0,131,1,0,83,41,4,122,52, + 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, + 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, + 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, + 103,104,32,103,101,116,95,100,97,116,97,40,41,114,106,0, + 0,0,78,41,5,114,163,0,0,0,218,8,103,101,116,95, + 100,97,116,97,114,40,0,0,0,114,107,0,0,0,114,160, + 0,0,0,41,5,114,108,0,0,0,114,126,0,0,0,114, + 35,0,0,0,114,158,0,0,0,218,3,101,120,99,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,103, + 101,116,95,115,111,117,114,99,101,228,2,0,0,115,14,0, + 0,0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105, + 109,105,122,101,114,29,0,0,0,99,3,0,0,0,1,0, + 0,0,4,0,0,0,9,0,0,0,67,0,0,0,115,34, + 0,0,0,116,0,0,106,1,0,116,2,0,124,1,0,124, + 2,0,100,1,0,100,2,0,100,3,0,100,4,0,124,3, + 0,131,4,2,83,41,5,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,192,0,0,0, + 218,12,100,111,110,116,95,105,110,104,101,114,105,116,84,114, + 68,0,0,0,41,3,114,121,0,0,0,114,191,0,0,0, + 218,7,99,111,109,112,105,108,101,41,4,114,108,0,0,0, + 114,53,0,0,0,114,35,0,0,0,114,204,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,14, + 115,111,117,114,99,101,95,116,111,95,99,111,100,101,238,2, + 0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174,1, + 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, + 0,100,1,0,125,3,0,121,16,0,116,1,0,124,2,0, + 131,1,0,125,4,0,87,110,24,0,4,116,2,0,107,10, + 0,114,63,0,1,1,1,100,1,0,125,4,0,89,110,202, + 0,88,121,19,0,124,0,0,106,3,0,124,2,0,131,1, + 0,125,5,0,87,110,18,0,4,116,4,0,107,10,0,114, + 103,0,1,1,1,89,110,162,0,88,116,5,0,124,5,0, + 100,2,0,25,131,1,0,125,3,0,121,19,0,124,0,0, + 106,6,0,124,4,0,131,1,0,125,6,0,87,110,18,0, + 4,116,7,0,107,10,0,114,159,0,1,1,1,89,110,106, + 0,88,121,34,0,116,8,0,124,6,0,100,3,0,124,5, + 0,100,4,0,124,1,0,100,5,0,124,4,0,131,1,3, + 125,7,0,87,110,24,0,4,116,9,0,116,10,0,102,2, + 0,107,10,0,114,220,0,1,1,1,89,110,45,0,88,116, + 11,0,100,6,0,124,4,0,124,2,0,131,3,0,1,116, + 12,0,124,7,0,100,4,0,124,1,0,100,7,0,124,4, + 0,100,8,0,124,2,0,131,1,3,83,124,0,0,106,6, + 0,124,2,0,131,1,0,125,8,0,124,0,0,106,13,0, + 124,8,0,124,2,0,131,2,0,125,9,0,116,11,0,100, + 9,0,124,2,0,131,2,0,1,116,14,0,106,15,0,12, + 114,170,1,124,4,0,100,1,0,107,9,0,114,170,1,124, + 3,0,100,1,0,107,9,0,114,170,1,116,16,0,124,9, + 0,124,3,0,116,17,0,124,8,0,131,1,0,131,3,0, + 125,6,0,121,36,0,124,0,0,106,18,0,124,2,0,124, + 4,0,124,6,0,131,3,0,1,116,11,0,100,10,0,124, + 4,0,131,2,0,1,87,110,18,0,4,116,2,0,107,10, + 0,114,169,1,1,1,1,89,110,1,0,88,124,9,0,83, + 41,11,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,114,138,0,0,0,114,143,0,0,0,114,106,0, + 0,0,114,35,0,0,0,122,13,123,125,32,109,97,116,99, + 104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66,0, + 0,0,114,198,0,0,0,114,196,0,0,0,114,14,0,0, + 0,114,201,0,0,0,114,40,0,0,0,114,146,0,0,0, + 114,107,0,0,0,114,141,0,0,0,114,105,0,0,0,114, + 152,0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200,0, + 0,0,41,10,114,108,0,0,0,114,126,0,0,0,114,90, + 0,0,0,114,144,0,0,0,114,89,0,0,0,218,2,115, + 116,114,53,0,0,0,218,10,98,121,116,101,115,95,100,97, + 116,97,114,158,0,0,0,90,11,99,111,100,101,95,111,98, + 106,101,99,116,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,190,0,0,0,246,2,0,0,115,78,0,0, + 0,0,7,15,1,6,1,3,1,16,1,13,1,11,2,3, + 1,19,1,13,1,5,2,16,1,3,1,19,1,13,1,5, + 2,3,1,9,1,12,1,13,1,19,1,5,2,9,1,7, + 1,15,1,6,1,7,1,15,1,18,1,13,1,22,1,12, + 1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112, + 0,0,0,114,111,0,0,0,114,113,0,0,0,114,197,0, + 0,0,114,198,0,0,0,114,200,0,0,0,114,199,0,0, + 0,114,203,0,0,0,114,207,0,0,0,114,190,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,195,0,0,0,188,2,0,0,115,14,0, + 0,0,12,2,12,8,12,13,12,10,12,7,12,10,18,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,112,0,0,0,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, + 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, + 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, + 0,0,90,6,0,101,7,0,135,0,0,102,1,0,100,8, + 0,100,9,0,134,0,0,131,1,0,90,8,0,101,7,0, + 100,10,0,100,11,0,132,0,0,131,1,0,90,9,0,100, + 12,0,100,13,0,132,0,0,90,10,0,135,0,0,83,41, + 14,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,22,0,0,0, + 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, + 1,0,100,1,0,83,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,106,0,0,0,114,35,0, + 0,0,41,3,114,108,0,0,0,114,126,0,0,0,114,35, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,188,0,0,0,47,3,0,0,115,4,0,0,0, + 0,3,9,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,34, + 0,0,0,124,0,0,106,0,0,124,1,0,106,0,0,107, + 2,0,111,33,0,124,0,0,106,1,0,124,1,0,106,1, + 0,107,2,0,83,41,1,78,41,2,218,9,95,95,99,108, + 97,115,115,95,95,114,118,0,0,0,41,2,114,108,0,0, + 0,218,5,111,116,104,101,114,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,6,95,95,101,113,95,95,53, + 3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106, + 1,0,131,1,0,116,0,0,124,0,0,106,2,0,131,1, + 0,65,83,41,1,78,41,3,218,4,104,97,115,104,114,106, + 0,0,0,114,35,0,0,0,41,1,114,108,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,8, + 95,95,104,97,115,104,95,95,57,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,22,0, + 0,0,116,0,0,116,1,0,124,0,0,131,2,0,106,2, + 0,124,1,0,131,1,0,83,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,211,0,0,0,114,194, + 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,41, + 1,114,212,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,194,0,0,0,60,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,7,0, + 0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,163,0,0,0,72,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,8, + 0,0,0,67,0,0,0,115,41,0,0,0,116,0,0,106, + 1,0,124,1,0,100,1,0,131,2,0,143,17,0,125,2, + 0,124,2,0,106,2,0,131,0,0,83,87,100,2,0,81, + 88,100,2,0,83,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,49,0,0,0,114,50,0,0,0, + 90,4,114,101,97,100,41,3,114,108,0,0,0,114,35,0, + 0,0,114,54,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,201,0,0,0,77,3,0,0,115, + 4,0,0,0,0,2,21,1,122,19,70,105,108,101,76,111, + 97,100,101,114,46,103,101,116,95,100,97,116,97,41,11,114, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, + 0,0,0,114,188,0,0,0,114,214,0,0,0,114,216,0, + 0,0,114,123,0,0,0,114,194,0,0,0,114,163,0,0, + 0,114,201,0,0,0,114,4,0,0,0,114,4,0,0,0, + 41,1,114,212,0,0,0,114,5,0,0,0,114,211,0,0, + 0,42,3,0,0,115,14,0,0,0,12,3,6,2,12,6, + 12,4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, + 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, + 0,100,6,0,100,7,0,100,8,0,100,9,0,132,0,1, + 90,6,0,100,10,0,83,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,36,0,0,0,116,0,0,124,1,0,131,1,0,125,2, + 0,105,2,0,124,2,0,106,1,0,100,1,0,54,124,2, + 0,106,2,0,100,2,0,54,83,41,3,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,114,138, + 0,0,0,114,139,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,108,0,0,0,114,35,0,0,0,114,209, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,198,0,0,0,87,3,0,0,115,4,0,0,0, + 0,2,12,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,34,0,0,0,116,0,0,124,1, + 0,131,1,0,125,4,0,124,0,0,106,1,0,124,2,0, + 124,3,0,100,1,0,124,4,0,131,2,1,83,41,2,78, + 218,5,95,109,111,100,101,41,2,114,97,0,0,0,114,199, + 0,0,0,41,5,114,108,0,0,0,114,90,0,0,0,114, + 89,0,0,0,114,53,0,0,0,114,42,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,200,0, + 0,0,92,3,0,0,115,4,0,0,0,0,2,12,1,122, + 32,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, + 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, + 101,114,221,0,0,0,105,182,1,0,0,99,3,0,0,0, + 1,0,0,0,9,0,0,0,17,0,0,0,67,0,0,0, + 115,53,1,0,0,116,0,0,124,1,0,131,1,0,92,2, + 0,125,4,0,125,5,0,103,0,0,125,6,0,120,54,0, + 124,4,0,114,80,0,116,1,0,124,4,0,131,1,0,12, + 114,80,0,116,0,0,124,4,0,131,1,0,92,2,0,125, + 4,0,125,7,0,124,6,0,106,2,0,124,7,0,131,1, + 0,1,113,27,0,87,120,132,0,116,3,0,124,6,0,131, + 1,0,68,93,118,0,125,7,0,116,4,0,124,4,0,124, + 7,0,131,2,0,125,4,0,121,17,0,116,5,0,106,6, + 0,124,4,0,131,1,0,1,87,113,94,0,4,116,7,0, + 107,10,0,114,155,0,1,1,1,119,94,0,89,113,94,0, + 4,116,8,0,107,10,0,114,211,0,1,125,8,0,1,122, + 25,0,116,9,0,100,1,0,124,4,0,124,8,0,131,3, + 0,1,100,2,0,83,87,89,100,2,0,100,2,0,125,8, + 0,126,8,0,88,113,94,0,88,113,94,0,87,121,33,0, + 116,10,0,124,1,0,124,2,0,124,3,0,131,3,0,1, + 116,9,0,100,3,0,124,1,0,131,2,0,1,87,110,53, + 0,4,116,8,0,107,10,0,114,48,1,1,125,8,0,1, + 122,21,0,116,9,0,100,1,0,124,1,0,124,8,0,131, + 3,0,1,87,89,100,2,0,100,2,0,125,8,0,126,8, + 0,88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0, + 0,114,169,0,0,0,114,33,0,0,0,114,28,0,0,0, + 114,3,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,105,0,0,0,114,55,0,0,0,41,9,114,108, + 0,0,0,114,35,0,0,0,114,53,0,0,0,114,221,0, + 0,0,218,6,112,97,114,101,110,116,114,94,0,0,0,114, + 27,0,0,0,114,23,0,0,0,114,202,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,199,0, + 0,0,97,3,0,0,115,38,0,0,0,0,2,18,1,6, + 2,22,1,18,1,17,2,19,1,15,1,3,1,17,1,13, + 2,7,1,18,3,16,1,27,1,3,1,16,1,17,1,18, + 2,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, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, + 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,219,0,0,0,83,3,0,0,115, + 8,0,0,0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1, + 0,100,0,0,90,2,0,100,1,0,90,3,0,100,2,0, + 100,3,0,132,0,0,90,4,0,100,4,0,100,5,0,132, + 0,0,90,5,0,100,6,0,83,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,6,0,0, + 0,67,0,0,0,115,76,0,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,125,2,0,124,0,0,106,1,0,124, + 2,0,131,1,0,125,3,0,116,2,0,124,3,0,100,1, + 0,124,1,0,100,2,0,124,2,0,131,1,2,125,4,0, + 116,3,0,124,4,0,100,1,0,124,1,0,100,3,0,124, + 2,0,131,1,2,83,41,4,78,114,106,0,0,0,114,35, + 0,0,0,114,89,0,0,0,41,4,114,163,0,0,0,114, + 201,0,0,0,114,146,0,0,0,114,152,0,0,0,41,5, + 114,108,0,0,0,114,126,0,0,0,114,35,0,0,0,114, + 53,0,0,0,114,210,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,190,0,0,0,130,3,0, + 0,115,8,0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108, + 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,203,0,0,0,136,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,112,0,0,0, + 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, + 190,0,0,0,114,203,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,224,0, + 0,0,126,3,0,0,115,6,0,0,0,12,2,6,2,12, + 6,114,224,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,130,0,0,0, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, + 132,0,0,90,6,0,101,7,0,100,8,0,100,9,0,132, + 0,0,131,1,0,90,8,0,100,10,0,100,11,0,132,0, + 0,90,9,0,100,12,0,100,13,0,132,0,0,90,10,0, + 100,14,0,100,15,0,132,0,0,90,11,0,101,7,0,100, + 16,0,100,17,0,132,0,0,131,1,0,90,12,0,100,18, + 0,83,41,19,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,22,0, + 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, + 0,95,1,0,100,0,0,83,41,1,78,41,2,114,106,0, + 0,0,114,35,0,0,0,41,3,114,108,0,0,0,114,106, + 0,0,0,114,35,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,188,0,0,0,153,3,0,0, + 115,4,0,0,0,0,1,9,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,34,0,0, + 0,124,0,0,106,0,0,124,1,0,106,0,0,107,2,0, + 111,33,0,124,0,0,106,1,0,124,1,0,106,1,0,107, + 2,0,83,41,1,78,41,2,114,212,0,0,0,114,118,0, + 0,0,41,2,114,108,0,0,0,114,213,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,214,0, + 0,0,157,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1,0,131,1, + 0,116,0,0,124,0,0,106,2,0,131,1,0,65,83,41, + 1,78,41,3,114,215,0,0,0,114,106,0,0,0,114,35, + 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,216,0,0,0,161,3, + 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, + 4,0,0,0,11,0,0,0,67,0,0,0,115,183,0,0, + 0,116,0,0,106,1,0,124,1,0,131,1,0,143,32,0, + 1,116,0,0,106,2,0,116,3,0,106,4,0,124,1,0, + 124,0,0,106,5,0,131,3,0,125,2,0,87,100,1,0, + 81,88,116,6,0,100,2,0,124,0,0,106,5,0,131,2, + 0,1,124,0,0,106,7,0,124,1,0,131,1,0,125,3, + 0,124,3,0,114,127,0,116,8,0,124,2,0,100,3,0, + 131,2,0,12,114,127,0,116,9,0,124,0,0,106,5,0, + 131,1,0,100,4,0,25,103,1,0,124,2,0,95,10,0, + 124,0,0,124,2,0,95,11,0,124,2,0,106,12,0,124, + 2,0,95,13,0,124,3,0,115,179,0,124,2,0,106,13, + 0,106,14,0,100,5,0,131,1,0,100,4,0,25,124,2, + 0,95,13,0,124,2,0,83,41,6,122,25,76,111,97,100, + 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,46,78,122,33,101,120,116,101,110,115,105,111, + 110,32,109,111,100,117,108,101,32,108,111,97,100,101,100,32, + 102,114,111,109,32,123,33,114,125,218,8,95,95,112,97,116, + 104,95,95,114,59,0,0,0,114,58,0,0,0,41,15,114, + 121,0,0,0,90,13,95,77,97,110,97,103,101,82,101,108, + 111,97,100,114,191,0,0,0,114,150,0,0,0,90,12,108, + 111,97,100,95,100,121,110,97,109,105,99,114,35,0,0,0, + 114,105,0,0,0,114,162,0,0,0,114,115,0,0,0,114, + 38,0,0,0,114,226,0,0,0,218,10,95,95,108,111,97, + 100,101,114,95,95,114,112,0,0,0,218,11,95,95,112,97, + 99,107,97,103,101,95,95,114,32,0,0,0,41,4,114,108, + 0,0,0,114,126,0,0,0,114,134,0,0,0,114,162,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,194,0,0,0,164,3,0,0,115,24,0,0,0,0, + 5,16,1,12,1,21,1,16,1,15,1,22,1,25,1,9, + 1,12,1,6,1,25,1,122,31,69,120,116,101,110,115,105, + 111,110,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,4,0,0,0,3,0,0,0,115,48,0, + 0,0,116,0,0,124,0,0,106,1,0,131,1,0,100,1, + 0,25,137,0,0,116,2,0,135,0,0,102,1,0,100,2, + 0,100,3,0,134,0,0,116,3,0,68,131,1,0,131,1, + 0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0,136, + 0,0,100,0,0,124,1,0,23,107,2,0,86,1,113,3, + 0,100,1,0,83,41,2,114,188,0,0,0,78,114,4,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,4, + 0,0,0,114,5,0,0,0,250,9,60,103,101,110,101,120, + 112,114,62,185,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0, + 0,0,114,4,0,0,0,41,1,114,230,0,0,0,114,5, + 0,0,0,114,162,0,0,0,182,3,0,0,115,6,0,0, + 0,0,2,19,1,18,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,0,83,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,4,0,0,0,41,2, + 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,190,0,0,0,188,3, + 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,0,83,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, + 4,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 203,0,0,0,192,3,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,7,0,0,0,124,0,0,106,0,0,83, + 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,108,0,0,0,114,126,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,163,0,0,0,196,3,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,13,114,112,0,0,0,114,111,0,0,0,114, + 113,0,0,0,114,114,0,0,0,114,188,0,0,0,114,214, + 0,0,0,114,216,0,0,0,114,123,0,0,0,114,194,0, + 0,0,114,162,0,0,0,114,190,0,0,0,114,203,0,0, + 0,114,163,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,225,0,0,0,145, + 3,0,0,115,18,0,0,0,12,6,6,2,12,4,12,4, + 12,3,18,18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0,100, + 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, + 0,132,0,0,90,4,0,100,4,0,100,5,0,132,0,0, + 90,5,0,100,6,0,100,7,0,132,0,0,90,6,0,100, + 8,0,100,9,0,132,0,0,90,7,0,100,10,0,100,11, + 0,132,0,0,90,8,0,100,12,0,100,13,0,132,0,0, + 90,9,0,100,14,0,100,15,0,132,0,0,90,10,0,100, + 16,0,100,17,0,132,0,0,90,11,0,100,18,0,100,19, + 0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0, + 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, + 0,95,1,0,116,2,0,124,0,0,106,3,0,131,0,0, + 131,1,0,124,0,0,95,4,0,124,3,0,124,0,0,95, + 5,0,100,0,0,83,41,1,78,41,6,218,5,95,110,97, + 109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0, + 0,0,218,11,112,97,116,104,95,102,105,110,100,101,114,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,188, + 0,0,0,209,3,0,0,115,8,0,0,0,0,1,9,1, + 9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1,0, + 100,1,0,131,1,0,92,3,0,125,1,0,125,2,0,125, + 3,0,124,2,0,100,2,0,107,2,0,114,43,0,100,6, + 0,83,124,1,0,100,5,0,102,2,0,83,41,7,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,58, + 0,0,0,114,30,0,0,0,114,7,0,0,0,114,35,0, + 0,0,114,226,0,0,0,41,2,122,3,115,121,115,122,4, + 112,97,116,104,41,2,114,235,0,0,0,114,32,0,0,0, + 41,4,114,108,0,0,0,114,223,0,0,0,218,3,100,111, + 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, + 5,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,215,3,0, + 0,115,8,0,0,0,0,2,27,1,12,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,38,0,0,0, + 124,0,0,106,0,0,131,0,0,92,2,0,125,1,0,125, + 2,0,116,1,0,116,2,0,106,3,0,124,1,0,25,124, + 2,0,131,2,0,83,41,1,78,41,4,114,242,0,0,0, + 114,117,0,0,0,114,7,0,0,0,114,132,0,0,0,41, + 3,114,108,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,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,237,0,0,0,225,3, + 0,0,115,4,0,0,0,0,1,18,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,3,0,0,0,67,0,0, + 0,115,118,0,0,0,116,0,0,124,0,0,106,1,0,131, + 0,0,131,1,0,125,1,0,124,1,0,124,0,0,106,2, + 0,107,3,0,114,111,0,124,0,0,106,3,0,124,0,0, + 106,4,0,124,1,0,131,2,0,125,2,0,124,2,0,100, + 0,0,107,9,0,114,102,0,124,2,0,106,5,0,100,0, + 0,107,8,0,114,102,0,124,2,0,106,6,0,114,102,0, + 124,2,0,106,6,0,124,0,0,95,7,0,124,1,0,124, + 0,0,95,2,0,124,0,0,106,7,0,83,41,1,78,41, + 8,114,93,0,0,0,114,237,0,0,0,114,238,0,0,0, + 114,239,0,0,0,114,235,0,0,0,114,127,0,0,0,114, + 164,0,0,0,114,236,0,0,0,41,3,114,108,0,0,0, + 90,11,112,97,114,101,110,116,95,112,97,116,104,114,133,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,12,95,114,101,99,97,108,99,117,108,97,116,101,229, + 3,0,0,115,16,0,0,0,0,2,18,1,15,1,21,3, + 27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16,0,0,0,116, + 0,0,124,0,0,106,1,0,131,0,0,131,1,0,83,41, + 1,78,41,2,218,4,105,116,101,114,114,243,0,0,0,41, + 1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,8,95,95,105,116,101,114,95,95,242, + 3,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,1,0,0,0,0,0,0,0,1,0,0,0, + 2,0,0,0,67,0,0,0,115,16,0,0,0,116,0,0, + 124,0,0,106,1,0,131,0,0,131,1,0,83,41,1,78, + 41,2,114,31,0,0,0,114,243,0,0,0,41,1,114,108, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,7,95,95,108,101,110,95,95,245,3,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,2,0,0,0,67, + 0,0,0,115,16,0,0,0,100,1,0,106,0,0,124,0, + 0,106,1,0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1,114, + 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,8,95,95,114,101,112,114,95,95,248,3,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,2,0, + 0,0,67,0,0,0,115,16,0,0,0,124,1,0,124,0, + 0,106,0,0,131,0,0,107,6,0,83,41,1,78,41,1, + 114,243,0,0,0,41,2,114,108,0,0,0,218,4,105,116, + 101,109,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,12,95,95,99,111,110,116,97,105,110,115,95,95,251, + 3,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,2,0,0,0,67,0,0,0,115,20,0,0, + 0,124,0,0,106,0,0,106,1,0,124,1,0,131,1,0, + 1,100,0,0,83,41,1,78,41,2,114,236,0,0,0,114, + 169,0,0,0,41,2,114,108,0,0,0,114,248,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 169,0,0,0,254,3,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,13,114,112,0,0,0,114,111, + 0,0,0,114,113,0,0,0,114,114,0,0,0,114,188,0, + 0,0,114,242,0,0,0,114,237,0,0,0,114,243,0,0, + 0,114,245,0,0,0,114,246,0,0,0,114,247,0,0,0, + 114,249,0,0,0,114,169,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,234, + 0,0,0,202,3,0,0,115,20,0,0,0,12,5,6,2, + 12,6,12,10,12,4,12,13,12,3,12,3,12,3,12,3, + 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,118,0,0,0,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,100,2, + 0,132,0,0,90,3,0,101,4,0,100,3,0,100,4,0, + 132,0,0,131,1,0,90,5,0,100,5,0,100,6,0,132, + 0,0,90,6,0,100,7,0,100,8,0,132,0,0,90,7, + 0,100,9,0,100,10,0,132,0,0,90,8,0,100,11,0, + 100,12,0,132,0,0,90,9,0,100,13,0,100,14,0,132, + 0,0,90,10,0,100,15,0,100,16,0,132,0,0,90,11, + 0,100,17,0,83,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,25, + 0,0,0,116,0,0,124,1,0,124,2,0,124,3,0,131, + 3,0,124,0,0,95,1,0,100,0,0,83,41,1,78,41, + 2,114,234,0,0,0,114,236,0,0,0,41,4,114,108,0, + 0,0,114,106,0,0,0,114,35,0,0,0,114,240,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,188,0,0,0,4,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,2,0,0,0,67,0,0,0, + 115,16,0,0,0,100,1,0,106,0,0,124,1,0,106,1, + 0,131,1,0,83,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,47,0,0,0,114,112, + 0,0,0,41,2,114,174,0,0,0,114,134,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, + 109,111,100,117,108,101,95,114,101,112,114,7,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, + 0,83,41,2,78,84,114,4,0,0,0,41,2,114,108,0, + 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,162,0,0,0,16,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,0, + 83,41,2,78,114,30,0,0,0,114,4,0,0,0,41,2, + 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,203,0,0,0,19,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,22,0,0,0, + 116,0,0,100,1,0,100,2,0,100,3,0,100,4,0,100, + 5,0,131,3,1,83,41,6,78,114,30,0,0,0,122,8, + 60,115,116,114,105,110,103,62,114,192,0,0,0,114,205,0, + 0,0,84,41,1,114,206,0,0,0,41,2,114,108,0,0, + 0,114,126,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,190,0,0,0,22,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,0,83,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,4,0, + 0,0,41,2,114,108,0,0,0,114,133,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,189,0, + 0,0,25,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,0,83,41,1,78,114,4,0,0, + 0,41,2,114,108,0,0,0,114,134,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,193,0,0, + 0,28,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,3,0,0,0,67,0,0,0,115, + 29,0,0,0,116,0,0,100,1,0,124,0,0,106,1,0, + 131,2,0,1,116,2,0,124,0,0,124,1,0,131,2,0, + 83,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, + 3,114,105,0,0,0,114,236,0,0,0,114,135,0,0,0, + 41,2,114,108,0,0,0,114,126,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,194,0,0,0, + 31,4,0,0,115,4,0,0,0,0,7,16,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,112, + 0,0,0,114,111,0,0,0,114,113,0,0,0,114,188,0, + 0,0,114,186,0,0,0,114,251,0,0,0,114,162,0,0, + 0,114,203,0,0,0,114,190,0,0,0,114,189,0,0,0, + 114,193,0,0,0,114,194,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,250, + 0,0,0,3,4,0,0,115,16,0,0,0,12,1,12,3, + 18,9,12,3,12,3,12,3,12,3,12,3,114,250,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,0,64,0,0,0,115,160,0,0,0,101,0,0,90,1, + 0,100,0,0,90,2,0,100,1,0,90,3,0,101,4,0, + 100,2,0,100,3,0,132,0,0,131,1,0,90,5,0,101, + 4,0,100,4,0,100,5,0,132,0,0,131,1,0,90,6, + 0,101,4,0,100,6,0,100,7,0,132,0,0,131,1,0, + 90,7,0,101,4,0,100,8,0,100,9,0,132,0,0,131, + 1,0,90,8,0,101,4,0,100,10,0,100,11,0,100,12, + 0,132,1,0,131,1,0,90,9,0,101,4,0,100,10,0, + 100,10,0,100,13,0,100,14,0,132,2,0,131,1,0,90, + 10,0,101,4,0,100,10,0,100,15,0,100,16,0,132,1, + 0,131,1,0,90,11,0,100,10,0,83,41,17,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,55, + 0,0,0,120,48,0,116,0,0,106,1,0,106,2,0,131, + 0,0,68,93,31,0,125,1,0,116,3,0,124,1,0,100, + 1,0,131,2,0,114,16,0,124,1,0,106,4,0,131,0, + 0,1,113,16,0,87,100,2,0,83,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,7,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,115,0,0,0,114,253,0,0,0,41,2,114, + 174,0,0,0,218,6,102,105,110,100,101,114,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,253,0,0,0, + 48,4,0,0,115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67,0, + 0,0,115,107,0,0,0,116,0,0,106,1,0,100,1,0, + 107,9,0,114,41,0,116,0,0,106,1,0,12,114,41,0, + 116,2,0,106,3,0,100,2,0,116,4,0,131,2,0,1, + 120,59,0,116,0,0,106,1,0,68,93,44,0,125,2,0, + 121,14,0,124,2,0,124,1,0,131,1,0,83,87,113,51, + 0,4,116,5,0,107,10,0,114,94,0,1,1,1,119,51, + 0,89,113,51,0,88,113,51,0,87,100,1,0,83,100,1, + 0,83,41,3,122,113,83,101,97,114,99,104,32,115,101,113, + 117,101,110,99,101,32,111,102,32,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,10,10,32,32,32,32,32,32,32, + 32,73,102,32,39,104,111,111,107,115,39,32,105,115,32,102, + 97,108,115,101,32,116,104,101,110,32,117,115,101,32,115,121, + 115,46,112,97,116,104,95,104,111,111,107,115,46,10,10,32, + 32,32,32,32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95,104, + 111,111,107,115,114,60,0,0,0,114,61,0,0,0,114,125, + 0,0,0,114,107,0,0,0,41,3,114,174,0,0,0,114, + 35,0,0,0,90,4,104,111,111,107,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,11,95,112,97,116,104, + 95,104,111,111,107,115,56,4,0,0,115,16,0,0,0,0, + 7,25,1,16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0,0, + 0,124,1,0,100,1,0,107,2,0,114,53,0,121,16,0, + 116,0,0,106,1,0,131,0,0,125,1,0,87,110,22,0, + 4,116,2,0,107,10,0,114,52,0,1,1,1,100,2,0, + 83,89,110,1,0,88,121,17,0,116,3,0,106,4,0,124, + 1,0,25,125,2,0,87,110,46,0,4,116,5,0,107,10, + 0,114,118,0,1,1,1,124,0,0,106,6,0,124,1,0, + 131,1,0,125,2,0,124,2,0,116,3,0,106,4,0,124, + 1,0,60,89,110,1,0,88,124,2,0,83,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,3,0,0,0,114, + 45,0,0,0,218,17,70,105,108,101,78,111,116,70,111,117, + 110,100,69,114,114,111,114,114,7,0,0,0,114,254,0,0, + 0,114,142,0,0,0,114,2,1,0,0,41,3,114,174,0, + 0,0,114,35,0,0,0,114,0,1,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,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,73,4,0,0,115,22,0,0,0,0,8,12,1,3,1, + 16,1,13,3,9,1,3,1,17,1,13,1,15,1,18,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,3,0, + 0,0,67,0,0,0,115,116,0,0,0,116,0,0,124,2, + 0,100,1,0,131,2,0,114,39,0,124,2,0,106,1,0, + 124,1,0,131,1,0,92,2,0,125,3,0,125,4,0,110, + 21,0,124,2,0,106,2,0,124,1,0,131,1,0,125,3, + 0,103,0,0,125,4,0,124,3,0,100,0,0,107,9,0, + 114,85,0,116,3,0,124,1,0,124,3,0,131,2,0,83, + 116,4,0,106,5,0,124,1,0,100,0,0,131,2,0,125, + 5,0,124,4,0,124,5,0,95,6,0,124,5,0,83,41, + 2,78,114,124,0,0,0,41,7,114,115,0,0,0,114,124, + 0,0,0,114,185,0,0,0,114,131,0,0,0,114,121,0, + 0,0,114,166,0,0,0,114,164,0,0,0,41,6,114,174, + 0,0,0,114,126,0,0,0,114,0,1,0,0,114,127,0, + 0,0,114,128,0,0,0,114,133,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,16,95,108,101, + 103,97,99,121,95,103,101,116,95,115,112,101,99,95,4,0, + 0,115,18,0,0,0,0,4,15,1,24,2,15,1,6,1, + 12,1,13,1,18,1,9,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,243,0,0,0, + 103,0,0,125,4,0,120,230,0,124,2,0,68,93,191,0, + 125,5,0,116,0,0,124,5,0,116,1,0,116,2,0,102, + 2,0,131,2,0,115,43,0,113,13,0,124,0,0,106,3, + 0,124,5,0,131,1,0,125,6,0,124,6,0,100,1,0, + 107,9,0,114,13,0,116,4,0,124,6,0,100,2,0,131, + 2,0,114,106,0,124,6,0,106,5,0,124,1,0,124,3, + 0,131,2,0,125,7,0,110,18,0,124,0,0,106,6,0, + 124,1,0,124,6,0,131,2,0,125,7,0,124,7,0,100, + 1,0,107,8,0,114,139,0,113,13,0,124,7,0,106,7, + 0,100,1,0,107,9,0,114,158,0,124,7,0,83,124,7, + 0,106,8,0,125,8,0,124,8,0,100,1,0,107,8,0, + 114,191,0,116,9,0,100,3,0,131,1,0,130,1,0,124, + 4,0,106,10,0,124,8,0,131,1,0,1,113,13,0,87, + 116,11,0,106,12,0,124,1,0,100,1,0,131,2,0,125, + 7,0,124,4,0,124,7,0,95,8,0,124,7,0,83,100, + 1,0,83,41,4,122,63,70,105,110,100,32,116,104,101,32, + 108,111,97,100,101,114,32,111,114,32,110,97,109,101,115,112, + 97,99,101,95,112,97,116,104,32,102,111,114,32,116,104,105, + 115,32,109,111,100,117,108,101,47,112,97,99,107,97,103,101, + 32,110,97,109,101,46,78,114,184,0,0,0,122,19,115,112, + 101,99,32,109,105,115,115,105,110,103,32,108,111,97,100,101, + 114,41,13,114,148,0,0,0,114,69,0,0,0,218,5,98, + 121,116,101,115,114,4,1,0,0,114,115,0,0,0,114,184, + 0,0,0,114,5,1,0,0,114,127,0,0,0,114,164,0, + 0,0,114,107,0,0,0,114,154,0,0,0,114,121,0,0, + 0,114,166,0,0,0,41,9,114,174,0,0,0,114,126,0, + 0,0,114,35,0,0,0,114,183,0,0,0,218,14,110,97, + 109,101,115,112,97,99,101,95,112,97,116,104,90,5,101,110, + 116,114,121,114,0,1,0,0,114,133,0,0,0,114,128,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,9,95,103,101,116,95,115,112,101,99,110,4,0,0, + 115,40,0,0,0,0,5,6,1,13,1,21,1,3,1,15, + 1,12,1,15,1,21,2,18,1,12,1,3,1,15,1,4, + 1,9,1,12,1,12,5,17,2,18,1,9,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, + 4,0,0,0,67,0,0,0,115,140,0,0,0,124,2,0, + 100,1,0,107,8,0,114,21,0,116,0,0,106,1,0,125, + 2,0,124,0,0,106,2,0,124,1,0,124,2,0,124,3, + 0,131,3,0,125,4,0,124,4,0,100,1,0,107,8,0, + 114,58,0,100,1,0,83,124,4,0,106,3,0,100,1,0, + 107,8,0,114,132,0,124,4,0,106,4,0,125,5,0,124, + 5,0,114,125,0,100,2,0,124,4,0,95,5,0,116,6, + 0,124,1,0,124,5,0,124,0,0,106,2,0,131,3,0, + 124,4,0,95,4,0,124,4,0,83,100,1,0,83,110,4, + 0,124,4,0,83,100,1,0,83,41,3,122,98,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,78, + 90,9,110,97,109,101,115,112,97,99,101,41,7,114,7,0, + 0,0,114,35,0,0,0,114,8,1,0,0,114,127,0,0, + 0,114,164,0,0,0,114,161,0,0,0,114,234,0,0,0, + 41,6,114,174,0,0,0,114,126,0,0,0,114,35,0,0, + 0,114,183,0,0,0,114,133,0,0,0,114,7,1,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 184,0,0,0,142,4,0,0,115,26,0,0,0,0,4,12, + 1,9,1,21,1,12,1,4,1,15,1,9,1,6,3,9, + 1,24,1,4,2,7,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,41,0,0,0,124,0,0,106,0,0,124,1,0, + 124,2,0,131,2,0,125,3,0,124,3,0,100,1,0,107, + 8,0,114,34,0,100,1,0,83,124,3,0,106,1,0,83, + 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,184,0,0,0,114,127,0,0,0,41,4,114,174,0, + 0,0,114,126,0,0,0,114,35,0,0,0,114,133,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,185,0,0,0,164,4,0,0,115,8,0,0,0,0,8, + 18,1,12,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,12, + 114,112,0,0,0,114,111,0,0,0,114,113,0,0,0,114, + 114,0,0,0,114,186,0,0,0,114,253,0,0,0,114,2, + 1,0,0,114,4,1,0,0,114,5,1,0,0,114,8,1, + 0,0,114,184,0,0,0,114,185,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,252,0,0,0,44,4,0,0,115,22,0,0,0,12,2, + 6,2,18,8,18,17,18,22,18,15,3,1,18,31,3,1, + 21,21,3,1,114,252,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,133, + 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, + 1,0,90,3,0,100,2,0,100,3,0,132,0,0,90,4, + 0,100,4,0,100,5,0,132,0,0,90,5,0,101,6,0, + 90,7,0,100,6,0,100,7,0,132,0,0,90,8,0,100, + 8,0,100,9,0,132,0,0,90,9,0,100,10,0,100,11, + 0,100,12,0,132,1,0,90,10,0,100,13,0,100,14,0, + 132,0,0,90,11,0,101,12,0,100,15,0,100,16,0,132, + 0,0,131,1,0,90,13,0,100,17,0,100,18,0,132,0, + 0,90,14,0,100,10,0,83,41,19,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,122,0,0,0,103,0, + 0,125,3,0,120,52,0,124,2,0,68,93,44,0,92,2, + 0,137,0,0,125,4,0,124,3,0,106,0,0,135,0,0, + 102,1,0,100,1,0,100,2,0,134,0,0,124,4,0,68, + 131,1,0,131,1,0,1,113,13,0,87,124,3,0,124,0, + 0,95,1,0,124,1,0,112,79,0,100,3,0,124,0,0, + 95,2,0,100,6,0,124,0,0,95,3,0,116,4,0,131, + 0,0,124,0,0,95,5,0,116,4,0,131,0,0,124,0, + 0,95,6,0,100,5,0,83,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,27,0,0,0, + 124,0,0,93,17,0,125,1,0,124,1,0,136,0,0,102, + 2,0,86,1,113,3,0,100,0,0,83,41,1,78,114,4, + 0,0,0,41,2,114,22,0,0,0,114,229,0,0,0,41, + 1,114,127,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,231,0,0,0,193,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0, + 0,0,78,114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0,0, + 0,41,1,114,127,0,0,0,114,5,0,0,0,114,188,0, + 0,0,187,4,0,0,115,16,0,0,0,0,4,6,1,19, + 1,36,1,9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0,0, + 95,0,0,100,2,0,83,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,29,0,0,0,78, + 114,87,0,0,0,41,1,114,11,1,0,0,41,1,114,108, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,253,0,0,0,201,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,59,0,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,125,2,0,124,2,0,100,1,0,107, + 8,0,114,37,0,100,1,0,103,0,0,102,2,0,83,124, + 2,0,106,1,0,124,2,0,106,2,0,112,55,0,103,0, + 0,102,2,0,83,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,184,0,0,0,114,127,0,0,0,114,164,0,0,0, + 41,3,114,108,0,0,0,114,126,0,0,0,114,133,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,124,0,0,0,207,4,0,0,115,8,0,0,0,0,7, + 15,1,12,1,10,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,7,0,0,0,67, + 0,0,0,115,40,0,0,0,124,1,0,124,2,0,124,3, + 0,131,2,0,125,6,0,116,0,0,124,2,0,124,3,0, + 100,1,0,124,6,0,100,2,0,124,4,0,131,2,2,83, + 41,3,78,114,127,0,0,0,114,164,0,0,0,41,1,114, + 165,0,0,0,41,7,114,108,0,0,0,114,170,0,0,0, + 114,126,0,0,0,114,35,0,0,0,90,4,115,109,115,108, + 114,183,0,0,0,114,127,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,8,1,0,0,219,4, + 0,0,115,6,0,0,0,0,1,15,1,18,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,234,1,0,0,100,1, + 0,125,3,0,124,1,0,106,0,0,100,2,0,131,1,0, + 100,3,0,25,125,4,0,121,34,0,116,1,0,124,0,0, + 106,2,0,112,49,0,116,3,0,106,4,0,131,0,0,131, + 1,0,106,5,0,125,5,0,87,110,24,0,4,116,6,0, + 107,10,0,114,85,0,1,1,1,100,10,0,125,5,0,89, + 110,1,0,88,124,5,0,124,0,0,106,7,0,107,3,0, + 114,120,0,124,0,0,106,8,0,131,0,0,1,124,5,0, + 124,0,0,95,7,0,116,9,0,131,0,0,114,153,0,124, + 0,0,106,10,0,125,6,0,124,4,0,106,11,0,131,0, + 0,125,7,0,110,15,0,124,0,0,106,12,0,125,6,0, + 124,4,0,125,7,0,124,7,0,124,6,0,107,6,0,114, + 45,1,116,13,0,124,0,0,106,2,0,124,4,0,131,2, + 0,125,8,0,120,100,0,124,0,0,106,14,0,68,93,77, + 0,92,2,0,125,9,0,125,10,0,100,5,0,124,9,0, + 23,125,11,0,116,13,0,124,8,0,124,11,0,131,2,0, + 125,12,0,116,15,0,124,12,0,131,1,0,114,208,0,124, + 0,0,106,16,0,124,10,0,124,1,0,124,12,0,124,8, + 0,103,1,0,124,2,0,131,5,0,83,113,208,0,87,116, + 17,0,124,8,0,131,1,0,125,3,0,120,123,0,124,0, + 0,106,14,0,68,93,112,0,92,2,0,125,9,0,125,10, + 0,116,13,0,124,0,0,106,2,0,124,4,0,124,9,0, + 23,131,2,0,125,12,0,116,18,0,100,6,0,106,19,0, + 124,12,0,131,1,0,100,7,0,100,3,0,131,1,1,1, + 124,7,0,124,9,0,23,124,6,0,107,6,0,114,55,1, + 116,15,0,124,12,0,131,1,0,114,55,1,124,0,0,106, + 16,0,124,10,0,124,1,0,124,12,0,100,8,0,124,2, + 0,131,5,0,83,113,55,1,87,124,3,0,114,230,1,116, + 18,0,100,9,0,106,19,0,124,8,0,131,1,0,131,1, + 0,1,116,20,0,106,21,0,124,1,0,100,8,0,131,2, + 0,125,13,0,124,8,0,103,1,0,124,13,0,95,22,0, + 124,13,0,83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0,114, + 56,0,0,0,114,29,0,0,0,114,188,0,0,0,122,9, + 116,114,121,105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0,41, + 23,114,32,0,0,0,114,39,0,0,0,114,35,0,0,0, + 114,3,0,0,0,114,45,0,0,0,114,220,0,0,0,114, + 40,0,0,0,114,11,1,0,0,218,11,95,102,105,108,108, + 95,99,97,99,104,101,114,6,0,0,0,114,14,1,0,0, + 114,88,0,0,0,114,13,1,0,0,114,28,0,0,0,114, + 10,1,0,0,114,44,0,0,0,114,8,1,0,0,114,46, + 0,0,0,114,105,0,0,0,114,47,0,0,0,114,121,0, + 0,0,114,166,0,0,0,114,164,0,0,0,41,14,114,108, + 0,0,0,114,126,0,0,0,114,183,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,138,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,229,0, + 0,0,114,170,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,133,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,184,0,0,0,224,4,0,0,115,68, + 0,0,0,0,3,6,1,19,1,3,1,34,1,13,1,11, + 1,15,1,10,1,9,2,9,1,9,1,15,2,9,1,6, + 2,12,1,18,1,22,1,10,1,15,1,12,1,32,4,12, + 2,22,1,22,1,25,1,16,1,12,1,29,1,6,1,19, + 1,18,1,12,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,11,1,0,0,124,0,0,106,0,0,125,1,0, + 121,31,0,116,1,0,106,2,0,124,1,0,112,33,0,116, + 1,0,106,3,0,131,0,0,131,1,0,125,2,0,87,110, + 33,0,4,116,4,0,116,5,0,116,6,0,102,3,0,107, + 10,0,114,75,0,1,1,1,103,0,0,125,2,0,89,110, + 1,0,88,116,7,0,106,8,0,106,9,0,100,1,0,131, + 1,0,115,112,0,116,10,0,124,2,0,131,1,0,124,0, + 0,95,11,0,110,111,0,116,10,0,131,0,0,125,3,0, + 120,90,0,124,2,0,68,93,82,0,125,4,0,124,4,0, + 106,12,0,100,2,0,131,1,0,92,3,0,125,5,0,125, + 6,0,125,7,0,124,6,0,114,191,0,100,3,0,106,13, + 0,124,5,0,124,7,0,106,14,0,131,0,0,131,2,0, + 125,8,0,110,6,0,124,5,0,125,8,0,124,3,0,106, + 15,0,124,8,0,131,1,0,1,113,128,0,87,124,3,0, + 124,0,0,95,11,0,116,7,0,106,8,0,106,9,0,116, + 16,0,131,1,0,114,7,1,100,4,0,100,5,0,132,0, + 0,124,2,0,68,131,1,0,124,0,0,95,17,0,100,6, + 0,83,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, + 58,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,28,0,0,0,104,0,0,124,0,0,93,18,0,125,1, + 0,124,1,0,106,0,0,131,0,0,146,2,0,113,6,0, + 83,114,4,0,0,0,41,1,114,88,0,0,0,41,2,114, + 22,0,0,0,90,2,102,110,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,250,9,60,115,101,116,99,111,109, + 112,62,42,5,0,0,115,2,0,0,0,9,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,3,0,0,0,90,7,108,105,115,116,100,105,114,114,45, + 0,0,0,114,3,1,0,0,218,15,80,101,114,109,105,115, + 115,105,111,110,69,114,114,111,114,218,18,78,111,116,65,68, + 105,114,101,99,116,111,114,121,69,114,114,111,114,114,7,0, + 0,0,114,8,0,0,0,114,9,0,0,0,114,12,1,0, + 0,114,13,1,0,0,114,83,0,0,0,114,47,0,0,0, + 114,88,0,0,0,218,3,97,100,100,114,10,0,0,0,114, + 14,1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,241,0,0,0, + 114,229,0,0,0,90,8,110,101,119,95,110,97,109,101,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,16, + 1,0,0,13,5,0,0,115,34,0,0,0,0,2,9,1, + 3,1,31,1,22,3,11,3,18,1,18,7,9,1,13,1, + 24,1,6,1,27,2,6,1,17,1,9,1,18,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,25,0,0,0, + 135,0,0,135,1,0,102,2,0,100,1,0,100,2,0,134, + 0,0,125,2,0,124,2,0,83,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,43,0,0,0,116,0, + 0,124,0,0,131,1,0,115,30,0,116,1,0,100,1,0, + 100,2,0,124,0,0,131,1,1,130,1,0,136,0,0,124, + 0,0,136,1,0,140,1,0,83,41,3,122,45,80,97,116, + 104,32,104,111,111,107,32,102,111,114,32,105,109,112,111,114, + 116,108,105,98,46,109,97,99,104,105,110,101,114,121,46,70, + 105,108,101,70,105,110,100,101,114,46,122,30,111,110,108,121, + 32,100,105,114,101,99,116,111,114,105,101,115,32,97,114,101, + 32,115,117,112,112,111,114,116,101,100,114,35,0,0,0,41, + 2,114,46,0,0,0,114,107,0,0,0,41,1,114,35,0, + 0,0,41,2,114,174,0,0,0,114,15,1,0,0,114,4, + 0,0,0,114,5,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,54,5,0,0,115,6,0,0,0,0,2,12,1,18, + 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,174,0,0,0,114,15,1,0,0,114,21,1,0,0,114, + 4,0,0,0,41,2,114,174,0,0,0,114,15,1,0,0, + 114,5,0,0,0,218,9,112,97,116,104,95,104,111,111,107, + 44,5,0,0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1,0, + 106,0,0,124,0,0,106,1,0,131,1,0,83,41,2,78, + 122,16,70,105,108,101,70,105,110,100,101,114,40,123,33,114, + 125,41,41,2,114,47,0,0,0,114,35,0,0,0,41,1, + 114,108,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,247,0,0,0,62,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,15,114,112,0,0,0, + 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, + 188,0,0,0,114,253,0,0,0,114,130,0,0,0,114,185, + 0,0,0,114,124,0,0,0,114,8,1,0,0,114,184,0, + 0,0,114,16,1,0,0,114,186,0,0,0,114,22,1,0, + 0,114,247,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,9,1,0,0,178, + 4,0,0,115,20,0,0,0,12,7,6,2,12,14,12,4, + 6,2,12,12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106,0, + 0,100,1,0,131,1,0,125,4,0,124,0,0,106,0,0, + 100,2,0,131,1,0,125,5,0,124,4,0,115,99,0,124, + 5,0,114,54,0,124,5,0,106,1,0,125,4,0,110,45, + 0,124,2,0,124,3,0,107,2,0,114,84,0,116,2,0, + 124,1,0,124,2,0,131,2,0,125,4,0,110,15,0,116, + 3,0,124,1,0,124,2,0,131,2,0,125,4,0,124,5, + 0,115,126,0,116,4,0,124,1,0,124,2,0,100,3,0, + 124,4,0,131,2,1,125,5,0,121,44,0,124,5,0,124, + 0,0,100,2,0,60,124,4,0,124,0,0,100,1,0,60, + 124,2,0,124,0,0,100,4,0,60,124,3,0,124,0,0, + 100,5,0,60,87,110,18,0,4,116,5,0,107,10,0,114, + 190,0,1,1,1,89,110,1,0,88,100,0,0,83,41,6, + 78,114,227,0,0,0,218,8,95,95,115,112,101,99,95,95, + 114,127,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,127,0,0,0,114,224,0,0,0,114,219,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,106,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,127,0,0,0,114,133,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,14,95,102,105,120, + 95,117,112,95,109,111,100,117,108,101,68,5,0,0,115,34, + 0,0,0,0,2,15,1,15,1,6,1,6,1,12,1,12, + 1,18,2,15,1,6,1,21,1,3,1,10,1,10,1,10, + 1,14,1,13,2,114,26,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, + 55,0,0,0,116,0,0,116,1,0,106,2,0,131,0,0, + 102,2,0,125,0,0,116,3,0,116,4,0,102,2,0,125, + 1,0,116,5,0,116,6,0,102,2,0,125,2,0,124,0, + 0,124,1,0,124,2,0,103,3,0,83,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,225,0,0,0,114,150,0,0,0,218,18,101,120,116,101, + 110,115,105,111,110,95,115,117,102,102,105,120,101,115,114,219, + 0,0,0,114,84,0,0,0,114,224,0,0,0,114,74,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,5,0,0, + 0,114,167,0,0,0,91,5,0,0,115,8,0,0,0,0, + 5,18,1,12,1,12,1,114,167,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,70,2,0,0,124,0,0,97,0,0,116,0,0,106, + 1,0,97,1,0,116,0,0,106,2,0,97,2,0,116,1, + 0,106,3,0,116,4,0,25,125,1,0,120,76,0,100,26, + 0,68,93,68,0,125,2,0,124,2,0,116,1,0,106,3, + 0,107,7,0,114,83,0,116,0,0,106,5,0,124,2,0, + 131,1,0,125,3,0,110,13,0,116,1,0,106,3,0,124, + 2,0,25,125,3,0,116,6,0,124,1,0,124,2,0,124, + 3,0,131,3,0,1,113,44,0,87,100,5,0,100,6,0, + 103,1,0,102,2,0,100,7,0,100,8,0,100,6,0,103, + 2,0,102,2,0,102,2,0,125,4,0,120,149,0,124,4, + 0,68,93,129,0,92,2,0,125,5,0,125,6,0,116,7, + 0,100,9,0,100,10,0,132,0,0,124,6,0,68,131,1, + 0,131,1,0,115,199,0,116,8,0,130,1,0,124,6,0, + 100,11,0,25,125,7,0,124,5,0,116,1,0,106,3,0, + 107,6,0,114,241,0,116,1,0,106,3,0,124,5,0,25, + 125,8,0,80,113,156,0,121,20,0,116,0,0,106,5,0, + 124,5,0,131,1,0,125,8,0,80,87,113,156,0,4,116, + 9,0,107,10,0,114,28,1,1,1,1,119,156,0,89,113, + 156,0,88,113,156,0,87,116,9,0,100,12,0,131,1,0, + 130,1,0,116,6,0,124,1,0,100,13,0,124,8,0,131, + 3,0,1,116,6,0,124,1,0,100,14,0,124,7,0,131, + 3,0,1,116,6,0,124,1,0,100,15,0,100,16,0,106, + 10,0,124,6,0,131,1,0,131,3,0,1,121,19,0,116, + 0,0,106,5,0,100,17,0,131,1,0,125,9,0,87,110, + 24,0,4,116,9,0,107,10,0,114,147,1,1,1,1,100, + 18,0,125,9,0,89,110,1,0,88,116,6,0,124,1,0, + 100,17,0,124,9,0,131,3,0,1,116,0,0,106,5,0, + 100,19,0,131,1,0,125,10,0,116,6,0,124,1,0,100, + 19,0,124,10,0,131,3,0,1,124,5,0,100,7,0,107, + 2,0,114,238,1,116,0,0,106,5,0,100,20,0,131,1, + 0,125,11,0,116,6,0,124,1,0,100,21,0,124,11,0, + 131,3,0,1,116,6,0,124,1,0,100,22,0,116,11,0, + 131,0,0,131,3,0,1,116,12,0,106,13,0,116,2,0, + 106,14,0,131,0,0,131,1,0,1,124,5,0,100,7,0, + 107,2,0,114,66,2,116,15,0,106,16,0,100,23,0,131, + 1,0,1,100,24,0,116,12,0,107,6,0,114,66,2,100, + 25,0,116,17,0,95,18,0,100,18,0,83,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,49,0, + 0,0,114,60,0,0,0,218,8,98,117,105,108,116,105,110, + 115,114,147,0,0,0,90,5,112,111,115,105,120,250,1,47, + 218,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,33,0,0, + 0,124,0,0,93,23,0,125,1,0,116,0,0,124,1,0, + 131,1,0,100,0,0,107,2,0,86,1,113,3,0,100,1, + 0,83,41,2,114,29,0,0,0,78,41,1,114,31,0,0, + 0,41,2,114,22,0,0,0,114,77,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,231,0,0, + 0,127,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,173,0,0, + 0,114,6,0,0,0,122,4,46,112,121,119,122,6,95,100, + 46,112,121,100,84,41,4,122,3,95,105,111,122,9,95,119, + 97,114,110,105,110,103,115,122,8,98,117,105,108,116,105,110, + 115,122,7,109,97,114,115,104,97,108,41,19,114,121,0,0, + 0,114,7,0,0,0,114,150,0,0,0,114,132,0,0,0, + 114,112,0,0,0,90,18,95,98,117,105,108,116,105,110,95, + 102,114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0, + 0,0,114,233,0,0,0,114,154,0,0,0,114,27,1,0, + 0,114,84,0,0,0,114,169,0,0,0,114,172,0,0,0, + 114,177,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 6,95,115,101,116,117,112,102,5,0,0,115,82,0,0,0, + 0,8,6,1,9,1,9,3,13,1,13,1,15,1,18,2, + 13,1,20,3,33,1,19,2,31,1,10,1,15,1,13,1, + 4,2,3,1,15,1,5,1,13,1,12,2,12,1,16,1, + 16,1,25,3,3,1,19,1,13,2,11,1,16,3,15,1, + 16,3,12,1,15,1,16,3,19,1,19,1,12,1,13,1, + 12,1,114,35,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,116,0,0, + 0,116,0,0,124,0,0,131,1,0,1,116,1,0,131,0, + 0,125,1,0,116,2,0,106,3,0,106,4,0,116,5,0, + 106,6,0,124,1,0,140,0,0,103,1,0,131,1,0,1, + 116,7,0,106,8,0,100,1,0,107,2,0,114,78,0,116, + 2,0,106,9,0,106,10,0,116,11,0,131,1,0,1,116, + 2,0,106,9,0,106,10,0,116,12,0,131,1,0,1,116, + 5,0,124,0,0,95,5,0,116,13,0,124,0,0,95,13, + 0,100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0,114, + 167,0,0,0,114,7,0,0,0,114,1,1,0,0,114,154, + 0,0,0,114,9,1,0,0,114,22,1,0,0,114,3,0, + 0,0,114,112,0,0,0,218,9,109,101,116,97,95,112,97, + 116,104,114,169,0,0,0,114,172,0,0,0,114,252,0,0, + 0,114,219,0,0,0,41,2,114,34,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,5,0,0,0,218, + 8,95,105,110,115,116,97,108,108,170,5,0,0,115,16,0, + 0,0,0,2,10,1,9,1,28,1,15,1,16,1,16,4, + 9,1,114,37,1,0,0,41,3,122,3,119,105,110,114,1, + 0,0,0,114,2,0,0,0,41,59,114,114,0,0,0,114, + 10,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,55,0,0,0,218,4,116,121,112,101,218,8,95,95, + 99,111,100,101,95,95,114,149,0,0,0,114,15,0,0,0, + 114,140,0,0,0,114,14,0,0,0,114,18,0,0,0,90, + 17,95,82,65,87,95,77,65,71,73,67,95,78,85,77,66, + 69,82,114,73,0,0,0,114,72,0,0,0,114,84,0,0, + 0,114,74,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,79,0,0, + 0,114,85,0,0,0,114,91,0,0,0,114,95,0,0,0, + 114,97,0,0,0,114,105,0,0,0,114,123,0,0,0,114, + 130,0,0,0,114,135,0,0,0,114,146,0,0,0,114,152, + 0,0,0,114,155,0,0,0,114,160,0,0,0,114,131,0, + 0,0,218,6,111,98,106,101,99,116,114,168,0,0,0,114, + 165,0,0,0,114,172,0,0,0,114,187,0,0,0,114,195, + 0,0,0,114,211,0,0,0,114,219,0,0,0,114,224,0, + 0,0,114,233,0,0,0,114,225,0,0,0,114,234,0,0, + 0,114,250,0,0,0,114,252,0,0,0,114,9,1,0,0, + 114,26,1,0,0,114,167,0,0,0,114,35,1,0,0,114, + 37,1,0,0,114,4,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,8,60,109,111,100,117,108, + 101,62,8,0,0,0,115,104,0,0,0,6,17,6,3,12, + 12,12,5,12,5,12,6,12,12,12,10,12,9,12,5,12, + 7,15,22,15,107,22,1,18,2,6,1,6,2,9,2,9, + 2,10,2,21,44,12,33,12,19,12,12,12,12,18,8,12, + 27,12,18,12,15,21,55,21,12,18,10,12,14,24,22,9, + 3,12,1,15,65,19,63,19,27,22,110,19,41,25,43,25, + 16,6,3,19,57,19,57,19,41,19,134,19,146,15,23,12, + 11,12,68, +}; diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -304,7 +304,7 @@ { PyInterpreterState *interp; PyThreadState *tstate; - PyObject *filename_obj, *loader_type, *loader; + PyObject *filename_obj, *bootstrap, *loader_type = NULL, *loader; int result = 0; filename_obj = PyUnicode_DecodeFSDefault(filename); @@ -313,7 +313,12 @@ /* Get current thread state and interpreter pointer */ tstate = PyThreadState_GET(); interp = tstate->interp; - loader_type = PyObject_GetAttrString(interp->importlib, loader_name); + bootstrap = PyObject_GetAttrString(interp->importlib, + "_bootstrap_external"); + if (bootstrap != NULL) { + loader_type = PyObject_GetAttrString(bootstrap, loader_name); + Py_DECREF(bootstrap); + } if (loader_type == NULL) { Py_DECREF(filename_obj); return -1; diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py --- a/Tools/freeze/freeze.py +++ b/Tools/freeze/freeze.py @@ -366,8 +366,10 @@ mf.load_file(mod) # Alias "importlib._bootstrap" to "_frozen_importlib" so that the - # import machinery can bootstrap. + # import machinery can bootstrap. Do the same for + # importlib._bootstrap_external. mf.modules["_frozen_importlib"] = mf.modules["importlib._bootstrap"] + mf.modules["_frozen_importlib_external"] = mf.modules["importlib._bootstrap_external"] # Add the main script as either __main__, or the actual module name. if python_entry_is_main: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 03:38:35 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 03 May 2015 01:38:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Asyncio_issue_?= =?utf-8?q?222_/_PR_231_=28Victor_Stinner=29_--_fix_=40coroutine_functions?= =?utf-8?q?_without?= Message-ID: <20150503013835.25433.40255@psf.io> https://hg.python.org/cpython/rev/3795daceff85 changeset: 95855:3795daceff85 branch: 3.4 parent: 95848:c5c65ef84a77 user: Guido van Rossum date: Sat May 02 18:38:24 2015 -0700 summary: Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine functions without __name__. files: Lib/asyncio/coroutines.py | 18 +++- Lib/asyncio/events.py | 14 ++- Lib/asyncio/futures.py | 2 +- Lib/test/test_asyncio/test_tasks.py | 65 +++++++++++----- Misc/NEWS | 3 + 5 files changed, 70 insertions(+), 32 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -151,7 +151,8 @@ w = CoroWrapper(coro(*args, **kwds), func) if w._source_traceback: del w._source_traceback[-1] - w.__name__ = func.__name__ + if hasattr(func, '__name__'): + w.__name__ = func.__name__ if hasattr(func, '__qualname__'): w.__qualname__ = func.__qualname__ w.__doc__ = func.__doc__ @@ -175,25 +176,30 @@ def _format_coroutine(coro): assert iscoroutine(coro) - coro_name = getattr(coro, '__qualname__', coro.__name__) + + if isinstance(coro, CoroWrapper): + func = coro.func + else: + func = coro + coro_name = events._format_callback(func, ()) filename = coro.gi_code.co_filename if (isinstance(coro, CoroWrapper) and not inspect.isgeneratorfunction(coro.func)): filename, lineno = events._get_function_source(coro.func) if coro.gi_frame is None: - coro_repr = ('%s() done, defined at %s:%s' + coro_repr = ('%s done, defined at %s:%s' % (coro_name, filename, lineno)) else: - coro_repr = ('%s() running, defined at %s:%s' + coro_repr = ('%s running, defined at %s:%s' % (coro_name, filename, lineno)) elif coro.gi_frame is not None: lineno = coro.gi_frame.f_lineno - coro_repr = ('%s() running at %s:%s' + coro_repr = ('%s running at %s:%s' % (coro_name, filename, lineno)) else: lineno = coro.gi_code.co_firstlineno - coro_repr = ('%s() done, defined at %s:%s' + coro_repr = ('%s done, defined at %s:%s' % (coro_name, filename, lineno)) return coro_repr diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -54,15 +54,21 @@ suffix = _format_args(args) + suffix return _format_callback(func.func, func.args, suffix) - func_repr = getattr(func, '__qualname__', None) - if not func_repr: + if hasattr(func, '__qualname__'): + func_repr = getattr(func, '__qualname__') + elif hasattr(func, '__name__'): + func_repr = getattr(func, '__name__') + else: func_repr = repr(func) if args is not None: func_repr += _format_args(args) if suffix: func_repr += suffix + return func_repr +def _format_callback_source(func, args): + func_repr = _format_callback(func, args) source = _get_function_source(func) if source: func_repr += ' at %s:%s' % source @@ -92,7 +98,7 @@ if self._cancelled: info.append('cancelled') if self._callback is not None: - info.append(_format_callback(self._callback, self._args)) + info.append(_format_callback_source(self._callback, self._args)) if self._source_traceback: frame = self._source_traceback[-1] info.append('created at %s:%s' % (frame[0], frame[1])) @@ -119,7 +125,7 @@ try: self._callback(*self._args) except Exception as exc: - cb = _format_callback(self._callback, self._args) + cb = _format_callback_source(self._callback, self._args) msg = 'Exception in callback {}'.format(cb) context = { 'message': msg, diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -162,7 +162,7 @@ cb = '' def format_cb(callback): - return events._format_callback(callback, ()) + return events._format_callback_source(callback, ()) if size == 1: cb = format_cb(cb[0]) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1,5 +1,7 @@ """Tests for tasks.py.""" +import contextlib +import functools import os import re import sys @@ -28,6 +30,19 @@ pass + at contextlib.contextmanager +def set_coroutine_debug(enabled): + coroutines = asyncio.coroutines + + old_debug = coroutines._DEBUG + try: + coroutines._DEBUG = enabled + yield + finally: + coroutines._DEBUG = old_debug + + + def format_coroutine(qualname, state, src, source_traceback, generator=False): if generator: state = '%s' % state @@ -279,6 +294,29 @@ fut.set_result(None) self.loop.run_until_complete(task) + def test_task_repr_partial_corowrapper(self): + # Issue #222: repr(CoroWrapper) must not fail in debug mode if the + # coroutine is a partial function + with set_coroutine_debug(True): + self.loop.set_debug(True) + + @asyncio.coroutine + def func(x, y): + yield from asyncio.sleep(0) + + partial_func = asyncio.coroutine(functools.partial(func, 1)) + task = self.loop.create_task(partial_func(2)) + + # make warnings quiet + task._log_destroy_pending = False + self.addCleanup(task._coro.close) + + coro_repr = repr(task._coro) + expected = ('.func(1)() running, ') + self.assertTrue(coro_repr.startswith(expected), + coro_repr) + def test_task_basics(self): @asyncio.coroutine def outer(): @@ -1555,25 +1593,16 @@ # The frame should have changed. self.assertIsNone(gen.gi_frame) - # Save debug flag. - old_debug = asyncio.coroutines._DEBUG - try: - # Test with debug flag cleared. - asyncio.coroutines._DEBUG = False + # Test with debug flag cleared. + with set_coroutine_debug(False): check() - # Test with debug flag set. - asyncio.coroutines._DEBUG = True + # Test with debug flag set. + with set_coroutine_debug(True): check() - finally: - # Restore original debug flag. - asyncio.coroutines._DEBUG = old_debug - def test_yield_from_corowrapper(self): - old_debug = asyncio.coroutines._DEBUG - asyncio.coroutines._DEBUG = True - try: + with set_coroutine_debug(True): @asyncio.coroutine def t1(): return (yield from t2()) @@ -1591,8 +1620,6 @@ task = asyncio.Task(t1(), loop=self.loop) val = self.loop.run_until_complete(task) self.assertEqual(val, (1, 2, 3)) - finally: - asyncio.coroutines._DEBUG = old_debug def test_yield_from_corowrapper_send(self): def foo(): @@ -1663,14 +1690,10 @@ @mock.patch('asyncio.coroutines.logger') def test_coroutine_never_yielded(self, m_log): - debug = asyncio.coroutines._DEBUG - try: - asyncio.coroutines._DEBUG = True + with set_coroutine_debug(True): @asyncio.coroutine def coro_noop(): pass - finally: - asyncio.coroutines._DEBUG = debug tb_filename = __file__ tb_lineno = sys._getframe().f_lineno + 2 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Library ------- +- Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine + functions without __name__. + - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 03:46:18 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 03 May 2015 01:46:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Asyncio_issue_222_/_PR_231_=28Victor_Stinner=29_--_fix_?= =?utf-8?q?=40coroutine_functions_without?= Message-ID: <20150503014618.14350.20747@psf.io> https://hg.python.org/cpython/rev/352d1fb2a8e4 changeset: 95856:352d1fb2a8e4 parent: 95854:02e3bf65b2f8 parent: 95855:3795daceff85 user: Guido van Rossum date: Sat May 02 18:45:51 2015 -0700 summary: Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine functions without __name__. (Merged from 3.4 branch.) files: Lib/asyncio/coroutines.py | 18 +++- Lib/asyncio/events.py | 14 ++- Lib/asyncio/futures.py | 2 +- Lib/test/test_asyncio/test_tasks.py | 65 +++++++++++----- Misc/NEWS | 27 +++++++ 5 files changed, 94 insertions(+), 32 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -151,7 +151,8 @@ w = CoroWrapper(coro(*args, **kwds), func) if w._source_traceback: del w._source_traceback[-1] - w.__name__ = func.__name__ + if hasattr(func, '__name__'): + w.__name__ = func.__name__ if hasattr(func, '__qualname__'): w.__qualname__ = func.__qualname__ w.__doc__ = func.__doc__ @@ -175,25 +176,30 @@ def _format_coroutine(coro): assert iscoroutine(coro) - coro_name = getattr(coro, '__qualname__', coro.__name__) + + if isinstance(coro, CoroWrapper): + func = coro.func + else: + func = coro + coro_name = events._format_callback(func, ()) filename = coro.gi_code.co_filename if (isinstance(coro, CoroWrapper) and not inspect.isgeneratorfunction(coro.func)): filename, lineno = events._get_function_source(coro.func) if coro.gi_frame is None: - coro_repr = ('%s() done, defined at %s:%s' + coro_repr = ('%s done, defined at %s:%s' % (coro_name, filename, lineno)) else: - coro_repr = ('%s() running, defined at %s:%s' + coro_repr = ('%s running, defined at %s:%s' % (coro_name, filename, lineno)) elif coro.gi_frame is not None: lineno = coro.gi_frame.f_lineno - coro_repr = ('%s() running at %s:%s' + coro_repr = ('%s running at %s:%s' % (coro_name, filename, lineno)) else: lineno = coro.gi_code.co_firstlineno - coro_repr = ('%s() done, defined at %s:%s' + coro_repr = ('%s done, defined at %s:%s' % (coro_name, filename, lineno)) return coro_repr diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -54,15 +54,21 @@ suffix = _format_args(args) + suffix return _format_callback(func.func, func.args, suffix) - func_repr = getattr(func, '__qualname__', None) - if not func_repr: + if hasattr(func, '__qualname__'): + func_repr = getattr(func, '__qualname__') + elif hasattr(func, '__name__'): + func_repr = getattr(func, '__name__') + else: func_repr = repr(func) if args is not None: func_repr += _format_args(args) if suffix: func_repr += suffix + return func_repr +def _format_callback_source(func, args): + func_repr = _format_callback(func, args) source = _get_function_source(func) if source: func_repr += ' at %s:%s' % source @@ -92,7 +98,7 @@ if self._cancelled: info.append('cancelled') if self._callback is not None: - info.append(_format_callback(self._callback, self._args)) + info.append(_format_callback_source(self._callback, self._args)) if self._source_traceback: frame = self._source_traceback[-1] info.append('created at %s:%s' % (frame[0], frame[1])) @@ -119,7 +125,7 @@ try: self._callback(*self._args) except Exception as exc: - cb = _format_callback(self._callback, self._args) + cb = _format_callback_source(self._callback, self._args) msg = 'Exception in callback {}'.format(cb) context = { 'message': msg, diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -162,7 +162,7 @@ cb = '' def format_cb(callback): - return events._format_callback(callback, ()) + return events._format_callback_source(callback, ()) if size == 1: cb = format_cb(cb[0]) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1,5 +1,7 @@ """Tests for tasks.py.""" +import contextlib +import functools import os import re import sys @@ -28,6 +30,19 @@ pass + at contextlib.contextmanager +def set_coroutine_debug(enabled): + coroutines = asyncio.coroutines + + old_debug = coroutines._DEBUG + try: + coroutines._DEBUG = enabled + yield + finally: + coroutines._DEBUG = old_debug + + + def format_coroutine(qualname, state, src, source_traceback, generator=False): if generator: state = '%s' % state @@ -279,6 +294,29 @@ fut.set_result(None) self.loop.run_until_complete(task) + def test_task_repr_partial_corowrapper(self): + # Issue #222: repr(CoroWrapper) must not fail in debug mode if the + # coroutine is a partial function + with set_coroutine_debug(True): + self.loop.set_debug(True) + + @asyncio.coroutine + def func(x, y): + yield from asyncio.sleep(0) + + partial_func = asyncio.coroutine(functools.partial(func, 1)) + task = self.loop.create_task(partial_func(2)) + + # make warnings quiet + task._log_destroy_pending = False + self.addCleanup(task._coro.close) + + coro_repr = repr(task._coro) + expected = ('.func(1)() running, ') + self.assertTrue(coro_repr.startswith(expected), + coro_repr) + def test_task_basics(self): @asyncio.coroutine def outer(): @@ -1555,25 +1593,16 @@ # The frame should have changed. self.assertIsNone(gen.gi_frame) - # Save debug flag. - old_debug = asyncio.coroutines._DEBUG - try: - # Test with debug flag cleared. - asyncio.coroutines._DEBUG = False + # Test with debug flag cleared. + with set_coroutine_debug(False): check() - # Test with debug flag set. - asyncio.coroutines._DEBUG = True + # Test with debug flag set. + with set_coroutine_debug(True): check() - finally: - # Restore original debug flag. - asyncio.coroutines._DEBUG = old_debug - def test_yield_from_corowrapper(self): - old_debug = asyncio.coroutines._DEBUG - asyncio.coroutines._DEBUG = True - try: + with set_coroutine_debug(True): @asyncio.coroutine def t1(): return (yield from t2()) @@ -1591,8 +1620,6 @@ task = asyncio.Task(t1(), loop=self.loop) val = self.loop.run_until_complete(task) self.assertEqual(val, (1, 2, 3)) - finally: - asyncio.coroutines._DEBUG = old_debug def test_yield_from_corowrapper_send(self): def foo(): @@ -1663,14 +1690,10 @@ @mock.patch('asyncio.coroutines.logger') def test_coroutine_never_yielded(self, m_log): - debug = asyncio.coroutines._DEBUG - try: - asyncio.coroutines._DEBUG = True + with set_coroutine_debug(True): @asyncio.coroutine def coro_noop(): pass - finally: - asyncio.coroutines._DEBUG = debug tb_filename = __file__ tb_lineno = sys._getframe().f_lineno + 2 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -101,6 +101,7 @@ Library ------- +<<<<<<< local - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials @@ -125,6 +126,32 @@ - Issue #21217: inspect.getsourcelines() now tries to compute the start and end lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger and Allison Kaptur. +======= +- Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine + functions without __name__. + +- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. + Patch written by William Orr. + +- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup + and siftdown functions. + +- Backport collections.deque fixes from Python 3.5. Prevents reentrant badness + during deletion by deferring the decref until the container has been restored + to a consistent state. + +- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. + +- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't + increment unfinished tasks (this bug was introduced in 3.4.3 when + JoinableQueue was merged with Queue). + +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. +>>>>>>> other - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 04:37:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 02:37:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_merge_markers?= Message-ID: <20150503023719.25451.76382@psf.io> https://hg.python.org/cpython/rev/47d1f9723a6f changeset: 95857:47d1f9723a6f user: Benjamin Peterson date: Sat May 02 22:34:31 2015 -0400 summary: remove merge markers files: Misc/NEWS | 27 --------------------------- 1 files changed, 0 insertions(+), 27 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -101,7 +101,6 @@ Library ------- -<<<<<<< local - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials @@ -126,32 +125,6 @@ - Issue #21217: inspect.getsourcelines() now tries to compute the start and end lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger and Allison Kaptur. -======= -- Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine - functions without __name__. - -- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. - Patch written by William Orr. - -- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup - and siftdown functions. - -- Backport collections.deque fixes from Python 3.5. Prevents reentrant badness - during deletion by deferring the decref until the container has been restored - to a consistent state. - -- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - -- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't - increment unfinished tasks (this bug was introduced in 3.4.3 when - JoinableQueue was merged with Queue). - -- Issue #23908: os functions now reject paths with embedded null character - on Windows instead of silently truncate them. - -- Issue #23728: binascii.crc_hqx() could return an integer outside of the range - 0-0xffff for empty data. ->>>>>>> other - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 04:37:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 02:37:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3_=28=2324094=29?= Message-ID: <20150503023719.8145.12985@psf.io> https://hg.python.org/cpython/rev/f9027b10b3c4 changeset: 95859:f9027b10b3c4 branch: 3.4 parent: 95855:3795daceff85 parent: 95858:0e8c9cf1fede user: Benjamin Peterson date: Sat May 02 22:36:26 2015 -0400 summary: merge 3.3 (#24094) files: Lib/test/test_json/test_dump.py | 19 ++++++++++++ Misc/NEWS | 3 ++ Modules/_json.c | 31 ++------------------ 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -28,6 +28,25 @@ self.assertEqual(self.dumps(a, default=crasher), '[null, null, null, null, null]') + # Issue 24094 + def test_encode_evil_dict(self): + class D(dict): + def keys(self): + return L + + class X: + def __hash__(self): + del L[0] + return 1337 + + def __lt__(self, o): + return 0 + + L = [X() for i in range(1122)] + d = D() + d[1337] = "true.dat" + self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}') + class TestPyDump(TestDump, PyTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Library ------- +- Issue #24094: Fix possible crash in json.encode with poorly behaved dict + subclasses. + - Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine functions without __name__. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1541,36 +1541,11 @@ */ } - if (PyObject_IsTrue(s->sort_keys)) { - /* First sort the keys then replace them with (key, value) tuples. */ - Py_ssize_t i, nitems; - items = PyMapping_Keys(dct); - if (items == NULL) - goto bail; - if (!PyList_Check(items)) { - PyErr_SetString(PyExc_ValueError, "keys must return list"); - goto bail; - } - if (PyList_Sort(items) < 0) - goto bail; - nitems = PyList_GET_SIZE(items); - for (i = 0; i < nitems; i++) { - PyObject *key, *value; - key = PyList_GET_ITEM(items, i); - value = PyDict_GetItem(dct, key); - item = PyTuple_Pack(2, key, value); - if (item == NULL) - goto bail; - PyList_SET_ITEM(items, i, item); - item = NULL; - Py_DECREF(key); - } - } - else { - items = PyMapping_Items(dct); - } + items = PyMapping_Items(dct); if (items == NULL) goto bail; + if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 04:37:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 02:37:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_just_sort_the_?= =?utf-8?q?items_tuple_directly_=28closes_=2324094=29?= Message-ID: <20150503023719.25441.10227@psf.io> https://hg.python.org/cpython/rev/0e8c9cf1fede changeset: 95858:0e8c9cf1fede branch: 3.3 parent: 95787:0d8f15053f42 user: Benjamin Peterson date: Sat May 02 22:28:04 2015 -0400 summary: just sort the items tuple directly (closes #24094) files: Lib/test/test_json/test_dump.py | 19 +++++++++++++ Misc/NEWS | 3 ++ Modules/_json.c | 30 ++------------------ 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -28,6 +28,25 @@ self.assertEqual(self.dumps(a, default=crasher), '[null, null, null, null, null]') + # Issue 24094 + def test_encode_evil_dict(self): + class D(dict): + def keys(self): + return L + + class X: + def __hash__(self): + del L[0] + return 1337 + + def __lt__(self, o): + return 0 + + L = [X() for i in range(1122)] + d = D() + d[1337] = "true.dat" + self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}') + class TestPyDump(TestDump, PyTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #24094: Fix possible crash in json.encode with poorly behaved dict + subclasses. + - Issue #23367: Fix possible overflows in the unicodedata module. - Issue #23361: Fix possible overflow in Windows subprocess creation code. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1527,35 +1527,11 @@ */ } - if (PyObject_IsTrue(s->sort_keys)) { - /* First sort the keys then replace them with (key, value) tuples. */ - Py_ssize_t i, nitems; - items = PyMapping_Keys(dct); - if (items == NULL) - goto bail; - if (!PyList_Check(items)) { - PyErr_SetString(PyExc_ValueError, "keys must return list"); - goto bail; - } - if (PyList_Sort(items) < 0) - goto bail; - nitems = PyList_GET_SIZE(items); - for (i = 0; i < nitems; i++) { - PyObject *key, *value; - key = PyList_GET_ITEM(items, i); - value = PyDict_GetItem(dct, key); - item = PyTuple_Pack(2, key, value); - if (item == NULL) - goto bail; - PyList_SET_ITEM(items, i, item); - Py_DECREF(key); - } - } - else { - items = PyMapping_Items(dct); - } + items = PyMapping_Items(dct); if (items == NULL) goto bail; + if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 04:37:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 02:37:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwOTQp?= Message-ID: <20150503023719.7812.88087@psf.io> https://hg.python.org/cpython/rev/3bdf1816f561 changeset: 95860:3bdf1816f561 parent: 95857:47d1f9723a6f parent: 95859:f9027b10b3c4 user: Benjamin Peterson date: Sat May 02 22:37:13 2015 -0400 summary: merge 3.4 (#24094) files: Lib/test/test_json/test_dump.py | 19 ++++++++++++ Misc/NEWS | 3 ++ Modules/_json.c | 31 ++------------------ 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -28,6 +28,25 @@ self.assertEqual(self.dumps(a, default=crasher), '[null, null, null, null, null]') + # Issue 24094 + def test_encode_evil_dict(self): + class D(dict): + def keys(self): + return L + + class X: + def __hash__(self): + del L[0] + return 1337 + + def __lt__(self, o): + return 0 + + L = [X() for i in range(1122)] + d = D() + d[1337] = "true.dat" + self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}') + class TestPyDump(TestDump, PyTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,9 @@ Library ------- +- Issue #24094: Fix possible crash in json.encode with poorly behaved dict + subclasses. + - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1663,36 +1663,11 @@ */ } - if (PyObject_IsTrue(s->sort_keys)) { - /* First sort the keys then replace them with (key, value) tuples. */ - Py_ssize_t i, nitems; - items = PyMapping_Keys(dct); - if (items == NULL) - goto bail; - if (!PyList_Check(items)) { - PyErr_SetString(PyExc_ValueError, "keys must return list"); - goto bail; - } - if (PyList_Sort(items) < 0) - goto bail; - nitems = PyList_GET_SIZE(items); - for (i = 0; i < nitems; i++) { - PyObject *key, *value; - key = PyList_GET_ITEM(items, i); - value = PyDict_GetItem(dct, key); - item = PyTuple_Pack(2, key, value); - if (item == NULL) - goto bail; - PyList_SET_ITEM(items, i, item); - item = NULL; - Py_DECREF(key); - } - } - else { - items = PyMapping_Items(dct); - } + items = PyMapping_Items(dct); if (items == NULL) goto bail; + if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 06:38:57 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 03 May 2015 04:38:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Replaces_use_of_WinRAR_to_?= =?utf-8?q?generate_ZIP_file_with_Python_script?= Message-ID: <20150503043857.76614.96207@psf.io> https://hg.python.org/cpython/rev/d9383a95b011 changeset: 95861:d9383a95b011 user: Steve Dower date: Sat May 02 21:38:26 2015 -0700 summary: Replaces use of WinRAR to generate ZIP file with Python script files: Tools/msi/buildrelease.bat | 9 +-------- Tools/msi/make_zip.proj | 1 - Tools/msi/make_zip.py | 18 ++++-------------- Tools/msi/uploadrelease.proj | 2 +- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat --- a/Tools/msi/buildrelease.bat +++ b/Tools/msi/buildrelease.bat @@ -64,13 +64,6 @@ set _DLLTOOL_PATH= :skipdlltoolsearch -where rar /q && goto skiprarsearch -set _RAR_PATH= -where /R "%ProgramFiles%\WinRAR" rar > "%TEMP%\rar.loc" 2> nul && set /P _RAR_PATH= < "%TEMP%\rar.loc" & del "%TEMP%\rar.loc" -where /R "%ProgramFiles(x86)%\WinRAR" rar > "%TEMP%\rar.loc" 2> nul && set /P _RAR_PATH= < "%TEMP%\rar.loc" & del "%TEMP%\rar.loc" -if not exist "%_RAR_PATH%" echo Cannot find WinRAR on PATH or in external && pause -:skiprarsearch - if defined BUILDX86 ( call :build x86 if errorlevel 1 exit /B @@ -142,7 +135,7 @@ msbuild "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false if errorlevel 1 exit /B -if defined _RAR_PATH msbuild "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS% "/p:RAR=%_RAR_PATH%" +msbuild "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS% if not "%OUTDIR%" EQU "" ( mkdir "%OUTDIR%\%OUTDIR_PLAT%" diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj --- a/Tools/msi/make_zip.proj +++ b/Tools/msi/make_zip.proj @@ -15,7 +15,6 @@ $(OutputPath)\en-us\$(TargetName)$(TargetExt) "$(PythonExe)" "$(MSBuildThisFileDirectory)\make_zip.py" $(Arguments) -e -o "$(TargetPath)" -t "$(IntermediateOutputPath)\zip_$(ArchName)" -a $(ArchName) - $(Arguments) --rar "$(RAR)" set DOC_FILENAME=python$(PythonVersion).chm diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -72,7 +72,7 @@ ('python35.zip', 'Lib', '**/*', include_in_lib), ] -def copy_to_layout(target, source, rel_sources): +def copy_to_layout(target, rel_sources): count = 0 if target.suffix.lower() == '.zip': @@ -146,21 +146,11 @@ try: for t, s, p, c in layout: s = source / s.replace("$arch", arch) - copied = copy_to_layout( - temp / t.rstrip('/'), - source, - rglob(s, p, c) - ) + copied = copy_to_layout(temp / t.rstrip('/'), rglob(s, p, c)) print('Copied {} files'.format(copied)) - if rar and rar.is_file(): - subprocess.check_call([ - str(rar), - "a", - "-ed", "-ep1", "-s", "-r", - str(out), - str(temp / '*') - ]) + total = copy_to_layout(out, rglob(temp, '*', None)) + print('Wrote {} files to {}'.format(total, out)) finally: if delete_temp: shutil.rmtree(temp, True) diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj --- a/Tools/msi/uploadrelease.proj +++ b/Tools/msi/uploadrelease.proj @@ -23,7 +23,7 @@ $(MSITarget) - + $(EXETarget) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 07:29:50 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 03 May 2015 05:29:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_documentation_for_?= =?utf-8?q?installing_Python_on_Windows=2E?= Message-ID: <20150503052950.11948.38987@psf.io> https://hg.python.org/cpython/rev/f12a0c27e13f changeset: 95862:f12a0c27e13f user: Steve Dower date: Sat May 02 22:28:58 2015 -0700 summary: Updates documentation for installing Python on Windows. files: Doc/using/win_installer.png | Bin Doc/using/windows.rst | 46 +++++++++++------------ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index 4696bb2a400eb1c7ab18b48e9eda9a004e08749f..8e258927c32ad46be2125cae89f90a770a8c34ba GIT binary patch [stripped] diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -12,11 +12,6 @@ This document aims to give an overview of Windows-specific behaviour you should know about when using Python on Microsoft Windows. -.. XXX (ncoghlan) - - This looks rather stale to me... - - Installing Python ================= @@ -24,11 +19,10 @@ supported installation of Python. To make Python available, the CPython team has compiled Windows installers (MSI packages) with every `release `_ for many years. These installers -are primarily intended to add a system-wide installation of Python, with the -core interpreter and library being shared by all application. Non-shared -layouts of the Python interpreter may also be created with the same installer, -however, the released installer is not intended for embedding in other -installers. +are primarily intended to add a per-user installation of Python, with the +core interpreter and library being used by a single user. The installer is also +able to install for all users of a single machine, and a separate ZIP file is +available for application-local distributions. Installation Steps ------------------ @@ -41,31 +35,35 @@ features. See :ref:`install-layout-option` for other ways to avoid downloading during installation. -After starting the installer, one of three options may be selected: +After starting the installer, one of two options may be selected: .. image:: win_installer.png -If you select "Install for All Users": +If you select "Install Now": -* You may be required to provide administrative credentials or approval -* Python will be installed into your Program Files directory -* The :ref:`launcher` will be installed into your Windows directory -* The standard library, test suite, launcher and pip will be installed -* After installation, the standard library will be pre-compiled to bytecode -* If selected, the install directory will be added to :envvar:`PATH` - -If you select "Install Just for Me": - -* You will *not* need to be an administrator +* You will *not* need to be an administrator (unless a system update for the + C Runtime Library is required) * Python will be installed into your user directory * The :ref:`launcher` will *also* be installed into your user directory * The standard library, test suite, launcher and pip will be installed -* If selected, the install directory will be added to :envvar:`PATH` +* If selected, the install directory will be added to your :envvar:`PATH` +* Shortcuts will only be visible for the current user Selecting "Customize installation" will allow you to select the features to install, the installation location and other options or post-install actions. To install debugging symbols or binaries, you will need to use this option. +To perform an all-users installation, you should select "Customize +installation". In this case: + +* You may be required to provide administrative credentials or approval +* Python will be installed into the Program Files directory +* The :ref:`launcher` will be installed into the Windows directory +* Optional features may be selected during installation +* The standard library will be pre-compiled to bytecode +* If selected, the install directory will be added to the system :envvar:`PATH` +* Shortcuts are available for all users + .. _install-quiet-option: Installing Without UI @@ -294,7 +292,7 @@ The :envvar:`PYTHONPATH` variable is used by all versions of Python 2 and Python 3, so you should not permanently configure this variable unless it - only includes code that is compatible all of your installed Python + only includes code that is compatible with all of your installed Python versions. .. seealso:: -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun May 3 10:36:52 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 03 May 2015 08:36:52 +0000 Subject: [Python-checkins] Daily reference leaks (f12a0c27e13f): sum=-1 Message-ID: <20150503083651.8940.38976@psf.io> results for f12a0c27e13f on branch "default" -------------------------------------------- test_collections leaked [-2, -2, 0] references, sum=-4 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogLnZuXL', '--timeout', '7200'] From python-checkins at python.org Sun May 3 12:32:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 10:32:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322619=3A_Added_ne?= =?utf-8?q?gative_limit_support_in_the_traceback_module=2E?= Message-ID: <20150503103220.25445.23987@psf.io> https://hg.python.org/cpython/rev/eb6052605fd8 changeset: 95863:eb6052605fd8 user: Serhiy Storchaka date: Sun May 03 13:19:46 2015 +0300 summary: Issue #22619: Added negative limit support in the traceback module. Based on patch by Dmitry Kazakov. files: Doc/library/traceback.rst | 52 ++++++--- Lib/test/test_traceback.py | 127 ++++++++++++++++++++++++- Lib/traceback.py | 14 +- Misc/ACKS | 1 + Misc/NEWS | 3 + 5 files changed, 170 insertions(+), 27 deletions(-) diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -22,15 +22,20 @@ .. function:: print_tb(traceback, limit=None, file=None) - Print up to *limit* stack trace entries from *traceback*. If *limit* is omitted - or ``None``, all entries are printed. If *file* is omitted or ``None``, the - output goes to ``sys.stderr``; otherwise it should be an open file or file-like - object to receive the output. + Print up to *limit* stack trace entries from *traceback* (starting from + the caller's frame) if *limit* is positive. Otherwise, print the last + ``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries + are printed. If *file* is omitted or ``None``, the output goes to + ``sys.stderr``; otherwise it should be an open file or file-like object + to receive the output. + + .. versionchanged:: 3.5 + Added negative *limit* support. .. function:: print_exception(type, value, traceback, limit=None, file=None, chain=True) - Print exception information and up to *limit* stack trace entries from + Print exception information and stack trace entries from *traceback* to *file*. This differs from :func:`print_tb` in the following ways: @@ -41,6 +46,7 @@ prints the line where the syntax error occurred with a caret indicating the approximate position of the error. + The optional *limit* argument has the same meaning as for :func:`print_tb`. If *chain* is true (the default), then chained exceptions (the :attr:`__cause__` or :attr:`__context__` attributes of the exception) will be printed as well, like the interpreter itself does when printing an unhandled @@ -49,33 +55,41 @@ .. function:: print_exc(limit=None, file=None, chain=True) - This is a shorthand for ``print_exception(*sys.exc_info())``. + This is a shorthand for ``print_exception(*sys.exc_info(), limit, file, + chain)``. .. function:: print_last(limit=None, file=None, chain=True) This is a shorthand for ``print_exception(sys.last_type, sys.last_value, - sys.last_traceback, limit, file)``. In general it will work only after - an exception has reached an interactive prompt (see :data:`sys.last_type`). + sys.last_traceback, limit, file, chain)``. In general it will work only + after an exception has reached an interactive prompt (see + :data:`sys.last_type`). .. function:: print_stack(f=None, limit=None, file=None) - This function prints a stack trace from its invocation point. The optional *f* - argument can be used to specify an alternate stack frame to start. The optional - *limit* and *file* arguments have the same meaning as for - :func:`print_exception`. + Print up to *limit* stack trace entries (starting from the invocation + point) if *limit* is positive. Otherwise, print the last ``abs(limit)`` + entries. If *limit* is omitted or ``None``, all entries are printed. + The optional *f* argument can be used to specify an alternate stack frame + to start. The optional *file* argument has the same meaning as for + :func:`print_tb`. + + .. versionchanged:: 3.5 + Added negative *limit* support. .. function:: extract_tb(traceback, limit=None) - Return a list of up to *limit* "pre-processed" stack trace entries extracted - from the traceback object *traceback*. It is useful for alternate formatting of - stack traces. If *limit* is omitted or ``None``, all entries are extracted. A - "pre-processed" stack trace entry is a 4-tuple (*filename*, *line number*, - *function name*, *text*) representing the information that is usually printed - for a stack trace. The *text* is a string with leading and trailing whitespace - stripped; if the source is not available it is ``None``. + Return a list of "pre-processed" stack trace entries extracted from the + traceback object *traceback*. It is useful for alternate formatting of + stack traces. The optional *limit* argument has the same meaning as for + :func:`print_tb`. A "pre-processed" stack trace entry is a 4-tuple + (*filename*, *line number*, *function name*, *text*) representing the + information that is usually printed for a stack trace. The *text* is a + string with leading and trailing whitespace stripped; if the source is + not available it is ``None``. .. function:: extract_stack(f=None, limit=None) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -6,6 +6,7 @@ import sys import unittest import re +from test import support from test.support import TESTFN, Error, captured_output, unlink, cpython_only from test.script_helper import assert_python_ok import textwrap @@ -453,6 +454,126 @@ return s.getvalue() +class LimitTests(unittest.TestCase): + + ''' Tests for limit argument. + It's enough to test extact_tb, extract_stack and format_exception ''' + + def last_raises1(self): + raise Exception('Last raised') + + def last_raises2(self): + self.last_raises1() + + def last_raises3(self): + self.last_raises2() + + def last_raises4(self): + self.last_raises3() + + def last_raises5(self): + self.last_raises4() + + def last_returns_frame1(self): + return sys._getframe() + + def last_returns_frame2(self): + return self.last_returns_frame1() + + def last_returns_frame3(self): + return self.last_returns_frame2() + + def last_returns_frame4(self): + return self.last_returns_frame3() + + def last_returns_frame5(self): + return self.last_returns_frame4() + + def test_extract_stack(self): + frame = self.last_returns_frame5() + def extract(**kwargs): + return traceback.extract_stack(frame, **kwargs) + def assertEqualExcept(actual, expected, ignore): + self.assertEqual(actual[:ignore], expected[:ignore]) + self.assertEqual(actual[ignore+1:], expected[ignore+1:]) + self.assertEqual(len(actual), len(expected)) + + with support.swap_attr(sys, 'tracebacklimit', 1000): + nolim = extract() + self.assertGreater(len(nolim), 5) + self.assertEqual(extract(limit=2), nolim[-2:]) + assertEqualExcept(extract(limit=100), nolim[-100:], -5-1) + self.assertEqual(extract(limit=-2), nolim[:2]) + assertEqualExcept(extract(limit=-100), nolim[:100], len(nolim)-5-1) + self.assertEqual(extract(limit=0), []) + del sys.tracebacklimit + assertEqualExcept(extract(), nolim, -5-1) + sys.tracebacklimit = 2 + self.assertEqual(extract(), nolim[-2:]) + self.assertEqual(extract(limit=3), nolim[-3:]) + self.assertEqual(extract(limit=-3), nolim[:3]) + sys.tracebacklimit = 0 + self.assertEqual(extract(), []) + sys.tracebacklimit = -1 + self.assertEqual(extract(), []) + + def test_extract_tb(self): + try: + self.last_raises5() + except Exception: + exc_type, exc_value, tb = sys.exc_info() + def extract(**kwargs): + return traceback.extract_tb(tb, **kwargs) + + with support.swap_attr(sys, 'tracebacklimit', 1000): + nolim = extract() + self.assertEqual(len(nolim), 5+1) + self.assertEqual(extract(limit=2), nolim[:2]) + self.assertEqual(extract(limit=10), nolim) + self.assertEqual(extract(limit=-2), nolim[-2:]) + self.assertEqual(extract(limit=-10), nolim) + self.assertEqual(extract(limit=0), []) + del sys.tracebacklimit + self.assertEqual(extract(), nolim) + sys.tracebacklimit = 2 + self.assertEqual(extract(), nolim[:2]) + self.assertEqual(extract(limit=3), nolim[:3]) + self.assertEqual(extract(limit=-3), nolim[-3:]) + sys.tracebacklimit = 0 + self.assertEqual(extract(), []) + sys.tracebacklimit = -1 + self.assertEqual(extract(), []) + + def test_format_exception(self): + try: + self.last_raises5() + except Exception: + exc_type, exc_value, tb = sys.exc_info() + # [1:-1] to exclude "Traceback (...)" header and + # exception type and value + def extract(**kwargs): + return traceback.format_exception(exc_type, exc_value, tb, **kwargs)[1:-1] + + with support.swap_attr(sys, 'tracebacklimit', 1000): + nolim = extract() + self.assertEqual(len(nolim), 5+1) + self.assertEqual(extract(limit=2), nolim[:2]) + self.assertEqual(extract(limit=10), nolim) + self.assertEqual(extract(limit=-2), nolim[-2:]) + self.assertEqual(extract(limit=-10), nolim) + self.assertEqual(extract(limit=0), []) + del sys.tracebacklimit + self.assertEqual(extract(), nolim) + sys.tracebacklimit = 2 + self.assertEqual(extract(), nolim[:2]) + self.assertEqual(extract(limit=3), nolim[:3]) + self.assertEqual(extract(limit=-3), nolim[-3:]) + sys.tracebacklimit = 0 + self.assertEqual(extract(), []) + sys.tracebacklimit = -1 + self.assertEqual(extract(), []) + + class MiscTracebackCases(unittest.TestCase): # # Check non-printing functions in traceback module @@ -592,16 +713,14 @@ traceback.walk_stack(None), capture_locals=True, limit=1) s = some_inner(3, 4) self.assertEqual( - [' File "' + __file__ + '", line 592, ' - 'in some_inner\n' + [' File "%s", line %d, in some_inner\n' ' traceback.walk_stack(None), capture_locals=True, limit=1)\n' ' a = 1\n' ' b = 2\n' ' k = 3\n' - ' v = 4\n' + ' v = 4\n' % (__file__, some_inner.__code__.co_firstlineno + 4) ], s.format()) - class TestTracebackException(unittest.TestCase): def test_smoke(self): diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1,8 +1,9 @@ """Extract, format and print information about Python stack traces.""" +import collections +import itertools import linecache import sys -import operator __all__ = ['extract_stack', 'extract_tb', 'format_exception', 'format_exception_only', 'format_list', 'format_stack', @@ -315,12 +316,17 @@ """ if limit is None: limit = getattr(sys, 'tracebacklimit', None) + if limit is not None and limit < 0: + limit = 0 + if limit is not None: + if limit >= 0: + frame_gen = itertools.islice(frame_gen, limit) + else: + frame_gen = collections.deque(frame_gen, maxlen=-limit) result = klass() fnames = set() - for pos, (f, lineno) in enumerate(frame_gen): - if limit is not None and pos >= limit: - break + for f, lineno in frame_gen: co = f.f_code filename = co.co_filename name = co.co_name diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -712,6 +712,7 @@ Lou Kates Makoto Kato Hiroaki Kawai +Dmitry Kazakov Brian Kearns Sebastien Keim Ryan Kelly diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,9 @@ Library ------- +- Issue #22619: Added negative limit support in the traceback module. + Based on patch by Dmitry Kazakov. + - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMzMw?= =?utf-8?q?=3A_h2py_now_supports_arbitrary_filenames_in_=23include=2E?= Message-ID: <20150503131846.84490.50921@psf.io> https://hg.python.org/cpython/rev/b32ca610c9e6 changeset: 95864:b32ca610c9e6 branch: 2.7 parent: 95850:5d356223f075 user: Serhiy Storchaka date: Sun May 03 15:35:02 2015 +0300 summary: Issue #23330: h2py now supports arbitrary filenames in #include. files: Misc/NEWS | 2 ++ Tools/scripts/h2py.py | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -210,6 +210,8 @@ Tools/Demos ----------- +- Issue #23330: h2py now supports arbitrary filenames in #include. + - Issue #6639: Module-level turtle functions no longer raise TclError after closing the window. diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py --- a/Tools/scripts/h2py.py +++ b/Tools/scripts/h2py.py @@ -29,7 +29,7 @@ '^[\t ]*#[\t ]*define[\t ]+' '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+') -p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)') +p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([^>\n]+)>') p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?') p_cpp_comment = re.compile('//.*') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323330=3A_h2py_now_supports_arbitrary_filenames_?= =?utf-8?q?in_=23include=2E?= Message-ID: <20150503131846.76602.42303@psf.io> https://hg.python.org/cpython/rev/f49e7e315d65 changeset: 95866:f49e7e315d65 parent: 95863:eb6052605fd8 parent: 95865:0079465a9425 user: Serhiy Storchaka date: Sun May 03 15:36:37 2015 +0300 summary: Issue #23330: h2py now supports arbitrary filenames in #include. files: Misc/NEWS | 3 +++ Tools/scripts/h2py.py | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -65,8 +65,11 @@ Tools/Demos ----------- +- Issue #23330: h2py now supports arbitrary filenames in #include. + - Issue #24031: make patchcheck now supports git checkouts, too. + What's New in Python 3.5.0 alpha 4? =================================== diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py --- a/Tools/scripts/h2py.py +++ b/Tools/scripts/h2py.py @@ -29,7 +29,7 @@ '^[\t ]*#[\t ]*define[\t ]+' '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+') -p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)') +p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([^>\n]+)>') p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?') p_cpp_comment = re.compile('//.*') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMzMw?= =?utf-8?q?=3A_h2py_now_supports_arbitrary_filenames_in_=23include=2E?= Message-ID: <20150503131846.1924.74496@psf.io> https://hg.python.org/cpython/rev/0079465a9425 changeset: 95865:0079465a9425 branch: 3.4 parent: 95859:f9027b10b3c4 user: Serhiy Storchaka date: Sun May 03 15:35:14 2015 +0300 summary: Issue #23330: h2py now supports arbitrary filenames in #include. files: Misc/NEWS | 3 +++ Tools/scripts/h2py.py | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -254,8 +254,11 @@ Tools/Demos ----------- +- Issue #23330: h2py now supports arbitrary filenames in #include. + - Issue #24031: make patchcheck now supports git checkouts, too. + What's New in Python 3.4.3? =========================== diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py --- a/Tools/scripts/h2py.py +++ b/Tools/scripts/h2py.py @@ -29,7 +29,7 @@ '^[\t ]*#[\t ]*define[\t ]+' '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+') -p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)') +p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([^>\n]+)>') p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?') p_cpp_comment = re.compile('//.*') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320148=3A_Converte?= =?utf-8?q?d_the_=5Fsre_module_to_Argument_Clinic=2E?= Message-ID: <20150503131846.7818.83888@psf.io> https://hg.python.org/cpython/rev/d5f78a855355 changeset: 95868:d5f78a855355 user: Serhiy Storchaka date: Sun May 03 15:54:23 2015 +0300 summary: Issue #20148: Converted the _sre module to Argument Clinic. files: Modules/_sre.c | 718 ++++--- Modules/_sre.c | 3231 ++++++----------------------------- 2 files changed, 960 insertions(+), 2989 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -258,25 +258,46 @@ /* see sre.h for object declarations */ static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject*pattern_scanner(PatternObject*, PyObject*, PyObject* kw); - -static PyObject * -sre_codesize(PyObject* self, PyObject *unused) +static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); + + +/*[clinic input] +module _sre +class _sre.SRE_Pattern "PatternObject *" "&Pattern_Type" +class _sre.SRE_Match "MatchObject *" "&Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ + +/*[clinic input] +_sre.getcodesize -> int +[clinic start generated code]*/ + +static int +_sre_getcodesize_impl(PyModuleDef *module) +/*[clinic end generated code: output=794f1f98ef4883e5 input=bd6f6ecf4916bb2b]*/ { - return PyLong_FromSize_t(sizeof(SRE_CODE)); + return sizeof(SRE_CODE); } -static PyObject * -sre_getlower(PyObject* self, PyObject* args) +/*[clinic input] +_sre.getlower -> int + + character: int + flags: int + / + +[clinic start generated code]*/ + +static int +_sre_getlower_impl(PyModuleDef *module, int character, int flags) +/*[clinic end generated code: output=5fc3616ae2a4c306 input=087d2f1c44bbca6f]*/ { - int character, flags; - if (!PyArg_ParseTuple(args, "ii", &character, &flags)) - return NULL; if (flags & SRE_FLAG_LOCALE) - return Py_BuildValue("i", sre_lower_locale(character)); + return sre_lower_locale(character); if (flags & SRE_FLAG_UNICODE) - return Py_BuildValue("i", sre_lower_unicode(character)); - return Py_BuildValue("i", sre_lower(character)); + return sre_lower_unicode(character); + return sre_lower(character); } LOCAL(void) @@ -552,27 +573,32 @@ return string; } +/*[clinic input] +_sre.SRE_Pattern.match + + string: object = NULL + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + * + pattern: object = NULL + +Matches zero or more characters at the beginning of the string. +[clinic start generated code]*/ + static PyObject * -pattern_match(PatternObject *self, PyObject *args, PyObject *kwargs) +_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern) +/*[clinic end generated code: output=74b4b1da3bb2d84e input=3d079aa99979b81d]*/ { - static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL}; - PyObject *string = NULL; - Py_ssize_t pos = 0; - Py_ssize_t endpos = PY_SSIZE_T_MAX; - PyObject *pattern = NULL; SRE_STATE state; Py_ssize_t status; PyObject *match; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|Onn$O:match", _keywords, - &string, &pos, &endpos, &pattern)) - return NULL; string = fix_string_param(string, pattern, "pattern"); if (!string) return NULL; - string = state_init(&state, (PatternObject *)self, string, pos, endpos); - if (!string) + if (!state_init(&state, (PatternObject *)self, string, pos, endpos)) return NULL; state.ptr = state.start; @@ -592,27 +618,33 @@ return match; } -static PyObject* -pattern_fullmatch(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.fullmatch + + string: object = NULL + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + * + pattern: object = NULL + +Matches against all of the string +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern) +/*[clinic end generated code: output=1c98bc5da744ea94 input=d4228606cc12580f]*/ { SRE_STATE state; Py_ssize_t status; PyObject *match; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "pattern", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:fullmatch", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "pattern"); + string = fix_string_param(string, pattern, "pattern"); if (!string) return NULL; - string = state_init(&state, self, string, start, end); - if (!string) + if (!state_init(&state, self, string, pos, endpos)) return NULL; state.ptr = state.start; @@ -632,27 +664,35 @@ return match; } -static PyObject* -pattern_search(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.search + + string: object = NULL + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + * + pattern: object = NULL + +Scan through string looking for a match, and return a corresponding match object instance. + +Return None if no position in the string matches. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern) +/*[clinic end generated code: output=3839394a18e5ea4f input=dab42720f4be3a4b]*/ { SRE_STATE state; Py_ssize_t status; PyObject *match; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "pattern", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:search", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "pattern"); + string = fix_string_param(string, pattern, "pattern"); if (!string) return NULL; - string = state_init(&state, self, string, start, end); - if (!string) + if (!state_init(&state, self, string, pos, endpos)) return NULL; TRACE(("|%p|%p|SEARCH\n", PatternObject_GetCode(self), state.ptr)); @@ -718,28 +758,34 @@ } #endif -static PyObject* -pattern_findall(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.findall + + string: object = NULL + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + * + source: object = NULL + +Return a list of all non-overlapping matches of pattern in string. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *source) +/*[clinic end generated code: output=51295498b300639d input=df688355c056b9de]*/ { SRE_STATE state; PyObject* list; Py_ssize_t status; Py_ssize_t i, b, e; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:findall", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "source"); + string = fix_string_param(string, source, "source"); if (!string) return NULL; - string = state_init(&state, self, string, start, end); - if (!string) + if (!state_init(&state, self, string, pos, endpos)) return NULL; list = PyList_New(0); @@ -819,14 +865,28 @@ } -static PyObject* -pattern_finditer(PatternObject* pattern, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.finditer + + string: object + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + +Return an iterator over all non-overlapping matches for the RE pattern in string. + +For each match, the iterator returns a match object. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos) +/*[clinic end generated code: output=0bbb1a0aeb38bb14 input=612aab69e9fe08e4]*/ { PyObject* scanner; PyObject* search; PyObject* iterator; - scanner = pattern_scanner(pattern, args, kw); + scanner = pattern_scanner(self, string, pos, endpos); if (!scanner) return NULL; @@ -841,8 +901,38 @@ return iterator; } -static PyObject* -pattern_split(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.scanner + + string: object + pos: Py_ssize_t = 0 + endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos) +/*[clinic end generated code: output=54ea548aed33890b input=3aacdbde77a3a637]*/ +{ + return pattern_scanner(self, string, pos, endpos); +} + +/*[clinic input] +_sre.SRE_Pattern.split + + string: object = NULL + maxsplit: Py_ssize_t = 0 + * + source: object = NULL + +Split string by the occurrences of pattern. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, + Py_ssize_t maxsplit, PyObject *source) +/*[clinic end generated code: output=20bac2ff55b9f84c input=41e0b2e35e599d7b]*/ { SRE_STATE state; PyObject* list; @@ -852,14 +942,7 @@ Py_ssize_t i; void* last; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t maxsplit = 0; - static char* kwlist[] = { "string", "maxsplit", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|On$O:split", kwlist, - &string, &maxsplit, &string2)) - return NULL; - - string = fix_string_param(string, string2, "source"); + string = fix_string_param(string, source, "source"); if (!string) return NULL; @@ -876,8 +959,7 @@ return NULL; } - string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX); - if (!string) + if (!state_init(&state, self, string, 0, PY_SSIZE_T_MAX)) return NULL; list = PyList_New(0); @@ -1021,8 +1103,7 @@ } } - string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX); - if (!string) { + if (!state_init(&state, self, string, 0, PY_SSIZE_T_MAX)) { Py_DECREF(filter); return NULL; } @@ -1162,36 +1243,50 @@ } -static PyObject* -pattern_sub(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.sub + + repl: object + string: object + count: Py_ssize_t = 0 + +Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, + PyObject *string, Py_ssize_t count) +/*[clinic end generated code: output=1dbf2ec3479cba00 input=c53d70be0b3caf86]*/ { - PyObject* ptemplate; - PyObject* string; - Py_ssize_t count = 0; - static char* kwlist[] = { "repl", "string", "count", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|n:sub", kwlist, - &ptemplate, &string, &count)) - return NULL; - - return pattern_subx(self, ptemplate, string, count, 0); + return pattern_subx(self, repl, string, count, 0); } -static PyObject* -pattern_subn(PatternObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Pattern.subn + + repl: object + string: object + count: Py_ssize_t = 0 + +Return the tuple (new_string, number_of_subs_made) found by replacing the leftmost non-overlapping occurrences of pattern with the replacement repl. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, + PyObject *string, Py_ssize_t count) +/*[clinic end generated code: output=0d9522cd529e9728 input=e7342d7ce6083577]*/ { - PyObject* ptemplate; - PyObject* string; - Py_ssize_t count = 0; - static char* kwlist[] = { "repl", "string", "count", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|n:subn", kwlist, - &ptemplate, &string, &count)) - return NULL; - - return pattern_subx(self, ptemplate, string, count, 1); + return pattern_subx(self, repl, string, count, 1); } -static PyObject* -pattern_copy(PatternObject* self, PyObject *unused) +/*[clinic input] +_sre.SRE_Pattern.__copy__ + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern___copy___impl(PatternObject *self) +/*[clinic end generated code: output=85dedc2db1bd8694 input=a730a59d863bc9f5]*/ { #ifdef USE_BUILTIN_COPY PatternObject* copy; @@ -1218,8 +1313,16 @@ #endif } -static PyObject* -pattern_deepcopy(PatternObject* self, PyObject* memo) +/*[clinic input] +_sre.SRE_Pattern.__deepcopy__ + + memo: object + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Pattern___deepcopy___impl(PatternObject *self, PyObject *memo) +/*[clinic end generated code: output=75efe69bd12c5d7d input=3959719482c07f70]*/ { #ifdef USE_BUILTIN_COPY PatternObject* copy; @@ -1321,68 +1424,9 @@ return result; } -PyDoc_STRVAR(pattern_match_doc, -"match(string[, pos[, endpos]]) -> match object or None.\n\ - Matches zero or more characters at the beginning of the string"); - -PyDoc_STRVAR(pattern_fullmatch_doc, -"fullmatch(string[, pos[, endpos]]) -> match object or None.\n\ - Matches against all of the string"); - -PyDoc_STRVAR(pattern_search_doc, -"search(string[, pos[, endpos]]) -> match object or None.\n\ - Scan through string looking for a match, and return a corresponding\n\ - match object instance. Return None if no position in the string matches."); - -PyDoc_STRVAR(pattern_split_doc, -"split(string[, maxsplit = 0]) -> list.\n\ - Split string by the occurrences of pattern."); - -PyDoc_STRVAR(pattern_findall_doc, -"findall(string[, pos[, endpos]]) -> list.\n\ - Return a list of all non-overlapping matches of pattern in string."); - -PyDoc_STRVAR(pattern_finditer_doc, -"finditer(string[, pos[, endpos]]) -> iterator.\n\ - Return an iterator over all non-overlapping matches for the \n\ - RE pattern in string. For each match, the iterator returns a\n\ - match object."); - -PyDoc_STRVAR(pattern_sub_doc, -"sub(repl, string[, count = 0]) -> newstring.\n\ - Return the string obtained by replacing the leftmost non-overlapping\n\ - occurrences of pattern in string by the replacement repl."); - -PyDoc_STRVAR(pattern_subn_doc, -"subn(repl, string[, count = 0]) -> (newstring, number of subs)\n\ - Return the tuple (new_string, number_of_subs_made) found by replacing\n\ - the leftmost non-overlapping occurrences of pattern with the\n\ - replacement repl."); - PyDoc_STRVAR(pattern_doc, "Compiled regular expression objects"); -static PyMethodDef pattern_methods[] = { - {"match", (PyCFunction) pattern_match, METH_VARARGS|METH_KEYWORDS, - pattern_match_doc}, - {"fullmatch", (PyCFunction) pattern_fullmatch, METH_VARARGS|METH_KEYWORDS, - pattern_fullmatch_doc}, - {"search", (PyCFunction) pattern_search, METH_VARARGS|METH_KEYWORDS, - pattern_search_doc}, - {"sub", (PyCFunction) pattern_sub, METH_VARARGS|METH_KEYWORDS, - pattern_sub_doc}, - {"subn", (PyCFunction) pattern_subn, METH_VARARGS|METH_KEYWORDS, - pattern_subn_doc}, - {"split", (PyCFunction) pattern_split, METH_VARARGS|METH_KEYWORDS, - pattern_split_doc}, - {"findall", (PyCFunction) pattern_findall, METH_VARARGS|METH_KEYWORDS, - pattern_findall_doc}, - {"finditer", (PyCFunction) pattern_finditer, METH_VARARGS|METH_KEYWORDS, - pattern_finditer_doc}, - {"scanner", (PyCFunction) pattern_scanner, METH_VARARGS|METH_KEYWORDS}, - {"__copy__", (PyCFunction) pattern_copy, METH_NOARGS}, - {"__deepcopy__", (PyCFunction) pattern_deepcopy, METH_O}, - {NULL, NULL} -}; +static PyMethodDef pattern_methods[]; /* PatternObject's 'groupindex' method. */ static PyObject * @@ -1439,26 +1483,29 @@ static int _validate(PatternObject *self); /* Forward */ +/*[clinic input] +_sre.compile + + pattern: object + flags: int + code: object(subclass_of='&PyList_Type') + groups: Py_ssize_t + groupindex: object + indexgroup: object + +[clinic start generated code]*/ + static PyObject * -_compile(PyObject* self_, PyObject* args) +_sre_compile_impl(PyModuleDef *module, PyObject *pattern, int flags, + PyObject *code, Py_ssize_t groups, PyObject *groupindex, + PyObject *indexgroup) +/*[clinic end generated code: output=3004b293730bf309 input=7d059ec8ae1edb85]*/ { /* "compile" pattern descriptor to pattern object */ PatternObject* self; Py_ssize_t i, n; - PyObject* pattern; - int flags = 0; - PyObject* code; - Py_ssize_t groups = 0; - PyObject* groupindex = NULL; - PyObject* indexgroup = NULL; - - if (!PyArg_ParseTuple(args, "OiO!nOO", &pattern, &flags, - &PyList_Type, &code, &groups, - &groupindex, &indexgroup)) - return NULL; - n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n); @@ -2071,13 +2118,22 @@ return match_getslice_by_index(self, match_getindex(self, index), def); } -static PyObject* -match_expand(MatchObject* self, PyObject* ptemplate) +/*[clinic input] +_sre.SRE_Match.expand + + template: object + +Return the string obtained by doing backslash substitution on the string template, as done by the sub() method. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match_expand_impl(MatchObject *self, PyObject *template) +/*[clinic end generated code: output=931b58ccc323c3a1 input=4bfdb22c2f8b146a]*/ { /* delegate to Python code */ return call( SRE_PY_MODULE, "_expand", - PyTuple_Pack(3, self->pattern, self, ptemplate) + PyTuple_Pack(3, self->pattern, self, template) ); } @@ -2116,24 +2172,29 @@ return result; } -static PyObject* -match_groups(MatchObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Match.groups + + default: object = None + Is used for groups that did not participate in the match. + +Return a tuple containing all the subgroups of the match, from 1. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match_groups_impl(MatchObject *self, PyObject *default_value) +/*[clinic end generated code: output=daf8e2641537238a input=bb069ef55dabca91]*/ { PyObject* result; Py_ssize_t index; - PyObject* def = Py_None; - static char* kwlist[] = { "default", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groups", kwlist, &def)) - return NULL; - result = PyTuple_New(self->groups-1); if (!result) return NULL; for (index = 1; index < self->groups; index++) { PyObject* item; - item = match_getslice_by_index(self, index, def); + item = match_getslice_by_index(self, index, default_value); if (!item) { Py_DECREF(result); return NULL; @@ -2144,18 +2205,23 @@ return result; } -static PyObject* -match_groupdict(MatchObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_sre.SRE_Match.groupdict + + default: object = None + Is used for groups that did not participate in the match. + +Return a dictionary containing all the named subgroups of the match, keyed by the subgroup name. +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match_groupdict_impl(MatchObject *self, PyObject *default_value) +/*[clinic end generated code: output=29917c9073e41757 input=0ded7960b23780aa]*/ { PyObject* result; PyObject* keys; Py_ssize_t index; - PyObject* def = Py_None; - static char* kwlist[] = { "default", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groupdict", kwlist, &def)) - return NULL; - result = PyDict_New(); if (!result || !self->pattern->groupindex) return result; @@ -2171,7 +2237,7 @@ key = PyList_GET_ITEM(keys, index); if (!key) goto failed; - value = match_getslice(self, key, def); + value = match_getslice(self, key, default_value); if (!value) { Py_DECREF(key); goto failed; @@ -2192,50 +2258,58 @@ return NULL; } -static PyObject* -match_start(MatchObject* self, PyObject* args) +/*[clinic input] +_sre.SRE_Match.start -> Py_ssize_t + + group: object(c_default="NULL") = 0 + / + +Return index of the start of the substring matched by group. +[clinic start generated code]*/ + +static Py_ssize_t +_sre_SRE_Match_start_impl(MatchObject *self, PyObject *group) +/*[clinic end generated code: output=3f6e7f9df2fb5201 input=ced8e4ed4b33ee6c]*/ { - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "start", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); + Py_ssize_t index = match_getindex(self, group); if (index < 0 || index >= self->groups) { PyErr_SetString( PyExc_IndexError, "no such group" ); - return NULL; + return -1; } /* mark is -1 if group is undefined */ - return PyLong_FromSsize_t(self->mark[index*2]); + return self->mark[index*2]; } -static PyObject* -match_end(MatchObject* self, PyObject* args) +/*[clinic input] +_sre.SRE_Match.end -> Py_ssize_t + + group: object(c_default="NULL") = 0 + / + +Return index of the end of the substring matched by group. +[clinic start generated code]*/ + +static Py_ssize_t +_sre_SRE_Match_end_impl(MatchObject *self, PyObject *group) +/*[clinic end generated code: output=f4240b09911f7692 input=1b799560c7f3d7e6]*/ { - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "end", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); + Py_ssize_t index = match_getindex(self, group); if (index < 0 || index >= self->groups) { PyErr_SetString( PyExc_IndexError, "no such group" ); - return NULL; + return -1; } /* mark is -1 if group is undefined */ - return PyLong_FromSsize_t(self->mark[index*2+1]); + return self->mark[index*2+1]; } LOCAL(PyObject*) @@ -2265,16 +2339,20 @@ return NULL; } -static PyObject* -match_span(MatchObject* self, PyObject* args) +/*[clinic input] +_sre.SRE_Match.span + + group: object(c_default="NULL") = 0 + / + +For MatchObject m, return the 2-tuple (m.start(group), m.end(group)). +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match_span_impl(MatchObject *self, PyObject *group) +/*[clinic end generated code: output=f02ae40594d14fe6 input=49092b6008d176d3]*/ { - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "span", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); + Py_ssize_t index = match_getindex(self, group); if (index < 0 || index >= self->groups) { PyErr_SetString( @@ -2314,8 +2392,14 @@ return regs; } -static PyObject* -match_copy(MatchObject* self, PyObject *unused) +/*[clinic input] +_sre.SRE_Match.__copy__ + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match___copy___impl(MatchObject *self) +/*[clinic end generated code: output=a779c5fc8b5b4eb4 input=3bb4d30b6baddb5b]*/ { #ifdef USE_BUILTIN_COPY MatchObject* copy; @@ -2345,8 +2429,16 @@ #endif } -static PyObject* -match_deepcopy(MatchObject* self, PyObject* memo) +/*[clinic input] +_sre.SRE_Match.__deepcopy__ + + memo: object + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Match___deepcopy___impl(MatchObject *self, PyObject *memo) +/*[clinic end generated code: output=2b657578eb03f4a3 input=b65b72489eac64cc]*/ { #ifdef USE_BUILTIN_COPY MatchObject* copy; @@ -2377,49 +2469,7 @@ Return subgroup(s) of the match by indices or names.\n\ For 0 returns the entire match."); -PyDoc_STRVAR(match_start_doc, -"start([group=0]) -> int.\n\ - Return index of the start of the substring matched by group."); - -PyDoc_STRVAR(match_end_doc, -"end([group=0]) -> int.\n\ - Return index of the end of the substring matched by group."); - -PyDoc_STRVAR(match_span_doc, -"span([group]) -> tuple.\n\ - For MatchObject m, return the 2-tuple (m.start(group), m.end(group))."); - -PyDoc_STRVAR(match_groups_doc, -"groups([default=None]) -> tuple.\n\ - Return a tuple containing all the subgroups of the match, from 1.\n\ - The default argument is used for groups\n\ - that did not participate in the match"); - -PyDoc_STRVAR(match_groupdict_doc, -"groupdict([default=None]) -> dict.\n\ - Return a dictionary containing all the named subgroups of the match,\n\ - keyed by the subgroup name. The default argument is used for groups\n\ - that did not participate in the match"); - -PyDoc_STRVAR(match_expand_doc, -"expand(template) -> str.\n\ - Return the string obtained by doing backslash substitution\n\ - on the string template, as done by the sub() method."); - -static PyMethodDef match_methods[] = { - {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc}, - {"start", (PyCFunction) match_start, METH_VARARGS, match_start_doc}, - {"end", (PyCFunction) match_end, METH_VARARGS, match_end_doc}, - {"span", (PyCFunction) match_span, METH_VARARGS, match_span_doc}, - {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS, - match_groups_doc}, - {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS, - match_groupdict_doc}, - {"expand", (PyCFunction) match_expand, METH_O, match_expand_doc}, - {"__copy__", (PyCFunction) match_copy, METH_NOARGS}, - {"__deepcopy__", (PyCFunction) match_deepcopy, METH_O}, - {NULL, NULL} -}; +static PyMethodDef match_methods[]; static PyObject * match_lastindex_get(MatchObject *self) @@ -2597,8 +2647,14 @@ PyObject_DEL(self); } -static PyObject* -scanner_match(ScannerObject* self, PyObject *unused) +/*[clinic input] +_sre.SRE_Scanner.match + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Scanner_match_impl(ScannerObject *self) +/*[clinic end generated code: output=936b30c63d4b81eb input=881a0154f8c13d9a]*/ { SRE_STATE* state = &self->state; PyObject* match; @@ -2624,8 +2680,14 @@ } -static PyObject* -scanner_search(ScannerObject* self, PyObject *unused) +/*[clinic input] +_sre.SRE_Scanner.search + +[clinic start generated code]*/ + +static PyObject * +_sre_SRE_Scanner_search_impl(ScannerObject *self) +/*[clinic end generated code: output=7dc211986088f025 input=161223ee92ef9270]*/ { SRE_STATE* state = &self->state; PyObject* match; @@ -2650,11 +2712,7 @@ return match; } -static PyMethodDef scanner_methods[] = { - {"match", (PyCFunction) scanner_match, METH_NOARGS}, - {"search", (PyCFunction) scanner_search, METH_NOARGS}, - {NULL, NULL} -}; +static PyMethodDef scanner_methods[]; #define SCAN_OFF(x) offsetof(ScannerObject, x) static PyMemberDef scanner_members[] = { @@ -2694,47 +2752,69 @@ 0, /* tp_getset */ }; -static PyObject* -pattern_scanner(PatternObject* pattern, PyObject* args, PyObject* kw) +static PyObject * +pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos) { + ScannerObject* scanner; + + /* create scanner object */ + scanner = PyObject_NEW(ScannerObject, &Scanner_Type); + if (!scanner) + return NULL; + scanner->pattern = NULL; + /* create search state object */ - - ScannerObject* self; - - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:scanner", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "source"); - if (!string) - return NULL; - - /* create scanner object */ - self = PyObject_NEW(ScannerObject, &Scanner_Type); - if (!self) - return NULL; - self->pattern = NULL; - - string = state_init(&self->state, pattern, string, start, end); - if (!string) { - Py_DECREF(self); + if (!state_init(&scanner->state, self, string, pos, endpos)) { + Py_DECREF(scanner); return NULL; } - Py_INCREF(pattern); - self->pattern = (PyObject*) pattern; - - return (PyObject*) self; + Py_INCREF(self); + scanner->pattern = (PyObject*) self; + + return (PyObject*) scanner; } +#include "clinic/_sre.c.h" + +static PyMethodDef pattern_methods[] = { + _SRE_SRE_PATTERN_MATCH_METHODDEF + _SRE_SRE_PATTERN_FULLMATCH_METHODDEF + _SRE_SRE_PATTERN_SEARCH_METHODDEF + _SRE_SRE_PATTERN_SUB_METHODDEF + _SRE_SRE_PATTERN_SUBN_METHODDEF + _SRE_SRE_PATTERN_FINDALL_METHODDEF + _SRE_SRE_PATTERN_SPLIT_METHODDEF + _SRE_SRE_PATTERN_FINDITER_METHODDEF + _SRE_SRE_PATTERN_SCANNER_METHODDEF + _SRE_SRE_PATTERN___COPY___METHODDEF + _SRE_SRE_PATTERN___DEEPCOPY___METHODDEF + {NULL, NULL} +}; + +static PyMethodDef match_methods[] = { + {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc}, + _SRE_SRE_MATCH_START_METHODDEF + _SRE_SRE_MATCH_END_METHODDEF + _SRE_SRE_MATCH_SPAN_METHODDEF + _SRE_SRE_MATCH_GROUPS_METHODDEF + _SRE_SRE_MATCH_GROUPDICT_METHODDEF + _SRE_SRE_MATCH_EXPAND_METHODDEF + _SRE_SRE_MATCH___COPY___METHODDEF + _SRE_SRE_MATCH___DEEPCOPY___METHODDEF + {NULL, NULL} +}; + +static PyMethodDef scanner_methods[] = { + _SRE_SRE_SCANNER_MATCH_METHODDEF + _SRE_SRE_SCANNER_SEARCH_METHODDEF + {NULL, NULL} +}; + static PyMethodDef _functions[] = { - {"compile", _compile, METH_VARARGS}, - {"getcodesize", sre_codesize, METH_NOARGS}, - {"getlower", sre_getlower, METH_VARARGS}, + _SRE_COMPILE_METHODDEF + _SRE_GETCODESIZE_METHODDEF + _SRE_GETLOWER_METHODDEF {NULL, NULL} }; diff --git a/Modules/_sre.c b/Modules/clinic/_sre.c.h copy from Modules/_sre.c copy to Modules/clinic/_sre.c.h --- a/Modules/_sre.c +++ b/Modules/clinic/_sre.c.h @@ -1,2802 +1,693 @@ -/* - * Secret Labs' Regular Expression Engine - * - * regular expression matching engine - * - * partial history: - * 1999-10-24 fl created (based on existing template matcher code) - * 2000-03-06 fl first alpha, sort of - * 2000-08-01 fl fixes for 1.6b1 - * 2000-08-07 fl use PyOS_CheckStack() if available - * 2000-09-20 fl added expand method - * 2001-03-20 fl lots of fixes for 2.1b2 - * 2001-04-15 fl export copyright as Python attribute, not global - * 2001-04-28 fl added __copy__ methods (work in progress) - * 2001-05-14 fl fixes for 1.5.2 compatibility - * 2001-07-01 fl added BIGCHARSET support (from Martin von Loewis) - * 2001-10-18 fl fixed group reset issue (from Matthew Mueller) - * 2001-10-20 fl added split primitive; reenable unicode for 1.6/2.0/2.1 - * 2001-10-21 fl added sub/subn primitive - * 2001-10-24 fl added finditer primitive (for 2.2 only) - * 2001-12-07 fl fixed memory leak in sub/subn (Guido van Rossum) - * 2002-11-09 fl fixed empty sub/subn return type - * 2003-04-18 mvl fully support 4-byte codes - * 2003-10-17 gn implemented non recursive scheme - * 2013-02-04 mrab added fullmatch primitive - * - * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. - * - * This version of the SRE library can be redistributed under CNRI's - * Python 1.6 license. For any other use, please contact Secret Labs - * AB (info at pythonware.com). - * - * Portions of this engine have been developed in cooperation with - * CNRI. Hewlett-Packard provided funding for 1.6 integration and - * other compatibility work. - */ +/*[clinic input] +preserve +[clinic start generated code]*/ -static char copyright[] = - " SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB "; +PyDoc_STRVAR(_sre_getcodesize__doc__, +"getcodesize($module, /)\n" +"--\n" +"\n"); -#define PY_SSIZE_T_CLEAN +#define _SRE_GETCODESIZE_METHODDEF \ + {"getcodesize", (PyCFunction)_sre_getcodesize, METH_NOARGS, _sre_getcodesize__doc__}, -#include "Python.h" -#include "structmember.h" /* offsetof */ +static int +_sre_getcodesize_impl(PyModuleDef *module); -#include "sre.h" +static PyObject * +_sre_getcodesize(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; -#define SRE_CODE_BITS (8 * sizeof(SRE_CODE)) + _return_value = _sre_getcodesize_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); -#include - -/* name of this module, minus the leading underscore */ -#if !defined(SRE_MODULE) -#define SRE_MODULE "sre" -#endif - -#define SRE_PY_MODULE "re" - -/* defining this one enables tracing */ -#undef VERBOSE - -/* -------------------------------------------------------------------- */ -/* optional features */ - -/* enables fast searching */ -#define USE_FAST_SEARCH - -/* enables copy/deepcopy handling (work in progress) */ -#undef USE_BUILTIN_COPY - -/* -------------------------------------------------------------------- */ - -#if defined(_MSC_VER) -#pragma optimize("agtw", on) /* doesn't seem to make much difference... */ -#pragma warning(disable: 4710) /* who cares if functions are not inlined ;-) */ -/* fastest possible local call under MSVC */ -#define LOCAL(type) static __inline type __fastcall -#elif defined(USE_INLINE) -#define LOCAL(type) static inline type -#else -#define LOCAL(type) static type -#endif - -/* error codes */ -#define SRE_ERROR_ILLEGAL -1 /* illegal opcode */ -#define SRE_ERROR_STATE -2 /* illegal state */ -#define SRE_ERROR_RECURSION_LIMIT -3 /* runaway recursion */ -#define SRE_ERROR_MEMORY -9 /* out of memory */ -#define SRE_ERROR_INTERRUPTED -10 /* signal handler raised exception */ - -#if defined(VERBOSE) -#define TRACE(v) printf v -#else -#define TRACE(v) -#endif - -/* -------------------------------------------------------------------- */ -/* search engine state */ - -#define SRE_IS_DIGIT(ch)\ - ((ch) < 128 && Py_ISDIGIT(ch)) -#define SRE_IS_SPACE(ch)\ - ((ch) < 128 && Py_ISSPACE(ch)) -#define SRE_IS_LINEBREAK(ch)\ - ((ch) == '\n') -#define SRE_IS_ALNUM(ch)\ - ((ch) < 128 && Py_ISALNUM(ch)) -#define SRE_IS_WORD(ch)\ - ((ch) < 128 && (Py_ISALNUM(ch) || (ch) == '_')) - -static unsigned int sre_lower(unsigned int ch) -{ - return ((ch) < 128 ? Py_TOLOWER(ch) : ch); +exit: + return return_value; } -static unsigned int sre_upper(unsigned int ch) +PyDoc_STRVAR(_sre_getlower__doc__, +"getlower($module, character, flags, /)\n" +"--\n" +"\n"); + +#define _SRE_GETLOWER_METHODDEF \ + {"getlower", (PyCFunction)_sre_getlower, METH_VARARGS, _sre_getlower__doc__}, + +static int +_sre_getlower_impl(PyModuleDef *module, int character, int flags); + +static PyObject * +_sre_getlower(PyModuleDef *module, PyObject *args) { - return ((ch) < 128 ? Py_TOUPPER(ch) : ch); + PyObject *return_value = NULL; + int character; + int flags; + int _return_value; + + if (!PyArg_ParseTuple(args, "ii:getlower", + &character, &flags)) + goto exit; + _return_value = _sre_getlower_impl(module, character, flags); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; } -/* locale-specific character predicates */ -/* !(c & ~N) == (c < N+1) for any unsigned c, this avoids - * warnings when c's type supports only numbers < N+1 */ -#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? isalnum((ch)) : 0) -#define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_') +PyDoc_STRVAR(_sre_SRE_Pattern_match__doc__, +"match($self, /, string=None, pos=0, endpos=sys.maxsize, *, pattern=None)\n" +"--\n" +"\n" +"Matches zero or more characters at the beginning of the string."); -static unsigned int sre_lower_locale(unsigned int ch) -{ - return ((ch) < 256 ? (unsigned int)tolower((ch)) : ch); -} - -static unsigned int sre_upper_locale(unsigned int ch) -{ - return ((ch) < 256 ? (unsigned int)toupper((ch)) : ch); -} - -/* unicode-specific character predicates */ - -#define SRE_UNI_IS_DIGIT(ch) Py_UNICODE_ISDECIMAL(ch) -#define SRE_UNI_IS_SPACE(ch) Py_UNICODE_ISSPACE(ch) -#define SRE_UNI_IS_LINEBREAK(ch) Py_UNICODE_ISLINEBREAK(ch) -#define SRE_UNI_IS_ALNUM(ch) Py_UNICODE_ISALNUM(ch) -#define SRE_UNI_IS_WORD(ch) (SRE_UNI_IS_ALNUM(ch) || (ch) == '_') - -static unsigned int sre_lower_unicode(unsigned int ch) -{ - return (unsigned int) Py_UNICODE_TOLOWER(ch); -} - -static unsigned int sre_upper_unicode(unsigned int ch) -{ - return (unsigned int) Py_UNICODE_TOUPPER(ch); -} - -LOCAL(int) -sre_category(SRE_CODE category, unsigned int ch) -{ - switch (category) { - - case SRE_CATEGORY_DIGIT: - return SRE_IS_DIGIT(ch); - case SRE_CATEGORY_NOT_DIGIT: - return !SRE_IS_DIGIT(ch); - case SRE_CATEGORY_SPACE: - return SRE_IS_SPACE(ch); - case SRE_CATEGORY_NOT_SPACE: - return !SRE_IS_SPACE(ch); - case SRE_CATEGORY_WORD: - return SRE_IS_WORD(ch); - case SRE_CATEGORY_NOT_WORD: - return !SRE_IS_WORD(ch); - case SRE_CATEGORY_LINEBREAK: - return SRE_IS_LINEBREAK(ch); - case SRE_CATEGORY_NOT_LINEBREAK: - return !SRE_IS_LINEBREAK(ch); - - case SRE_CATEGORY_LOC_WORD: - return SRE_LOC_IS_WORD(ch); - case SRE_CATEGORY_LOC_NOT_WORD: - return !SRE_LOC_IS_WORD(ch); - - case SRE_CATEGORY_UNI_DIGIT: - return SRE_UNI_IS_DIGIT(ch); - case SRE_CATEGORY_UNI_NOT_DIGIT: - return !SRE_UNI_IS_DIGIT(ch); - case SRE_CATEGORY_UNI_SPACE: - return SRE_UNI_IS_SPACE(ch); - case SRE_CATEGORY_UNI_NOT_SPACE: - return !SRE_UNI_IS_SPACE(ch); - case SRE_CATEGORY_UNI_WORD: - return SRE_UNI_IS_WORD(ch); - case SRE_CATEGORY_UNI_NOT_WORD: - return !SRE_UNI_IS_WORD(ch); - case SRE_CATEGORY_UNI_LINEBREAK: - return SRE_UNI_IS_LINEBREAK(ch); - case SRE_CATEGORY_UNI_NOT_LINEBREAK: - return !SRE_UNI_IS_LINEBREAK(ch); - } - return 0; -} - -/* helpers */ - -static void -data_stack_dealloc(SRE_STATE* state) -{ - if (state->data_stack) { - PyMem_FREE(state->data_stack); - state->data_stack = NULL; - } - state->data_stack_size = state->data_stack_base = 0; -} - -static int -data_stack_grow(SRE_STATE* state, Py_ssize_t size) -{ - Py_ssize_t minsize, cursize; - minsize = state->data_stack_base+size; - cursize = state->data_stack_size; - if (cursize < minsize) { - void* stack; - cursize = minsize+minsize/4+1024; - TRACE(("allocate/grow stack %" PY_FORMAT_SIZE_T "d\n", cursize)); - stack = PyMem_REALLOC(state->data_stack, cursize); - if (!stack) { - data_stack_dealloc(state); - return SRE_ERROR_MEMORY; - } - state->data_stack = (char *)stack; - state->data_stack_size = cursize; - } - return 0; -} - -/* generate 8-bit version */ - -#define SRE_CHAR Py_UCS1 -#define SIZEOF_SRE_CHAR 1 -#define SRE(F) sre_ucs1_##F -#include "sre_lib.h" - -/* generate 16-bit unicode version */ - -#define SRE_CHAR Py_UCS2 -#define SIZEOF_SRE_CHAR 2 -#define SRE(F) sre_ucs2_##F -#include "sre_lib.h" - -/* generate 32-bit unicode version */ - -#define SRE_CHAR Py_UCS4 -#define SIZEOF_SRE_CHAR 4 -#define SRE(F) sre_ucs4_##F -#include "sre_lib.h" - -/* -------------------------------------------------------------------- */ -/* factories and destructors */ - -/* see sre.h for object declarations */ -static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject*pattern_scanner(PatternObject*, PyObject*, PyObject* kw); +#define _SRE_SRE_PATTERN_MATCH_METHODDEF \ + {"match", (PyCFunction)_sre_SRE_Pattern_match, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, static PyObject * -sre_codesize(PyObject* self, PyObject *unused) -{ - return PyLong_FromSize_t(sizeof(SRE_CODE)); -} +_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern); static PyObject * -sre_getlower(PyObject* self, PyObject* args) +_sre_SRE_Pattern_match(PatternObject *self, PyObject *args, PyObject *kwargs) { - int character, flags; - if (!PyArg_ParseTuple(args, "ii", &character, &flags)) - return NULL; - if (flags & SRE_FLAG_LOCALE) - return Py_BuildValue("i", sre_lower_locale(character)); - if (flags & SRE_FLAG_UNICODE) - return Py_BuildValue("i", sre_lower_unicode(character)); - return Py_BuildValue("i", sre_lower(character)); -} - -LOCAL(void) -state_reset(SRE_STATE* state) -{ - /* FIXME: dynamic! */ - /*memset(state->mark, 0, sizeof(*state->mark) * SRE_MARK_SIZE);*/ - - state->lastmark = -1; - state->lastindex = -1; - - state->repeat = NULL; - - data_stack_dealloc(state); -} - -static void* -getstring(PyObject* string, Py_ssize_t* p_length, - int* p_isbytes, int* p_charsize, - Py_buffer *view) -{ - /* given a python object, return a data pointer, a length (in - characters), and a character size. return NULL if the object - is not a string (or not compatible) */ - - /* Unicode objects do not support the buffer API. So, get the data - directly instead. */ - if (PyUnicode_Check(string)) { - if (PyUnicode_READY(string) == -1) - return NULL; - *p_length = PyUnicode_GET_LENGTH(string); - *p_charsize = PyUnicode_KIND(string); - *p_isbytes = 0; - return PyUnicode_DATA(string); - } - - /* get pointer to byte string buffer */ - if (PyObject_GetBuffer(string, view, PyBUF_SIMPLE) != 0) { - PyErr_SetString(PyExc_TypeError, "expected string or bytes-like object"); - return NULL; - } - - *p_length = view->len; - *p_charsize = 1; - *p_isbytes = 1; - - if (view->buf == NULL) { - PyErr_SetString(PyExc_ValueError, "Buffer is NULL"); - PyBuffer_Release(view); - view->buf = NULL; - return NULL; - } - return view->buf; -} - -LOCAL(PyObject*) -state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string, - Py_ssize_t start, Py_ssize_t end) -{ - /* prepare state object */ - - Py_ssize_t length; - int isbytes, charsize; - void* ptr; - - memset(state, 0, sizeof(SRE_STATE)); - - state->mark = PyMem_New(void *, pattern->groups * 2); - if (!state->mark) { - PyErr_NoMemory(); - goto err; - } - state->lastmark = -1; - state->lastindex = -1; - - state->buffer.buf = NULL; - ptr = getstring(string, &length, &isbytes, &charsize, &state->buffer); - if (!ptr) - goto err; - - if (isbytes && pattern->isbytes == 0) { - PyErr_SetString(PyExc_TypeError, - "cannot use a string pattern on a bytes-like object"); - goto err; - } - if (!isbytes && pattern->isbytes > 0) { - PyErr_SetString(PyExc_TypeError, - "cannot use a bytes pattern on a string-like object"); - goto err; - } - - /* adjust boundaries */ - if (start < 0) - start = 0; - else if (start > length) - start = length; - - if (end < 0) - end = 0; - else if (end > length) - end = length; - - state->isbytes = isbytes; - state->charsize = charsize; - - state->beginning = ptr; - - state->start = (void*) ((char*) ptr + start * state->charsize); - state->end = (void*) ((char*) ptr + end * state->charsize); - - Py_INCREF(string); - state->string = string; - state->pos = start; - state->endpos = end; - - if (pattern->flags & SRE_FLAG_LOCALE) { - state->lower = sre_lower_locale; - state->upper = sre_upper_locale; - } - else if (pattern->flags & SRE_FLAG_UNICODE) { - state->lower = sre_lower_unicode; - state->upper = sre_upper_unicode; - } - else { - state->lower = sre_lower; - state->upper = sre_upper; - } - - return string; - err: - PyMem_Del(state->mark); - state->mark = NULL; - if (state->buffer.buf) - PyBuffer_Release(&state->buffer); - return NULL; -} - -LOCAL(void) -state_fini(SRE_STATE* state) -{ - if (state->buffer.buf) - PyBuffer_Release(&state->buffer); - Py_XDECREF(state->string); - data_stack_dealloc(state); - PyMem_Del(state->mark); - state->mark = NULL; -} - -/* calculate offset from start of string */ -#define STATE_OFFSET(state, member)\ - (((char*)(member) - (char*)(state)->beginning) / (state)->charsize) - -LOCAL(PyObject*) -getslice(int isbytes, const void *ptr, - PyObject* string, Py_ssize_t start, Py_ssize_t end) -{ - if (isbytes) { - if (PyBytes_CheckExact(string) && - start == 0 && end == PyBytes_GET_SIZE(string)) { - Py_INCREF(string); - return string; - } - return PyBytes_FromStringAndSize( - (const char *)ptr + start, end - start); - } - else { - return PyUnicode_Substring(string, start, end); - } -} - -LOCAL(PyObject*) -state_getslice(SRE_STATE* state, Py_ssize_t index, PyObject* string, int empty) -{ - Py_ssize_t i, j; - - index = (index - 1) * 2; - - if (string == Py_None || index >= state->lastmark || !state->mark[index] || !state->mark[index+1]) { - if (empty) - /* want empty string */ - i = j = 0; - else { - Py_INCREF(Py_None); - return Py_None; - } - } else { - i = STATE_OFFSET(state, state->mark[index]); - j = STATE_OFFSET(state, state->mark[index+1]); - } - - return getslice(state->isbytes, state->beginning, string, i, j); -} - -static void -pattern_error(Py_ssize_t status) -{ - switch (status) { - case SRE_ERROR_RECURSION_LIMIT: - PyErr_SetString( - PyExc_RuntimeError, - "maximum recursion limit exceeded" - ); - break; - case SRE_ERROR_MEMORY: - PyErr_NoMemory(); - break; - case SRE_ERROR_INTERRUPTED: - /* An exception has already been raised, so let it fly */ - break; - default: - /* other error codes indicate compiler/engine bugs */ - PyErr_SetString( - PyExc_RuntimeError, - "internal error in regular expression engine" - ); - } -} - -static void -pattern_dealloc(PatternObject* self) -{ - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_XDECREF(self->pattern); - Py_XDECREF(self->groupindex); - Py_XDECREF(self->indexgroup); - PyObject_DEL(self); -} - -LOCAL(Py_ssize_t) -sre_match(SRE_STATE* state, SRE_CODE* pattern, int match_all) -{ - if (state->charsize == 1) - return sre_ucs1_match(state, pattern, match_all); - if (state->charsize == 2) - return sre_ucs2_match(state, pattern, match_all); - assert(state->charsize == 4); - return sre_ucs4_match(state, pattern, match_all); -} - -LOCAL(Py_ssize_t) -sre_search(SRE_STATE* state, SRE_CODE* pattern) -{ - if (state->charsize == 1) - return sre_ucs1_search(state, pattern); - if (state->charsize == 2) - return sre_ucs2_search(state, pattern); - assert(state->charsize == 4); - return sre_ucs4_search(state, pattern); -} - -static PyObject * -fix_string_param(PyObject *string, PyObject *string2, const char *oldname) -{ - if (string2 != NULL) { - if (string != NULL) { - PyErr_Format(PyExc_TypeError, - "Argument given by name ('%s') and position (1)", - oldname); - return NULL; - } - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "The '%s' keyword parameter name is deprecated. " - "Use 'string' instead.", oldname) < 0) - return NULL; - return string2; - } - if (string == NULL) { - PyErr_SetString(PyExc_TypeError, - "Required argument 'string' (pos 1) not found"); - return NULL; - } - return string; -} - -static PyObject * -pattern_match(PatternObject *self, PyObject *args, PyObject *kwargs) -{ + PyObject *return_value = NULL; static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL}; PyObject *string = NULL; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; PyObject *pattern = NULL; - SRE_STATE state; - Py_ssize_t status; - PyObject *match; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|Onn$O:match", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:match", _keywords, &string, &pos, &endpos, &pattern)) - return NULL; - string = fix_string_param(string, pattern, "pattern"); - if (!string) - return NULL; - string = state_init(&state, (PatternObject *)self, string, pos, endpos); - if (!string) - return NULL; + goto exit; + return_value = _sre_SRE_Pattern_match_impl(self, string, pos, endpos, pattern); - state.ptr = state.start; - - TRACE(("|%p|%p|MATCH\n", PatternObject_GetCode(self), state.ptr)); - - status = sre_match(&state, PatternObject_GetCode(self), 0); - - TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr)); - if (PyErr_Occurred()) { - state_fini(&state); - return NULL; - } - - match = pattern_new_match(self, &state, status); - state_fini(&state); - return match; +exit: + return return_value; } -static PyObject* -pattern_fullmatch(PatternObject* self, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern_fullmatch__doc__, +"fullmatch($self, /, string=None, pos=0, endpos=sys.maxsize, *,\n" +" pattern=None)\n" +"--\n" +"\n" +"Matches against all of the string"); + +#define _SRE_SRE_PATTERN_FULLMATCH_METHODDEF \ + {"fullmatch", (PyCFunction)_sre_SRE_Pattern_fullmatch, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_fullmatch__doc__}, + +static PyObject * +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern); + +static PyObject * +_sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject *args, PyObject *kwargs) { - SRE_STATE state; - Py_ssize_t status; - PyObject *match; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL}; + PyObject *string = NULL; + Py_ssize_t pos = 0; + Py_ssize_t endpos = PY_SSIZE_T_MAX; + PyObject *pattern = NULL; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "pattern", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:fullmatch", kwlist, - &string, &start, &end, &string2)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:fullmatch", _keywords, + &string, &pos, &endpos, &pattern)) + goto exit; + return_value = _sre_SRE_Pattern_fullmatch_impl(self, string, pos, endpos, pattern); - string = fix_string_param(string, string2, "pattern"); - if (!string) - return NULL; - - string = state_init(&state, self, string, start, end); - if (!string) - return NULL; - - state.ptr = state.start; - - TRACE(("|%p|%p|FULLMATCH\n", PatternObject_GetCode(self), state.ptr)); - - status = sre_match(&state, PatternObject_GetCode(self), 1); - - TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr)); - if (PyErr_Occurred()) { - state_fini(&state); - return NULL; - } - - match = pattern_new_match(self, &state, status); - state_fini(&state); - return match; +exit: + return return_value; } -static PyObject* -pattern_search(PatternObject* self, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern_search__doc__, +"search($self, /, string=None, pos=0, endpos=sys.maxsize, *,\n" +" pattern=None)\n" +"--\n" +"\n" +"Scan through string looking for a match, and return a corresponding match object instance.\n" +"\n" +"Return None if no position in the string matches."); + +#define _SRE_SRE_PATTERN_SEARCH_METHODDEF \ + {"search", (PyCFunction)_sre_SRE_Pattern_search, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_search__doc__}, + +static PyObject * +_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *pattern); + +static PyObject * +_sre_SRE_Pattern_search(PatternObject *self, PyObject *args, PyObject *kwargs) { - SRE_STATE state; - Py_ssize_t status; - PyObject *match; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL}; + PyObject *string = NULL; + Py_ssize_t pos = 0; + Py_ssize_t endpos = PY_SSIZE_T_MAX; + PyObject *pattern = NULL; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "pattern", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:search", kwlist, - &string, &start, &end, &string2)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:search", _keywords, + &string, &pos, &endpos, &pattern)) + goto exit; + return_value = _sre_SRE_Pattern_search_impl(self, string, pos, endpos, pattern); - string = fix_string_param(string, string2, "pattern"); - if (!string) - return NULL; - - string = state_init(&state, self, string, start, end); - if (!string) - return NULL; - - TRACE(("|%p|%p|SEARCH\n", PatternObject_GetCode(self), state.ptr)); - - status = sre_search(&state, PatternObject_GetCode(self)); - - TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr)); - - if (PyErr_Occurred()) { - state_fini(&state); - return NULL; - } - - match = pattern_new_match(self, &state, status); - state_fini(&state); - return match; +exit: + return return_value; } -static PyObject* -call(char* module, char* function, PyObject* args) +PyDoc_STRVAR(_sre_SRE_Pattern_findall__doc__, +"findall($self, /, string=None, pos=0, endpos=sys.maxsize, *,\n" +" source=None)\n" +"--\n" +"\n" +"Return a list of all non-overlapping matches of pattern in string."); + +#define _SRE_SRE_PATTERN_FINDALL_METHODDEF \ + {"findall", (PyCFunction)_sre_SRE_Pattern_findall, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_findall__doc__}, + +static PyObject * +_sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos, + PyObject *source); + +static PyObject * +_sre_SRE_Pattern_findall(PatternObject *self, PyObject *args, PyObject *kwargs) { - PyObject* name; - PyObject* mod; - PyObject* func; - PyObject* result; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "pos", "endpos", "source", NULL}; + PyObject *string = NULL; + Py_ssize_t pos = 0; + Py_ssize_t endpos = PY_SSIZE_T_MAX; + PyObject *source = NULL; - if (!args) - return NULL; - name = PyUnicode_FromString(module); - if (!name) - return NULL; - mod = PyImport_Import(name); - Py_DECREF(name); - if (!mod) - return NULL; - func = PyObject_GetAttrString(mod, function); - Py_DECREF(mod); - if (!func) - return NULL; - result = PyObject_CallObject(func, args); - Py_DECREF(func); - Py_DECREF(args); - return result; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:findall", _keywords, + &string, &pos, &endpos, &source)) + goto exit; + return_value = _sre_SRE_Pattern_findall_impl(self, string, pos, endpos, source); + +exit: + return return_value; } -#ifdef USE_BUILTIN_COPY -static int -deepcopy(PyObject** object, PyObject* memo) +PyDoc_STRVAR(_sre_SRE_Pattern_finditer__doc__, +"finditer($self, /, string, pos=0, endpos=sys.maxsize)\n" +"--\n" +"\n" +"Return an iterator over all non-overlapping matches for the RE pattern in string.\n" +"\n" +"For each match, the iterator returns a match object."); + +#define _SRE_SRE_PATTERN_FINDITER_METHODDEF \ + {"finditer", (PyCFunction)_sre_SRE_Pattern_finditer, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_finditer__doc__}, + +static PyObject * +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos); + +static PyObject * +_sre_SRE_Pattern_finditer(PatternObject *self, PyObject *args, PyObject *kwargs) { - PyObject* copy; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "pos", "endpos", NULL}; + PyObject *string; + Py_ssize_t pos = 0; + Py_ssize_t endpos = PY_SSIZE_T_MAX; - copy = call( - "copy", "deepcopy", - PyTuple_Pack(2, *object, memo) - ); - if (!copy) - return 0; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nn:finditer", _keywords, + &string, &pos, &endpos)) + goto exit; + return_value = _sre_SRE_Pattern_finditer_impl(self, string, pos, endpos); - Py_DECREF(*object); - *object = copy; - - return 1; /* success */ -} -#endif - -static PyObject* -pattern_findall(PatternObject* self, PyObject* args, PyObject* kw) -{ - SRE_STATE state; - PyObject* list; - Py_ssize_t status; - Py_ssize_t i, b, e; - - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:findall", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "source"); - if (!string) - return NULL; - - string = state_init(&state, self, string, start, end); - if (!string) - return NULL; - - list = PyList_New(0); - if (!list) { - state_fini(&state); - return NULL; - } - - while (state.start <= state.end) { - - PyObject* item; - - state_reset(&state); - - state.ptr = state.start; - - status = sre_search(&state, PatternObject_GetCode(self)); - if (PyErr_Occurred()) - goto error; - - if (status <= 0) { - if (status == 0) - break; - pattern_error(status); - goto error; - } - - /* don't bother to build a match object */ - switch (self->groups) { - case 0: - b = STATE_OFFSET(&state, state.start); - e = STATE_OFFSET(&state, state.ptr); - item = getslice(state.isbytes, state.beginning, - string, b, e); - if (!item) - goto error; - break; - case 1: - item = state_getslice(&state, 1, string, 1); - if (!item) - goto error; - break; - default: - item = PyTuple_New(self->groups); - if (!item) - goto error; - for (i = 0; i < self->groups; i++) { - PyObject* o = state_getslice(&state, i+1, string, 1); - if (!o) { - Py_DECREF(item); - goto error; - } - PyTuple_SET_ITEM(item, i, o); - } - break; - } - - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - - if (state.ptr == state.start) - state.start = (void*) ((char*) state.ptr + state.charsize); - else - state.start = state.ptr; - - } - - state_fini(&state); - return list; - -error: - Py_DECREF(list); - state_fini(&state); - return NULL; - +exit: + return return_value; } -static PyObject* -pattern_finditer(PatternObject* pattern, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern_scanner__doc__, +"scanner($self, /, string, pos=0, endpos=sys.maxsize)\n" +"--\n" +"\n"); + +#define _SRE_SRE_PATTERN_SCANNER_METHODDEF \ + {"scanner", (PyCFunction)_sre_SRE_Pattern_scanner, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_scanner__doc__}, + +static PyObject * +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, + Py_ssize_t pos, Py_ssize_t endpos); + +static PyObject * +_sre_SRE_Pattern_scanner(PatternObject *self, PyObject *args, PyObject *kwargs) { - PyObject* scanner; - PyObject* search; - PyObject* iterator; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "pos", "endpos", NULL}; + PyObject *string; + Py_ssize_t pos = 0; + Py_ssize_t endpos = PY_SSIZE_T_MAX; - scanner = pattern_scanner(pattern, args, kw); - if (!scanner) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nn:scanner", _keywords, + &string, &pos, &endpos)) + goto exit; + return_value = _sre_SRE_Pattern_scanner_impl(self, string, pos, endpos); - search = PyObject_GetAttrString(scanner, "search"); - Py_DECREF(scanner); - if (!search) - return NULL; - - iterator = PyCallIter_New(search, Py_None); - Py_DECREF(search); - - return iterator; +exit: + return return_value; } -static PyObject* -pattern_split(PatternObject* self, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern_split__doc__, +"split($self, /, string=None, maxsplit=0, *, source=None)\n" +"--\n" +"\n" +"Split string by the occurrences of pattern."); + +#define _SRE_SRE_PATTERN_SPLIT_METHODDEF \ + {"split", (PyCFunction)_sre_SRE_Pattern_split, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_split__doc__}, + +static PyObject * +_sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, + Py_ssize_t maxsplit, PyObject *source); + +static PyObject * +_sre_SRE_Pattern_split(PatternObject *self, PyObject *args, PyObject *kwargs) { - SRE_STATE state; - PyObject* list; - PyObject* item; - Py_ssize_t status; - Py_ssize_t n; - Py_ssize_t i; - void* last; + PyObject *return_value = NULL; + static char *_keywords[] = {"string", "maxsplit", "source", NULL}; + PyObject *string = NULL; + Py_ssize_t maxsplit = 0; + PyObject *source = NULL; - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t maxsplit = 0; - static char* kwlist[] = { "string", "maxsplit", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|On$O:split", kwlist, - &string, &maxsplit, &string2)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On$O:split", _keywords, + &string, &maxsplit, &source)) + goto exit; + return_value = _sre_SRE_Pattern_split_impl(self, string, maxsplit, source); - string = fix_string_param(string, string2, "source"); - if (!string) - return NULL; - - assert(self->codesize != 0); - if (self->code[0] != SRE_OP_INFO || self->code[3] == 0) { - if (self->code[0] == SRE_OP_INFO && self->code[4] == 0) { - PyErr_SetString(PyExc_ValueError, - "split() requires a non-empty pattern match."); - return NULL; - } - if (PyErr_WarnEx(PyExc_FutureWarning, - "split() requires a non-empty pattern match.", - 1) < 0) - return NULL; - } - - string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX); - if (!string) - return NULL; - - list = PyList_New(0); - if (!list) { - state_fini(&state); - return NULL; - } - - n = 0; - last = state.start; - - while (!maxsplit || n < maxsplit) { - - state_reset(&state); - - state.ptr = state.start; - - status = sre_search(&state, PatternObject_GetCode(self)); - if (PyErr_Occurred()) - goto error; - - if (status <= 0) { - if (status == 0) - break; - pattern_error(status); - goto error; - } - - if (state.start == state.ptr) { - if (last == state.end) - break; - /* skip one character */ - state.start = (void*) ((char*) state.ptr + state.charsize); - continue; - } - - /* get segment before this match */ - item = getslice(state.isbytes, state.beginning, - string, STATE_OFFSET(&state, last), - STATE_OFFSET(&state, state.start) - ); - if (!item) - goto error; - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - - /* add groups (if any) */ - for (i = 0; i < self->groups; i++) { - item = state_getslice(&state, i+1, string, 0); - if (!item) - goto error; - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - } - - n = n + 1; - - last = state.start = state.ptr; - - } - - /* get segment following last match (even if empty) */ - item = getslice(state.isbytes, state.beginning, - string, STATE_OFFSET(&state, last), state.endpos - ); - if (!item) - goto error; - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - - state_fini(&state); - return list; - -error: - Py_DECREF(list); - state_fini(&state); - return NULL; - +exit: + return return_value; } -static PyObject* -pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, - Py_ssize_t count, Py_ssize_t subn) +PyDoc_STRVAR(_sre_SRE_Pattern_sub__doc__, +"sub($self, /, repl, string, count=0)\n" +"--\n" +"\n" +"Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl."); + +#define _SRE_SRE_PATTERN_SUB_METHODDEF \ + {"sub", (PyCFunction)_sre_SRE_Pattern_sub, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_sub__doc__}, + +static PyObject * +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, + PyObject *string, Py_ssize_t count); + +static PyObject * +_sre_SRE_Pattern_sub(PatternObject *self, PyObject *args, PyObject *kwargs) { - SRE_STATE state; - PyObject* list; - PyObject* joiner; - PyObject* item; - PyObject* filter; - PyObject* args; - PyObject* match; - void* ptr; - Py_ssize_t status; - Py_ssize_t n; - Py_ssize_t i, b, e; - int isbytes, charsize; - int filter_is_callable; - Py_buffer view; + PyObject *return_value = NULL; + static char *_keywords[] = {"repl", "string", "count", NULL}; + PyObject *repl; + PyObject *string; + Py_ssize_t count = 0; - if (PyCallable_Check(ptemplate)) { - /* sub/subn takes either a function or a template */ - filter = ptemplate; - Py_INCREF(filter); - filter_is_callable = 1; - } else { - /* if not callable, check if it's a literal string */ - int literal; - view.buf = NULL; - ptr = getstring(ptemplate, &n, &isbytes, &charsize, &view); - b = charsize; - if (ptr) { - if (charsize == 1) - literal = memchr(ptr, '\\', n) == NULL; - else - literal = PyUnicode_FindChar(ptemplate, '\\', 0, n, 1) == -1; - } else { - PyErr_Clear(); - literal = 0; - } - if (view.buf) - PyBuffer_Release(&view); - if (literal) { - filter = ptemplate; - Py_INCREF(filter); - filter_is_callable = 0; - } else { - /* not a literal; hand it over to the template compiler */ - filter = call( - SRE_PY_MODULE, "_subx", - PyTuple_Pack(2, self, ptemplate) - ); - if (!filter) - return NULL; - filter_is_callable = PyCallable_Check(filter); - } - } + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|n:sub", _keywords, + &repl, &string, &count)) + goto exit; + return_value = _sre_SRE_Pattern_sub_impl(self, repl, string, count); - string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX); - if (!string) { - Py_DECREF(filter); - return NULL; - } - - list = PyList_New(0); - if (!list) { - Py_DECREF(filter); - state_fini(&state); - return NULL; - } - - n = i = 0; - - while (!count || n < count) { - - state_reset(&state); - - state.ptr = state.start; - - status = sre_search(&state, PatternObject_GetCode(self)); - if (PyErr_Occurred()) - goto error; - - if (status <= 0) { - if (status == 0) - break; - pattern_error(status); - goto error; - } - - b = STATE_OFFSET(&state, state.start); - e = STATE_OFFSET(&state, state.ptr); - - if (i < b) { - /* get segment before this match */ - item = getslice(state.isbytes, state.beginning, - string, i, b); - if (!item) - goto error; - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - - } else if (i == b && i == e && n > 0) - /* ignore empty match on latest position */ - goto next; - - if (filter_is_callable) { - /* pass match object through filter */ - match = pattern_new_match(self, &state, 1); - if (!match) - goto error; - args = PyTuple_Pack(1, match); - if (!args) { - Py_DECREF(match); - goto error; - } - item = PyObject_CallObject(filter, args); - Py_DECREF(args); - Py_DECREF(match); - if (!item) - goto error; - } else { - /* filter is literal string */ - item = filter; - Py_INCREF(item); - } - - /* add to list */ - if (item != Py_None) { - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - } - - i = e; - n = n + 1; - -next: - /* move on */ - if (state.ptr == state.start) - state.start = (void*) ((char*) state.ptr + state.charsize); - else - state.start = state.ptr; - - } - - /* get segment following last match */ - if (i < state.endpos) { - item = getslice(state.isbytes, state.beginning, - string, i, state.endpos); - if (!item) - goto error; - status = PyList_Append(list, item); - Py_DECREF(item); - if (status < 0) - goto error; - } - - state_fini(&state); - - Py_DECREF(filter); - - /* convert list to single string (also removes list) */ - joiner = getslice(state.isbytes, state.beginning, string, 0, 0); - if (!joiner) { - Py_DECREF(list); - return NULL; - } - if (PyList_GET_SIZE(list) == 0) { - Py_DECREF(list); - item = joiner; - } - else { - if (state.isbytes) - item = _PyBytes_Join(joiner, list); - else - item = PyUnicode_Join(joiner, list); - Py_DECREF(joiner); - Py_DECREF(list); - if (!item) - return NULL; - } - - if (subn) - return Py_BuildValue("Nn", item, n); - - return item; - -error: - Py_DECREF(list); - state_fini(&state); - Py_DECREF(filter); - return NULL; - +exit: + return return_value; } -static PyObject* -pattern_sub(PatternObject* self, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern_subn__doc__, +"subn($self, /, repl, string, count=0)\n" +"--\n" +"\n" +"Return the tuple (new_string, number_of_subs_made) found by replacing the leftmost non-overlapping occurrences of pattern with the replacement repl."); + +#define _SRE_SRE_PATTERN_SUBN_METHODDEF \ + {"subn", (PyCFunction)_sre_SRE_Pattern_subn, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern_subn__doc__}, + +static PyObject * +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, + PyObject *string, Py_ssize_t count); + +static PyObject * +_sre_SRE_Pattern_subn(PatternObject *self, PyObject *args, PyObject *kwargs) { - PyObject* ptemplate; - PyObject* string; + PyObject *return_value = NULL; + static char *_keywords[] = {"repl", "string", "count", NULL}; + PyObject *repl; + PyObject *string; Py_ssize_t count = 0; - static char* kwlist[] = { "repl", "string", "count", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|n:sub", kwlist, - &ptemplate, &string, &count)) - return NULL; - return pattern_subx(self, ptemplate, string, count, 0); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|n:subn", _keywords, + &repl, &string, &count)) + goto exit; + return_value = _sre_SRE_Pattern_subn_impl(self, repl, string, count); + +exit: + return return_value; } -static PyObject* -pattern_subn(PatternObject* self, PyObject* args, PyObject* kw) +PyDoc_STRVAR(_sre_SRE_Pattern___copy____doc__, +"__copy__($self, /)\n" +"--\n" +"\n"); + +#define _SRE_SRE_PATTERN___COPY___METHODDEF \ + {"__copy__", (PyCFunction)_sre_SRE_Pattern___copy__, METH_NOARGS, _sre_SRE_Pattern___copy____doc__}, + +static PyObject * +_sre_SRE_Pattern___copy___impl(PatternObject *self); + +static PyObject * +_sre_SRE_Pattern___copy__(PatternObject *self, PyObject *Py_UNUSED(ignored)) { - PyObject* ptemplate; - PyObject* string; - Py_ssize_t count = 0; - static char* kwlist[] = { "repl", "string", "count", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|n:subn", kwlist, - &ptemplate, &string, &count)) - return NULL; - - return pattern_subx(self, ptemplate, string, count, 1); + return _sre_SRE_Pattern___copy___impl(self); } -static PyObject* -pattern_copy(PatternObject* self, PyObject *unused) +PyDoc_STRVAR(_sre_SRE_Pattern___deepcopy____doc__, +"__deepcopy__($self, /, memo)\n" +"--\n" +"\n"); + +#define _SRE_SRE_PATTERN___DEEPCOPY___METHODDEF \ + {"__deepcopy__", (PyCFunction)_sre_SRE_Pattern___deepcopy__, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Pattern___deepcopy____doc__}, + +static PyObject * +_sre_SRE_Pattern___deepcopy___impl(PatternObject *self, PyObject *memo); + +static PyObject * +_sre_SRE_Pattern___deepcopy__(PatternObject *self, PyObject *args, PyObject *kwargs) { -#ifdef USE_BUILTIN_COPY - PatternObject* copy; - int offset; + PyObject *return_value = NULL; + static char *_keywords[] = {"memo", NULL}; + PyObject *memo; - copy = PyObject_NEW_VAR(PatternObject, &Pattern_Type, self->codesize); - if (!copy) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:__deepcopy__", _keywords, + &memo)) + goto exit; + return_value = _sre_SRE_Pattern___deepcopy___impl(self, memo); - offset = offsetof(PatternObject, groups); - - Py_XINCREF(self->groupindex); - Py_XINCREF(self->indexgroup); - Py_XINCREF(self->pattern); - - memcpy((char*) copy + offset, (char*) self + offset, - sizeof(PatternObject) + self->codesize * sizeof(SRE_CODE) - offset); - copy->weakreflist = NULL; - - return (PyObject*) copy; -#else - PyErr_SetString(PyExc_TypeError, "cannot copy this pattern object"); - return NULL; -#endif +exit: + return return_value; } -static PyObject* -pattern_deepcopy(PatternObject* self, PyObject* memo) +PyDoc_STRVAR(_sre_compile__doc__, +"compile($module, /, pattern, flags, code, groups, groupindex,\n" +" indexgroup)\n" +"--\n" +"\n"); + +#define _SRE_COMPILE_METHODDEF \ + {"compile", (PyCFunction)_sre_compile, METH_VARARGS|METH_KEYWORDS, _sre_compile__doc__}, + +static PyObject * +_sre_compile_impl(PyModuleDef *module, PyObject *pattern, int flags, + PyObject *code, Py_ssize_t groups, PyObject *groupindex, + PyObject *indexgroup); + +static PyObject * +_sre_compile(PyModuleDef *module, PyObject *args, PyObject *kwargs) { -#ifdef USE_BUILTIN_COPY - PatternObject* copy; + PyObject *return_value = NULL; + static char *_keywords[] = {"pattern", "flags", "code", "groups", "groupindex", "indexgroup", NULL}; + PyObject *pattern; + int flags; + PyObject *code; + Py_ssize_t groups; + PyObject *groupindex; + PyObject *indexgroup; - copy = (PatternObject*) pattern_copy(self); - if (!copy) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiO!nOO:compile", _keywords, + &pattern, &flags, &PyList_Type, &code, &groups, &groupindex, &indexgroup)) + goto exit; + return_value = _sre_compile_impl(module, pattern, flags, code, groups, groupindex, indexgroup); - if (!deepcopy(©->groupindex, memo) || - !deepcopy(©->indexgroup, memo) || - !deepcopy(©->pattern, memo)) { - Py_DECREF(copy); - return NULL; - } - -#else - PyErr_SetString(PyExc_TypeError, "cannot deepcopy this pattern object"); - return NULL; -#endif +exit: + return return_value; } +PyDoc_STRVAR(_sre_SRE_Match_expand__doc__, +"expand($self, /, template)\n" +"--\n" +"\n" +"Return the string obtained by doing backslash substitution on the string template, as done by the sub() method."); + +#define _SRE_SRE_MATCH_EXPAND_METHODDEF \ + {"expand", (PyCFunction)_sre_SRE_Match_expand, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Match_expand__doc__}, + static PyObject * -pattern_repr(PatternObject *obj) +_sre_SRE_Match_expand_impl(MatchObject *self, PyObject *template); + +static PyObject * +_sre_SRE_Match_expand(MatchObject *self, PyObject *args, PyObject *kwargs) { - static const struct { - const char *name; - int value; - } flag_names[] = { - {"re.TEMPLATE", SRE_FLAG_TEMPLATE}, - {"re.IGNORECASE", SRE_FLAG_IGNORECASE}, - {"re.LOCALE", SRE_FLAG_LOCALE}, - {"re.MULTILINE", SRE_FLAG_MULTILINE}, - {"re.DOTALL", SRE_FLAG_DOTALL}, - {"re.UNICODE", SRE_FLAG_UNICODE}, - {"re.VERBOSE", SRE_FLAG_VERBOSE}, - {"re.DEBUG", SRE_FLAG_DEBUG}, - {"re.ASCII", SRE_FLAG_ASCII}, - }; - PyObject *result = NULL; - PyObject *flag_items; - size_t i; - int flags = obj->flags; + PyObject *return_value = NULL; + static char *_keywords[] = {"template", NULL}; + PyObject *template; - /* Omit re.UNICODE for valid string patterns. */ - if (obj->isbytes == 0 && - (flags & (SRE_FLAG_LOCALE|SRE_FLAG_UNICODE|SRE_FLAG_ASCII)) == - SRE_FLAG_UNICODE) - flags &= ~SRE_FLAG_UNICODE; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:expand", _keywords, + &template)) + goto exit; + return_value = _sre_SRE_Match_expand_impl(self, template); - flag_items = PyList_New(0); - if (!flag_items) - return NULL; - - for (i = 0; i < Py_ARRAY_LENGTH(flag_names); i++) { - if (flags & flag_names[i].value) { - PyObject *item = PyUnicode_FromString(flag_names[i].name); - if (!item) - goto done; - - if (PyList_Append(flag_items, item) < 0) { - Py_DECREF(item); - goto done; - } - Py_DECREF(item); - flags &= ~flag_names[i].value; - } - } - if (flags) { - PyObject *item = PyUnicode_FromFormat("0x%x", flags); - if (!item) - goto done; - - if (PyList_Append(flag_items, item) < 0) { - Py_DECREF(item); - goto done; - } - Py_DECREF(item); - } - - if (PyList_Size(flag_items) > 0) { - PyObject *flags_result; - PyObject *sep = PyUnicode_FromString("|"); - if (!sep) - goto done; - flags_result = PyUnicode_Join(sep, flag_items); - Py_DECREF(sep); - if (!flags_result) - goto done; - result = PyUnicode_FromFormat("re.compile(%.200R, %S)", - obj->pattern, flags_result); - Py_DECREF(flags_result); - } - else { - result = PyUnicode_FromFormat("re.compile(%.200R)", obj->pattern); - } - -done: - Py_DECREF(flag_items); - return result; +exit: + return return_value; } -PyDoc_STRVAR(pattern_match_doc, -"match(string[, pos[, endpos]]) -> match object or None.\n\ - Matches zero or more characters at the beginning of the string"); +PyDoc_STRVAR(_sre_SRE_Match_groups__doc__, +"groups($self, /, default=None)\n" +"--\n" +"\n" +"Return a tuple containing all the subgroups of the match, from 1.\n" +"\n" +" default\n" +" Is used for groups that did not participate in the match."); -PyDoc_STRVAR(pattern_fullmatch_doc, -"fullmatch(string[, pos[, endpos]]) -> match object or None.\n\ - Matches against all of the string"); +#define _SRE_SRE_MATCH_GROUPS_METHODDEF \ + {"groups", (PyCFunction)_sre_SRE_Match_groups, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Match_groups__doc__}, -PyDoc_STRVAR(pattern_search_doc, -"search(string[, pos[, endpos]]) -> match object or None.\n\ - Scan through string looking for a match, and return a corresponding\n\ - match object instance. Return None if no position in the string matches."); +static PyObject * +_sre_SRE_Match_groups_impl(MatchObject *self, PyObject *default_value); -PyDoc_STRVAR(pattern_split_doc, -"split(string[, maxsplit = 0]) -> list.\n\ - Split string by the occurrences of pattern."); +static PyObject * +_sre_SRE_Match_groups(MatchObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"default", NULL}; + PyObject *default_value = Py_None; -PyDoc_STRVAR(pattern_findall_doc, -"findall(string[, pos[, endpos]]) -> list.\n\ - Return a list of all non-overlapping matches of pattern in string."); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groups", _keywords, + &default_value)) + goto exit; + return_value = _sre_SRE_Match_groups_impl(self, default_value); -PyDoc_STRVAR(pattern_finditer_doc, -"finditer(string[, pos[, endpos]]) -> iterator.\n\ - Return an iterator over all non-overlapping matches for the \n\ - RE pattern in string. For each match, the iterator returns a\n\ - match object."); - -PyDoc_STRVAR(pattern_sub_doc, -"sub(repl, string[, count = 0]) -> newstring.\n\ - Return the string obtained by replacing the leftmost non-overlapping\n\ - occurrences of pattern in string by the replacement repl."); - -PyDoc_STRVAR(pattern_subn_doc, -"subn(repl, string[, count = 0]) -> (newstring, number of subs)\n\ - Return the tuple (new_string, number_of_subs_made) found by replacing\n\ - the leftmost non-overlapping occurrences of pattern with the\n\ - replacement repl."); - -PyDoc_STRVAR(pattern_doc, "Compiled regular expression objects"); - -static PyMethodDef pattern_methods[] = { - {"match", (PyCFunction) pattern_match, METH_VARARGS|METH_KEYWORDS, - pattern_match_doc}, - {"fullmatch", (PyCFunction) pattern_fullmatch, METH_VARARGS|METH_KEYWORDS, - pattern_fullmatch_doc}, - {"search", (PyCFunction) pattern_search, METH_VARARGS|METH_KEYWORDS, - pattern_search_doc}, - {"sub", (PyCFunction) pattern_sub, METH_VARARGS|METH_KEYWORDS, - pattern_sub_doc}, - {"subn", (PyCFunction) pattern_subn, METH_VARARGS|METH_KEYWORDS, - pattern_subn_doc}, - {"split", (PyCFunction) pattern_split, METH_VARARGS|METH_KEYWORDS, - pattern_split_doc}, - {"findall", (PyCFunction) pattern_findall, METH_VARARGS|METH_KEYWORDS, - pattern_findall_doc}, - {"finditer", (PyCFunction) pattern_finditer, METH_VARARGS|METH_KEYWORDS, - pattern_finditer_doc}, - {"scanner", (PyCFunction) pattern_scanner, METH_VARARGS|METH_KEYWORDS}, - {"__copy__", (PyCFunction) pattern_copy, METH_NOARGS}, - {"__deepcopy__", (PyCFunction) pattern_deepcopy, METH_O}, - {NULL, NULL} -}; - -/* PatternObject's 'groupindex' method. */ -static PyObject * -pattern_groupindex(PatternObject *self) -{ - return PyDictProxy_New(self->groupindex); +exit: + return return_value; } -static PyGetSetDef pattern_getset[] = { - {"groupindex", (getter)pattern_groupindex, (setter)NULL, - "A dictionary mapping group names to group numbers."}, - {NULL} /* Sentinel */ -}; +PyDoc_STRVAR(_sre_SRE_Match_groupdict__doc__, +"groupdict($self, /, default=None)\n" +"--\n" +"\n" +"Return a dictionary containing all the named subgroups of the match, keyed by the subgroup name.\n" +"\n" +" default\n" +" Is used for groups that did not participate in the match."); -#define PAT_OFF(x) offsetof(PatternObject, x) -static PyMemberDef pattern_members[] = { - {"pattern", T_OBJECT, PAT_OFF(pattern), READONLY}, - {"flags", T_INT, PAT_OFF(flags), READONLY}, - {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject Pattern_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_" SRE_MODULE ".SRE_Pattern", - sizeof(PatternObject), sizeof(SRE_CODE), - (destructor)pattern_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)pattern_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - pattern_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pattern_methods, /* tp_methods */ - pattern_members, /* tp_members */ - pattern_getset, /* tp_getset */ -}; - -static int _validate(PatternObject *self); /* Forward */ +#define _SRE_SRE_MATCH_GROUPDICT_METHODDEF \ + {"groupdict", (PyCFunction)_sre_SRE_Match_groupdict, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Match_groupdict__doc__}, static PyObject * -_compile(PyObject* self_, PyObject* args) +_sre_SRE_Match_groupdict_impl(MatchObject *self, PyObject *default_value); + +static PyObject * +_sre_SRE_Match_groupdict(MatchObject *self, PyObject *args, PyObject *kwargs) { - /* "compile" pattern descriptor to pattern object */ + PyObject *return_value = NULL; + static char *_keywords[] = {"default", NULL}; + PyObject *default_value = Py_None; - PatternObject* self; - Py_ssize_t i, n; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groupdict", _keywords, + &default_value)) + goto exit; + return_value = _sre_SRE_Match_groupdict_impl(self, default_value); - PyObject* pattern; - int flags = 0; - PyObject* code; - Py_ssize_t groups = 0; - PyObject* groupindex = NULL; - PyObject* indexgroup = NULL; - - if (!PyArg_ParseTuple(args, "OiO!nOO", &pattern, &flags, - &PyList_Type, &code, &groups, - &groupindex, &indexgroup)) - return NULL; - - n = PyList_GET_SIZE(code); - /* coverity[ampersand_in_size] */ - self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n); - if (!self) - return NULL; - self->weakreflist = NULL; - self->pattern = NULL; - self->groupindex = NULL; - self->indexgroup = NULL; - - self->codesize = n; - - for (i = 0; i < n; i++) { - PyObject *o = PyList_GET_ITEM(code, i); - unsigned long value = PyLong_AsUnsignedLong(o); - self->code[i] = (SRE_CODE) value; - if ((unsigned long) self->code[i] != value) { - PyErr_SetString(PyExc_OverflowError, - "regular expression code size limit exceeded"); - break; - } - } - - if (PyErr_Occurred()) { - Py_DECREF(self); - return NULL; - } - - if (pattern == Py_None) { - self->isbytes = -1; - } - else { - Py_ssize_t p_length; - int charsize; - Py_buffer view; - view.buf = NULL; - if (!getstring(pattern, &p_length, &self->isbytes, - &charsize, &view)) { - Py_DECREF(self); - return NULL; - } - if (view.buf) - PyBuffer_Release(&view); - } - - Py_INCREF(pattern); - self->pattern = pattern; - - self->flags = flags; - - self->groups = groups; - - Py_XINCREF(groupindex); - self->groupindex = groupindex; - - Py_XINCREF(indexgroup); - self->indexgroup = indexgroup; - - self->weakreflist = NULL; - - if (!_validate(self)) { - Py_DECREF(self); - return NULL; - } - - return (PyObject*) self; +exit: + return return_value; } -/* -------------------------------------------------------------------- */ -/* Code validation */ +PyDoc_STRVAR(_sre_SRE_Match_start__doc__, +"start($self, group=0, /)\n" +"--\n" +"\n" +"Return index of the start of the substring matched by group."); -/* To learn more about this code, have a look at the _compile() function in - Lib/sre_compile.py. The validation functions below checks the code array - for conformance with the code patterns generated there. +#define _SRE_SRE_MATCH_START_METHODDEF \ + {"start", (PyCFunction)_sre_SRE_Match_start, METH_VARARGS, _sre_SRE_Match_start__doc__}, - The nice thing about the generated code is that it is position-independent: - all jumps are relative jumps forward. Also, jumps don't cross each other: - the target of a later jump is always earlier than the target of an earlier - jump. IOW, this is okay: +static Py_ssize_t +_sre_SRE_Match_start_impl(MatchObject *self, PyObject *group); - J---------J-------T--------T - \ \_____/ / - \______________________/ +static PyObject * +_sre_SRE_Match_start(MatchObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *group = NULL; + Py_ssize_t _return_value; - but this is not: + if (!PyArg_UnpackTuple(args, "start", + 0, 1, + &group)) + goto exit; + _return_value = _sre_SRE_Match_start_impl(self, group); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); - J---------J-------T--------T - \_________\_____/ / - \____________/ - - It also helps that SRE_CODE is always an unsigned type. -*/ - -/* Defining this one enables tracing of the validator */ -#undef VVERBOSE - -/* Trace macro for the validator */ -#if defined(VVERBOSE) -#define VTRACE(v) printf v -#else -#define VTRACE(v) do {} while(0) /* do nothing */ -#endif - -/* Report failure */ -#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return 0; } while (0) - -/* Extract opcode, argument, or skip count from code array */ -#define GET_OP \ - do { \ - VTRACE(("%p: ", code)); \ - if (code >= end) FAIL; \ - op = *code++; \ - VTRACE(("%lu (op)\n", (unsigned long)op)); \ - } while (0) -#define GET_ARG \ - do { \ - VTRACE(("%p= ", code)); \ - if (code >= end) FAIL; \ - arg = *code++; \ - VTRACE(("%lu (arg)\n", (unsigned long)arg)); \ - } while (0) -#define GET_SKIP_ADJ(adj) \ - do { \ - VTRACE(("%p= ", code)); \ - if (code >= end) FAIL; \ - skip = *code; \ - VTRACE(("%lu (skip to %p)\n", \ - (unsigned long)skip, code+skip)); \ - if (skip-adj > (Py_uintptr_t)(end - code)) \ - FAIL; \ - code++; \ - } while (0) -#define GET_SKIP GET_SKIP_ADJ(0) - -static int -_validate_charset(SRE_CODE *code, SRE_CODE *end) -{ - /* Some variables are manipulated by the macros above */ - SRE_CODE op; - SRE_CODE arg; - SRE_CODE offset; - int i; - - while (code < end) { - GET_OP; - switch (op) { - - case SRE_OP_NEGATE: - break; - - case SRE_OP_LITERAL: - GET_ARG; - break; - - case SRE_OP_RANGE: - case SRE_OP_RANGE_IGNORE: - GET_ARG; - GET_ARG; - break; - - case SRE_OP_CHARSET: - offset = 256/SRE_CODE_BITS; /* 256-bit bitmap */ - if (offset > (Py_uintptr_t)(end - code)) - FAIL; - code += offset; - break; - - case SRE_OP_BIGCHARSET: - GET_ARG; /* Number of blocks */ - offset = 256/sizeof(SRE_CODE); /* 256-byte table */ - if (offset > (Py_uintptr_t)(end - code)) - FAIL; - /* Make sure that each byte points to a valid block */ - for (i = 0; i < 256; i++) { - if (((unsigned char *)code)[i] >= arg) - FAIL; - } - code += offset; - offset = arg * (256/SRE_CODE_BITS); /* 256-bit bitmap times arg */ - if (offset > (Py_uintptr_t)(end - code)) - FAIL; - code += offset; - break; - - case SRE_OP_CATEGORY: - GET_ARG; - switch (arg) { - case SRE_CATEGORY_DIGIT: - case SRE_CATEGORY_NOT_DIGIT: - case SRE_CATEGORY_SPACE: - case SRE_CATEGORY_NOT_SPACE: - case SRE_CATEGORY_WORD: - case SRE_CATEGORY_NOT_WORD: - case SRE_CATEGORY_LINEBREAK: - case SRE_CATEGORY_NOT_LINEBREAK: - case SRE_CATEGORY_LOC_WORD: - case SRE_CATEGORY_LOC_NOT_WORD: - case SRE_CATEGORY_UNI_DIGIT: - case SRE_CATEGORY_UNI_NOT_DIGIT: - case SRE_CATEGORY_UNI_SPACE: - case SRE_CATEGORY_UNI_NOT_SPACE: - case SRE_CATEGORY_UNI_WORD: - case SRE_CATEGORY_UNI_NOT_WORD: - case SRE_CATEGORY_UNI_LINEBREAK: - case SRE_CATEGORY_UNI_NOT_LINEBREAK: - break; - default: - FAIL; - } - break; - - default: - FAIL; - - } - } - - return 1; +exit: + return return_value; } -static int -_validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) +PyDoc_STRVAR(_sre_SRE_Match_end__doc__, +"end($self, group=0, /)\n" +"--\n" +"\n" +"Return index of the end of the substring matched by group."); + +#define _SRE_SRE_MATCH_END_METHODDEF \ + {"end", (PyCFunction)_sre_SRE_Match_end, METH_VARARGS, _sre_SRE_Match_end__doc__}, + +static Py_ssize_t +_sre_SRE_Match_end_impl(MatchObject *self, PyObject *group); + +static PyObject * +_sre_SRE_Match_end(MatchObject *self, PyObject *args) { - /* Some variables are manipulated by the macros above */ - SRE_CODE op; - SRE_CODE arg; - SRE_CODE skip; + PyObject *return_value = NULL; + PyObject *group = NULL; + Py_ssize_t _return_value; - VTRACE(("code=%p, end=%p\n", code, end)); + if (!PyArg_UnpackTuple(args, "end", + 0, 1, + &group)) + goto exit; + _return_value = _sre_SRE_Match_end_impl(self, group); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); - if (code > end) - FAIL; - - while (code < end) { - GET_OP; - switch (op) { - - case SRE_OP_MARK: - /* We don't check whether marks are properly nested; the - sre_match() code is robust even if they don't, and the worst - you can get is nonsensical match results. */ - GET_ARG; - if (arg > 2 * (size_t)groups + 1) { - VTRACE(("arg=%d, groups=%d\n", (int)arg, (int)groups)); - FAIL; - } - break; - - case SRE_OP_LITERAL: - case SRE_OP_NOT_LITERAL: - case SRE_OP_LITERAL_IGNORE: - case SRE_OP_NOT_LITERAL_IGNORE: - GET_ARG; - /* The arg is just a character, nothing to check */ - break; - - case SRE_OP_SUCCESS: - case SRE_OP_FAILURE: - /* Nothing to check; these normally end the matching process */ - break; - - case SRE_OP_AT: - GET_ARG; - switch (arg) { - case SRE_AT_BEGINNING: - case SRE_AT_BEGINNING_STRING: - case SRE_AT_BEGINNING_LINE: - case SRE_AT_END: - case SRE_AT_END_LINE: - case SRE_AT_END_STRING: - case SRE_AT_BOUNDARY: - case SRE_AT_NON_BOUNDARY: - case SRE_AT_LOC_BOUNDARY: - case SRE_AT_LOC_NON_BOUNDARY: - case SRE_AT_UNI_BOUNDARY: - case SRE_AT_UNI_NON_BOUNDARY: - break; - default: - FAIL; - } - break; - - case SRE_OP_ANY: - case SRE_OP_ANY_ALL: - /* These have no operands */ - break; - - case SRE_OP_IN: - case SRE_OP_IN_IGNORE: - GET_SKIP; - /* Stop 1 before the end; we check the FAILURE below */ - if (!_validate_charset(code, code+skip-2)) - FAIL; - if (code[skip-2] != SRE_OP_FAILURE) - FAIL; - code += skip-1; - break; - - case SRE_OP_INFO: - { - /* A minimal info field is - <1=skip> <2=flags> <3=min> <4=max>; - If SRE_INFO_PREFIX or SRE_INFO_CHARSET is in the flags, - more follows. */ - SRE_CODE flags, i; - SRE_CODE *newcode; - GET_SKIP; - newcode = code+skip-1; - GET_ARG; flags = arg; - GET_ARG; - GET_ARG; - /* Check that only valid flags are present */ - if ((flags & ~(SRE_INFO_PREFIX | - SRE_INFO_LITERAL | - SRE_INFO_CHARSET)) != 0) - FAIL; - /* PREFIX and CHARSET are mutually exclusive */ - if ((flags & SRE_INFO_PREFIX) && - (flags & SRE_INFO_CHARSET)) - FAIL; - /* LITERAL implies PREFIX */ - if ((flags & SRE_INFO_LITERAL) && - !(flags & SRE_INFO_PREFIX)) - FAIL; - /* Validate the prefix */ - if (flags & SRE_INFO_PREFIX) { - SRE_CODE prefix_len; - GET_ARG; prefix_len = arg; - GET_ARG; - /* Here comes the prefix string */ - if (prefix_len > (Py_uintptr_t)(newcode - code)) - FAIL; - code += prefix_len; - /* And here comes the overlap table */ - if (prefix_len > (Py_uintptr_t)(newcode - code)) - FAIL; - /* Each overlap value should be < prefix_len */ - for (i = 0; i < prefix_len; i++) { - if (code[i] >= prefix_len) - FAIL; - } - code += prefix_len; - } - /* Validate the charset */ - if (flags & SRE_INFO_CHARSET) { - if (!_validate_charset(code, newcode-1)) - FAIL; - if (newcode[-1] != SRE_OP_FAILURE) - FAIL; - code = newcode; - } - else if (code != newcode) { - VTRACE(("code=%p, newcode=%p\n", code, newcode)); - FAIL; - } - } - break; - - case SRE_OP_BRANCH: - { - SRE_CODE *target = NULL; - for (;;) { - GET_SKIP; - if (skip == 0) - break; - /* Stop 2 before the end; we check the JUMP below */ - if (!_validate_inner(code, code+skip-3, groups)) - FAIL; - code += skip-3; - /* Check that it ends with a JUMP, and that each JUMP - has the same target */ - GET_OP; - if (op != SRE_OP_JUMP) - FAIL; - GET_SKIP; - if (target == NULL) - target = code+skip-1; - else if (code+skip-1 != target) - FAIL; - } - } - break; - - case SRE_OP_REPEAT_ONE: - case SRE_OP_MIN_REPEAT_ONE: - { - SRE_CODE min, max; - GET_SKIP; - GET_ARG; min = arg; - GET_ARG; max = arg; - if (min > max) - FAIL; - if (max > SRE_MAXREPEAT) - FAIL; - if (!_validate_inner(code, code+skip-4, groups)) - FAIL; - code += skip-4; - GET_OP; - if (op != SRE_OP_SUCCESS) - FAIL; - } - break; - - case SRE_OP_REPEAT: - { - SRE_CODE min, max; - GET_SKIP; - GET_ARG; min = arg; - GET_ARG; max = arg; - if (min > max) - FAIL; - if (max > SRE_MAXREPEAT) - FAIL; - if (!_validate_inner(code, code+skip-3, groups)) - FAIL; - code += skip-3; - GET_OP; - if (op != SRE_OP_MAX_UNTIL && op != SRE_OP_MIN_UNTIL) - FAIL; - } - break; - - case SRE_OP_GROUPREF: - case SRE_OP_GROUPREF_IGNORE: - GET_ARG; - if (arg >= (size_t)groups) - FAIL; - break; - - case SRE_OP_GROUPREF_EXISTS: - /* The regex syntax for this is: '(?(group)then|else)', where - 'group' is either an integer group number or a group name, - 'then' and 'else' are sub-regexes, and 'else' is optional. */ - GET_ARG; - if (arg >= (size_t)groups) - FAIL; - GET_SKIP_ADJ(1); - code--; /* The skip is relative to the first arg! */ - /* There are two possibilities here: if there is both a 'then' - part and an 'else' part, the generated code looks like: - - GROUPREF_EXISTS - - - ...then part... - JUMP - - ( jumps here) - ...else part... - ( jumps here) - - If there is only a 'then' part, it looks like: - - GROUPREF_EXISTS - - - ...then part... - ( jumps here) - - There is no direct way to decide which it is, and we don't want - to allow arbitrary jumps anywhere in the code; so we just look - for a JUMP opcode preceding our skip target. - */ - if (skip >= 3 && skip-3 < (Py_uintptr_t)(end - code) && - code[skip-3] == SRE_OP_JUMP) - { - VTRACE(("both then and else parts present\n")); - if (!_validate_inner(code+1, code+skip-3, groups)) - FAIL; - code += skip-2; /* Position after JUMP, at */ - GET_SKIP; - if (!_validate_inner(code, code+skip-1, groups)) - FAIL; - code += skip-1; - } - else { - VTRACE(("only a then part present\n")); - if (!_validate_inner(code+1, code+skip-1, groups)) - FAIL; - code += skip-1; - } - break; - - case SRE_OP_ASSERT: - case SRE_OP_ASSERT_NOT: - GET_SKIP; - GET_ARG; /* 0 for lookahead, width for lookbehind */ - code--; /* Back up over arg to simplify math below */ - if (arg & 0x80000000) - FAIL; /* Width too large */ - /* Stop 1 before the end; we check the SUCCESS below */ - if (!_validate_inner(code+1, code+skip-2, groups)) - FAIL; - code += skip-2; - GET_OP; - if (op != SRE_OP_SUCCESS) - FAIL; - break; - - default: - FAIL; - - } - } - - VTRACE(("okay\n")); - return 1; +exit: + return return_value; } -static int -_validate_outer(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) +PyDoc_STRVAR(_sre_SRE_Match_span__doc__, +"span($self, group=0, /)\n" +"--\n" +"\n" +"For MatchObject m, return the 2-tuple (m.start(group), m.end(group))."); + +#define _SRE_SRE_MATCH_SPAN_METHODDEF \ + {"span", (PyCFunction)_sre_SRE_Match_span, METH_VARARGS, _sre_SRE_Match_span__doc__}, + +static PyObject * +_sre_SRE_Match_span_impl(MatchObject *self, PyObject *group); + +static PyObject * +_sre_SRE_Match_span(MatchObject *self, PyObject *args) { - if (groups < 0 || (size_t)groups > SRE_MAXGROUPS || - code >= end || end[-1] != SRE_OP_SUCCESS) - FAIL; - return _validate_inner(code, end-1, groups); + PyObject *return_value = NULL; + PyObject *group = NULL; + + if (!PyArg_UnpackTuple(args, "span", + 0, 1, + &group)) + goto exit; + return_value = _sre_SRE_Match_span_impl(self, group); + +exit: + return return_value; } -static int -_validate(PatternObject *self) +PyDoc_STRVAR(_sre_SRE_Match___copy____doc__, +"__copy__($self, /)\n" +"--\n" +"\n"); + +#define _SRE_SRE_MATCH___COPY___METHODDEF \ + {"__copy__", (PyCFunction)_sre_SRE_Match___copy__, METH_NOARGS, _sre_SRE_Match___copy____doc__}, + +static PyObject * +_sre_SRE_Match___copy___impl(MatchObject *self); + +static PyObject * +_sre_SRE_Match___copy__(MatchObject *self, PyObject *Py_UNUSED(ignored)) { - if (!_validate_outer(self->code, self->code+self->codesize, self->groups)) - { - PyErr_SetString(PyExc_RuntimeError, "invalid SRE code"); - return 0; - } - else - VTRACE(("Success!\n")); - return 1; + return _sre_SRE_Match___copy___impl(self); } -/* -------------------------------------------------------------------- */ -/* match methods */ +PyDoc_STRVAR(_sre_SRE_Match___deepcopy____doc__, +"__deepcopy__($self, /, memo)\n" +"--\n" +"\n"); -static void -match_dealloc(MatchObject* self) +#define _SRE_SRE_MATCH___DEEPCOPY___METHODDEF \ + {"__deepcopy__", (PyCFunction)_sre_SRE_Match___deepcopy__, METH_VARARGS|METH_KEYWORDS, _sre_SRE_Match___deepcopy____doc__}, + +static PyObject * +_sre_SRE_Match___deepcopy___impl(MatchObject *self, PyObject *memo); + +static PyObject * +_sre_SRE_Match___deepcopy__(MatchObject *self, PyObject *args, PyObject *kwargs) { - Py_XDECREF(self->regs); - Py_XDECREF(self->string); - Py_DECREF(self->pattern); - PyObject_DEL(self); + PyObject *return_value = NULL; + static char *_keywords[] = {"memo", NULL}; + PyObject *memo; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:__deepcopy__", _keywords, + &memo)) + goto exit; + return_value = _sre_SRE_Match___deepcopy___impl(self, memo); + +exit: + return return_value; } -static PyObject* -match_getslice_by_index(MatchObject* self, Py_ssize_t index, PyObject* def) +PyDoc_STRVAR(_sre_SRE_Scanner_match__doc__, +"match($self, /)\n" +"--\n" +"\n"); + +#define _SRE_SRE_SCANNER_MATCH_METHODDEF \ + {"match", (PyCFunction)_sre_SRE_Scanner_match, METH_NOARGS, _sre_SRE_Scanner_match__doc__}, + +static PyObject * +_sre_SRE_Scanner_match_impl(ScannerObject *self); + +static PyObject * +_sre_SRE_Scanner_match(ScannerObject *self, PyObject *Py_UNUSED(ignored)) { - Py_ssize_t length; - int isbytes, charsize; - Py_buffer view; - PyObject *result; - void* ptr; - - if (index < 0 || index >= self->groups) { - /* raise IndexError if we were given a bad group number */ - PyErr_SetString( - PyExc_IndexError, - "no such group" - ); - return NULL; - } - - index *= 2; - - if (self->string == Py_None || self->mark[index] < 0) { - /* return default value if the string or group is undefined */ - Py_INCREF(def); - return def; - } - - ptr = getstring(self->string, &length, &isbytes, &charsize, &view); - if (ptr == NULL) - return NULL; - result = getslice(isbytes, ptr, - self->string, self->mark[index], self->mark[index+1]); - if (isbytes && view.buf != NULL) - PyBuffer_Release(&view); - return result; + return _sre_SRE_Scanner_match_impl(self); } -static Py_ssize_t -match_getindex(MatchObject* self, PyObject* index) -{ - Py_ssize_t i; +PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, +"search($self, /)\n" +"--\n" +"\n"); - if (index == NULL) - /* Default value */ - return 0; - - if (PyLong_Check(index)) - return PyLong_AsSsize_t(index); - - i = -1; - - if (self->pattern->groupindex) { - index = PyObject_GetItem(self->pattern->groupindex, index); - if (index) { - if (PyLong_Check(index)) - i = PyLong_AsSsize_t(index); - Py_DECREF(index); - } else - PyErr_Clear(); - } - - return i; -} - -static PyObject* -match_getslice(MatchObject* self, PyObject* index, PyObject* def) -{ - return match_getslice_by_index(self, match_getindex(self, index), def); -} - -static PyObject* -match_expand(MatchObject* self, PyObject* ptemplate) -{ - /* delegate to Python code */ - return call( - SRE_PY_MODULE, "_expand", - PyTuple_Pack(3, self->pattern, self, ptemplate) - ); -} - -static PyObject* -match_group(MatchObject* self, PyObject* args) -{ - PyObject* result; - Py_ssize_t i, size; - - size = PyTuple_GET_SIZE(args); - - switch (size) { - case 0: - result = match_getslice(self, Py_False, Py_None); - break; - case 1: - result = match_getslice(self, PyTuple_GET_ITEM(args, 0), Py_None); - break; - default: - /* fetch multiple items */ - result = PyTuple_New(size); - if (!result) - return NULL; - for (i = 0; i < size; i++) { - PyObject* item = match_getslice( - self, PyTuple_GET_ITEM(args, i), Py_None - ); - if (!item) { - Py_DECREF(result); - return NULL; - } - PyTuple_SET_ITEM(result, i, item); - } - break; - } - return result; -} - -static PyObject* -match_groups(MatchObject* self, PyObject* args, PyObject* kw) -{ - PyObject* result; - Py_ssize_t index; - - PyObject* def = Py_None; - static char* kwlist[] = { "default", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groups", kwlist, &def)) - return NULL; - - result = PyTuple_New(self->groups-1); - if (!result) - return NULL; - - for (index = 1; index < self->groups; index++) { - PyObject* item; - item = match_getslice_by_index(self, index, def); - if (!item) { - Py_DECREF(result); - return NULL; - } - PyTuple_SET_ITEM(result, index-1, item); - } - - return result; -} - -static PyObject* -match_groupdict(MatchObject* self, PyObject* args, PyObject* kw) -{ - PyObject* result; - PyObject* keys; - Py_ssize_t index; - - PyObject* def = Py_None; - static char* kwlist[] = { "default", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:groupdict", kwlist, &def)) - return NULL; - - result = PyDict_New(); - if (!result || !self->pattern->groupindex) - return result; - - keys = PyMapping_Keys(self->pattern->groupindex); - if (!keys) - goto failed; - - for (index = 0; index < PyList_GET_SIZE(keys); index++) { - int status; - PyObject* key; - PyObject* value; - key = PyList_GET_ITEM(keys, index); - if (!key) - goto failed; - value = match_getslice(self, key, def); - if (!value) { - Py_DECREF(key); - goto failed; - } - status = PyDict_SetItem(result, key, value); - Py_DECREF(value); - if (status < 0) - goto failed; - } - - Py_DECREF(keys); - - return result; - -failed: - Py_XDECREF(keys); - Py_DECREF(result); - return NULL; -} - -static PyObject* -match_start(MatchObject* self, PyObject* args) -{ - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "start", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); - - if (index < 0 || index >= self->groups) { - PyErr_SetString( - PyExc_IndexError, - "no such group" - ); - return NULL; - } - - /* mark is -1 if group is undefined */ - return PyLong_FromSsize_t(self->mark[index*2]); -} - -static PyObject* -match_end(MatchObject* self, PyObject* args) -{ - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "end", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); - - if (index < 0 || index >= self->groups) { - PyErr_SetString( - PyExc_IndexError, - "no such group" - ); - return NULL; - } - - /* mark is -1 if group is undefined */ - return PyLong_FromSsize_t(self->mark[index*2+1]); -} - -LOCAL(PyObject*) -_pair(Py_ssize_t i1, Py_ssize_t i2) -{ - PyObject* pair; - PyObject* item; - - pair = PyTuple_New(2); - if (!pair) - return NULL; - - item = PyLong_FromSsize_t(i1); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 0, item); - - item = PyLong_FromSsize_t(i2); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 1, item); - - return pair; - - error: - Py_DECREF(pair); - return NULL; -} - -static PyObject* -match_span(MatchObject* self, PyObject* args) -{ - Py_ssize_t index; - - PyObject* index_ = NULL; - if (!PyArg_UnpackTuple(args, "span", 0, 1, &index_)) - return NULL; - - index = match_getindex(self, index_); - - if (index < 0 || index >= self->groups) { - PyErr_SetString( - PyExc_IndexError, - "no such group" - ); - return NULL; - } - - /* marks are -1 if group is undefined */ - return _pair(self->mark[index*2], self->mark[index*2+1]); -} - -static PyObject* -match_regs(MatchObject* self) -{ - PyObject* regs; - PyObject* item; - Py_ssize_t index; - - regs = PyTuple_New(self->groups); - if (!regs) - return NULL; - - for (index = 0; index < self->groups; index++) { - item = _pair(self->mark[index*2], self->mark[index*2+1]); - if (!item) { - Py_DECREF(regs); - return NULL; - } - PyTuple_SET_ITEM(regs, index, item); - } - - Py_INCREF(regs); - self->regs = regs; - - return regs; -} - -static PyObject* -match_copy(MatchObject* self, PyObject *unused) -{ -#ifdef USE_BUILTIN_COPY - MatchObject* copy; - Py_ssize_t slots, offset; - - slots = 2 * (self->pattern->groups+1); - - copy = PyObject_NEW_VAR(MatchObject, &Match_Type, slots); - if (!copy) - return NULL; - - /* this value a constant, but any compiler should be able to - figure that out all by itself */ - offset = offsetof(MatchObject, string); - - Py_XINCREF(self->pattern); - Py_XINCREF(self->string); - Py_XINCREF(self->regs); - - memcpy((char*) copy + offset, (char*) self + offset, - sizeof(MatchObject) + slots * sizeof(Py_ssize_t) - offset); - - return (PyObject*) copy; -#else - PyErr_SetString(PyExc_TypeError, "cannot copy this match object"); - return NULL; -#endif -} - -static PyObject* -match_deepcopy(MatchObject* self, PyObject* memo) -{ -#ifdef USE_BUILTIN_COPY - MatchObject* copy; - - copy = (MatchObject*) match_copy(self); - if (!copy) - return NULL; - - if (!deepcopy((PyObject**) ©->pattern, memo) || - !deepcopy(©->string, memo) || - !deepcopy(©->regs, memo)) { - Py_DECREF(copy); - return NULL; - } - -#else - PyErr_SetString(PyExc_TypeError, "cannot deepcopy this match object"); - return NULL; -#endif -} - -PyDoc_STRVAR(match_doc, -"The result of re.match() and re.search().\n\ -Match objects always have a boolean value of True."); - -PyDoc_STRVAR(match_group_doc, -"group([group1, ...]) -> str or tuple.\n\ - Return subgroup(s) of the match by indices or names.\n\ - For 0 returns the entire match."); - -PyDoc_STRVAR(match_start_doc, -"start([group=0]) -> int.\n\ - Return index of the start of the substring matched by group."); - -PyDoc_STRVAR(match_end_doc, -"end([group=0]) -> int.\n\ - Return index of the end of the substring matched by group."); - -PyDoc_STRVAR(match_span_doc, -"span([group]) -> tuple.\n\ - For MatchObject m, return the 2-tuple (m.start(group), m.end(group))."); - -PyDoc_STRVAR(match_groups_doc, -"groups([default=None]) -> tuple.\n\ - Return a tuple containing all the subgroups of the match, from 1.\n\ - The default argument is used for groups\n\ - that did not participate in the match"); - -PyDoc_STRVAR(match_groupdict_doc, -"groupdict([default=None]) -> dict.\n\ - Return a dictionary containing all the named subgroups of the match,\n\ - keyed by the subgroup name. The default argument is used for groups\n\ - that did not participate in the match"); - -PyDoc_STRVAR(match_expand_doc, -"expand(template) -> str.\n\ - Return the string obtained by doing backslash substitution\n\ - on the string template, as done by the sub() method."); - -static PyMethodDef match_methods[] = { - {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc}, - {"start", (PyCFunction) match_start, METH_VARARGS, match_start_doc}, - {"end", (PyCFunction) match_end, METH_VARARGS, match_end_doc}, - {"span", (PyCFunction) match_span, METH_VARARGS, match_span_doc}, - {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS, - match_groups_doc}, - {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS, - match_groupdict_doc}, - {"expand", (PyCFunction) match_expand, METH_O, match_expand_doc}, - {"__copy__", (PyCFunction) match_copy, METH_NOARGS}, - {"__deepcopy__", (PyCFunction) match_deepcopy, METH_O}, - {NULL, NULL} -}; +#define _SRE_SRE_SCANNER_SEARCH_METHODDEF \ + {"search", (PyCFunction)_sre_SRE_Scanner_search, METH_NOARGS, _sre_SRE_Scanner_search__doc__}, static PyObject * -match_lastindex_get(MatchObject *self) -{ - if (self->lastindex >= 0) - return PyLong_FromSsize_t(self->lastindex); - Py_INCREF(Py_None); - return Py_None; -} +_sre_SRE_Scanner_search_impl(ScannerObject *self); static PyObject * -match_lastgroup_get(MatchObject *self) +_sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) { - if (self->pattern->indexgroup && self->lastindex >= 0) { - PyObject* result = PySequence_GetItem( - self->pattern->indexgroup, self->lastindex - ); - if (result) - return result; - PyErr_Clear(); - } - Py_INCREF(Py_None); - return Py_None; + return _sre_SRE_Scanner_search_impl(self); } - -static PyObject * -match_regs_get(MatchObject *self) -{ - if (self->regs) { - Py_INCREF(self->regs); - return self->regs; - } else - return match_regs(self); -} - -static PyObject * -match_repr(MatchObject *self) -{ - PyObject *result; - PyObject *group0 = match_getslice_by_index(self, 0, Py_None); - if (group0 == NULL) - return NULL; - result = PyUnicode_FromFormat( - "<%s object; span=(%d, %d), match=%.50R>", - Py_TYPE(self)->tp_name, - self->mark[0], self->mark[1], group0); - Py_DECREF(group0); - return result; -} - - -static PyGetSetDef match_getset[] = { - {"lastindex", (getter)match_lastindex_get, (setter)NULL}, - {"lastgroup", (getter)match_lastgroup_get, (setter)NULL}, - {"regs", (getter)match_regs_get, (setter)NULL}, - {NULL} -}; - -#define MATCH_OFF(x) offsetof(MatchObject, x) -static PyMemberDef match_members[] = { - {"string", T_OBJECT, MATCH_OFF(string), READONLY}, - {"re", T_OBJECT, MATCH_OFF(pattern), READONLY}, - {"pos", T_PYSSIZET, MATCH_OFF(pos), READONLY}, - {"endpos", T_PYSSIZET, MATCH_OFF(endpos), READONLY}, - {NULL} -}; - -/* FIXME: implement setattr("string", None) as a special case (to - detach the associated string, if any */ - -static PyTypeObject Match_Type = { - PyVarObject_HEAD_INIT(NULL,0) - "_" SRE_MODULE ".SRE_Match", - sizeof(MatchObject), sizeof(Py_ssize_t), - (destructor)match_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)match_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - match_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - match_methods, /* tp_methods */ - match_members, /* tp_members */ - match_getset, /* tp_getset */ -}; - -static PyObject* -pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) -{ - /* create match object (from state object) */ - - MatchObject* match; - Py_ssize_t i, j; - char* base; - int n; - - if (status > 0) { - - /* create match object (with room for extra group marks) */ - /* coverity[ampersand_in_size] */ - match = PyObject_NEW_VAR(MatchObject, &Match_Type, - 2*(pattern->groups+1)); - if (!match) - return NULL; - - Py_INCREF(pattern); - match->pattern = pattern; - - Py_INCREF(state->string); - match->string = state->string; - - match->regs = NULL; - match->groups = pattern->groups+1; - - /* fill in group slices */ - - base = (char*) state->beginning; - n = state->charsize; - - match->mark[0] = ((char*) state->start - base) / n; - match->mark[1] = ((char*) state->ptr - base) / n; - - for (i = j = 0; i < pattern->groups; i++, j+=2) - if (j+1 <= state->lastmark && state->mark[j] && state->mark[j+1]) { - match->mark[j+2] = ((char*) state->mark[j] - base) / n; - match->mark[j+3] = ((char*) state->mark[j+1] - base) / n; - } else - match->mark[j+2] = match->mark[j+3] = -1; /* undefined */ - - match->pos = state->pos; - match->endpos = state->endpos; - - match->lastindex = state->lastindex; - - return (PyObject*) match; - - } else if (status == 0) { - - /* no match */ - Py_INCREF(Py_None); - return Py_None; - - } - - /* internal error */ - pattern_error(status); - return NULL; -} - - -/* -------------------------------------------------------------------- */ -/* scanner methods (experimental) */ - -static void -scanner_dealloc(ScannerObject* self) -{ - state_fini(&self->state); - Py_XDECREF(self->pattern); - PyObject_DEL(self); -} - -static PyObject* -scanner_match(ScannerObject* self, PyObject *unused) -{ - SRE_STATE* state = &self->state; - PyObject* match; - Py_ssize_t status; - - state_reset(state); - - state->ptr = state->start; - - status = sre_match(state, PatternObject_GetCode(self->pattern), 0); - if (PyErr_Occurred()) - return NULL; - - match = pattern_new_match((PatternObject*) self->pattern, - state, status); - - if (status == 0 || state->ptr == state->start) - state->start = (void*) ((char*) state->ptr + state->charsize); - else - state->start = state->ptr; - - return match; -} - - -static PyObject* -scanner_search(ScannerObject* self, PyObject *unused) -{ - SRE_STATE* state = &self->state; - PyObject* match; - Py_ssize_t status; - - state_reset(state); - - state->ptr = state->start; - - status = sre_search(state, PatternObject_GetCode(self->pattern)); - if (PyErr_Occurred()) - return NULL; - - match = pattern_new_match((PatternObject*) self->pattern, - state, status); - - if (status == 0 || state->ptr == state->start) - state->start = (void*) ((char*) state->ptr + state->charsize); - else - state->start = state->ptr; - - return match; -} - -static PyMethodDef scanner_methods[] = { - {"match", (PyCFunction) scanner_match, METH_NOARGS}, - {"search", (PyCFunction) scanner_search, METH_NOARGS}, - {NULL, NULL} -}; - -#define SCAN_OFF(x) offsetof(ScannerObject, x) -static PyMemberDef scanner_members[] = { - {"pattern", T_OBJECT, SCAN_OFF(pattern), READONLY}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject Scanner_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_" SRE_MODULE ".SRE_Scanner", - sizeof(ScannerObject), 0, - (destructor)scanner_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - scanner_methods, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ -}; - -static PyObject* -pattern_scanner(PatternObject* pattern, PyObject* args, PyObject* kw) -{ - /* create search state object */ - - ScannerObject* self; - - PyObject *string = NULL, *string2 = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - static char* kwlist[] = { "string", "pos", "endpos", "source", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Onn$O:scanner", kwlist, - &string, &start, &end, &string2)) - return NULL; - - string = fix_string_param(string, string2, "source"); - if (!string) - return NULL; - - /* create scanner object */ - self = PyObject_NEW(ScannerObject, &Scanner_Type); - if (!self) - return NULL; - self->pattern = NULL; - - string = state_init(&self->state, pattern, string, start, end); - if (!string) { - Py_DECREF(self); - return NULL; - } - - Py_INCREF(pattern); - self->pattern = (PyObject*) pattern; - - return (PyObject*) self; -} - -static PyMethodDef _functions[] = { - {"compile", _compile, METH_VARARGS}, - {"getcodesize", sre_codesize, METH_NOARGS}, - {"getlower", sre_getlower, METH_VARARGS}, - {NULL, NULL} -}; - -static struct PyModuleDef sremodule = { - PyModuleDef_HEAD_INIT, - "_" SRE_MODULE, - NULL, - -1, - _functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC PyInit__sre(void) -{ - PyObject* m; - PyObject* d; - PyObject* x; - - /* Patch object types */ - if (PyType_Ready(&Pattern_Type) || PyType_Ready(&Match_Type) || - PyType_Ready(&Scanner_Type)) - return NULL; - - m = PyModule_Create(&sremodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - - x = PyLong_FromLong(SRE_MAGIC); - if (x) { - PyDict_SetItemString(d, "MAGIC", x); - Py_DECREF(x); - } - - x = PyLong_FromLong(sizeof(SRE_CODE)); - if (x) { - PyDict_SetItemString(d, "CODESIZE", x); - Py_DECREF(x); - } - - x = PyLong_FromUnsignedLong(SRE_MAXREPEAT); - if (x) { - PyDict_SetItemString(d, "MAXREPEAT", x); - Py_DECREF(x); - } - - x = PyLong_FromUnsignedLong(SRE_MAXGROUPS); - if (x) { - PyDict_SetItemString(d, "MAXGROUPS", x); - Py_DECREF(x); - } - - x = PyUnicode_FromString(copyright); - if (x) { - PyDict_SetItemString(d, "copyright", x); - Py_DECREF(x); - } - return m; -} - -/* vim:ts=4:sw=4:et -*/ +/*[clinic end generated code: output=d1d73ab2c5008bd4 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320168=3A_Converte?= =?utf-8?q?d_the_=5Ftkinter_module_to_Argument_Clinic=2E?= Message-ID: <20150503131846.25445.18857@psf.io> https://hg.python.org/cpython/rev/b22ced894d51 changeset: 95867:b22ced894d51 user: Serhiy Storchaka date: Sun May 03 15:49:47 2015 +0300 summary: Issue #20168: Converted the _tkinter module to Argument Clinic. files: Modules/_tkinter.c | 663 +++-- Modules/_tkinter.c | 3930 ++++--------------------------- 2 files changed, 1017 insertions(+), 3576 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -509,6 +509,14 @@ } +/*[clinic input] +module _tkinter +class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec" +class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec" +class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/ + /**** Tkapp Object ****/ #ifndef WITH_APPINIT @@ -1489,16 +1497,21 @@ } +/*[clinic input] +_tkinter.tkapp.eval + + script: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_Eval(PyObject *self, PyObject *args) +_tkinter_tkapp_eval_impl(TkappObject *self, const char *script) +/*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/ { - char *script; PyObject *res = NULL; int err; - if (!PyArg_ParseTuple(args, "s:eval", &script)) - return NULL; - CHECK_STRING_LENGTH(script); CHECK_TCL_APPARTMENT; @@ -1506,23 +1519,28 @@ err = Tcl_Eval(Tkapp_Interp(self), script); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.evalfile + + fileName: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_EvalFile(PyObject *self, PyObject *args) +_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName) +/*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/ { - char *fileName; PyObject *res = NULL; int err; - if (!PyArg_ParseTuple(args, "s:evalfile", &fileName)) - return NULL; - CHECK_STRING_LENGTH(fileName); CHECK_TCL_APPARTMENT; @@ -1530,23 +1548,28 @@ err = Tcl_EvalFile(Tkapp_Interp(self), fileName); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.record + + script: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_Record(PyObject *self, PyObject *args) +_tkinter_tkapp_record_impl(TkappObject *self, const char *script) +/*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/ { - char *script; PyObject *res = NULL; int err; - if (!PyArg_ParseTuple(args, "s:record", &script)) - return NULL; - CHECK_STRING_LENGTH(script); CHECK_TCL_APPARTMENT; @@ -1554,20 +1577,25 @@ err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.adderrinfo + + msg: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_AddErrorInfo(PyObject *self, PyObject *args) +_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg) +/*[clinic end generated code: output=0e222ee2050eb357 input=4971399317d4c136]*/ { - char *msg; - - if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg)) - return NULL; CHECK_STRING_LENGTH(msg); CHECK_TCL_APPARTMENT; @@ -1600,6 +1628,15 @@ } VarEvent; #endif +/*[python] + +class varname_converter(CConverter): + type = 'const char *' + converter = 'varname_converter' + +[python]*/ +/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + static int varname_converter(PyObject *in, void *_out) { @@ -1876,26 +1913,33 @@ /** Tcl to Python **/ +/*[clinic input] +_tkinter.tkapp.getint + + arg: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_GetInt(PyObject *self, PyObject *args) +_tkinter_tkapp_getint(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/ { char *s; Tcl_Obj *value; PyObject *result; - if (PyTuple_Size(args) == 1) { - PyObject* o = PyTuple_GetItem(args, 0); - if (PyLong_Check(o)) { - Py_INCREF(o); - return o; - } + if (PyLong_Check(arg)) { + Py_INCREF(arg); + return arg; } - if (!PyArg_ParseTuple(args, "s:getint", &s)) + + if (!PyArg_Parse(arg, "s:getint", &s)) return NULL; CHECK_STRING_LENGTH(s); value = Tcl_NewStringObj(s, -1); if (value == NULL) - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); /* Don't use Tcl_GetInt() because it returns ambiguous result for value in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). @@ -1903,39 +1947,55 @@ value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). */ #ifdef HAVE_LIBTOMMAMTH - result = fromBignumObj(self, value); + result = fromBignumObj((PyObject *)self, value); #else - result = fromWideIntObj(self, value); + result = fromWideIntObj((PyObject *)self, value); #endif Tcl_DecrRefCount(value); if (result != NULL || PyErr_Occurred()) return result; - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); } +/*[clinic input] +_tkinter.tkapp.getdouble + + arg: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_GetDouble(PyObject *self, PyObject *args) +_tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/ { char *s; double v; - if (PyTuple_Size(args) == 1) { - PyObject *o = PyTuple_GetItem(args, 0); - if (PyFloat_Check(o)) { - Py_INCREF(o); - return o; - } + if (PyFloat_Check(arg)) { + Py_INCREF(arg); + return arg; } - if (!PyArg_ParseTuple(args, "s:getdouble", &s)) + + if (!PyArg_Parse(arg, "s:getdouble", &s)) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); return Py_BuildValue("d", v); } +/*[clinic input] +_tkinter.tkapp.getboolean + + arg: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_GetBoolean(PyObject *self, PyObject *arg) +_tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/ { char *s; int v; @@ -1948,7 +2008,7 @@ if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), ((PyTclObject*)arg)->value, &v) == TCL_ERROR) - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); return PyBool_FromLong(v); } @@ -1956,20 +2016,25 @@ return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); return PyBool_FromLong(v); } +/*[clinic input] +_tkinter.tkapp.exprstring + + s: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_ExprString(PyObject *self, PyObject *args) +_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s) +/*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/ { - char *s; PyObject *res = NULL; int retval; - if (!PyArg_ParseTuple(args, "s:exprstring", &s)) - return NULL; - CHECK_STRING_LENGTH(s); CHECK_TCL_APPARTMENT; @@ -1977,24 +2042,29 @@ retval = Tcl_ExprString(Tkapp_Interp(self), s); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.exprlong + + s: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_ExprLong(PyObject *self, PyObject *args) +_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s) +/*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/ { - char *s; PyObject *res = NULL; int retval; long v; - if (!PyArg_ParseTuple(args, "s:exprlong", &s)) - return NULL; - CHECK_STRING_LENGTH(s); CHECK_TCL_APPARTMENT; @@ -2002,23 +2072,29 @@ retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = Py_BuildValue("l", v); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.exprdouble + + s: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_ExprDouble(PyObject *self, PyObject *args) +_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s) +/*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/ { - char *s; PyObject *res = NULL; double v; int retval; - if (!PyArg_ParseTuple(args, "s:exprdouble", &s)) - return NULL; CHECK_STRING_LENGTH(s); CHECK_TCL_APPARTMENT; PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0) @@ -2027,30 +2103,36 @@ ENTER_OVERLAP PyFPE_END_PROTECT(retval) if (retval == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = Py_BuildValue("d", v); LEAVE_OVERLAP_TCL return res; } +/*[clinic input] +_tkinter.tkapp.exprboolean + + s: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_ExprBoolean(PyObject *self, PyObject *args) +_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s) +/*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/ { - char *s; PyObject *res = NULL; int retval; int v; - if (!PyArg_ParseTuple(args, "s:exprboolean", &s)) - return NULL; CHECK_STRING_LENGTH(s); CHECK_TCL_APPARTMENT; ENTER_TCL retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error(self); + res = Tkinter_Error((PyObject *)self); else res = Py_BuildValue("i", v); LEAVE_OVERLAP_TCL @@ -2059,29 +2141,36 @@ +/*[clinic input] +_tkinter.tkapp.splitlist + + arg: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_SplitList(PyObject *self, PyObject *args) +_tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/ { char *list; int argc; const char **argv; - PyObject *arg, *v; + PyObject *v; int i; - if (!PyArg_ParseTuple(args, "O:splitlist", &arg)) - return NULL; if (PyTclObject_Check(arg)) { int objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(Tkapp_Interp(self), ((PyTclObject*)arg)->value, &objc, &objv) == TCL_ERROR) { - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); } if (!(v = PyTuple_New(objc))) return NULL; for (i = 0; i < objc; i++) { - PyObject *s = FromObj(self, objv[i]); + PyObject *s = FromObj((PyObject*)self, objv[i]); if (!s || PyTuple_SetItem(v, i, s)) { Py_DECREF(v); return NULL; @@ -2097,14 +2186,14 @@ return PySequence_Tuple(arg); } - if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list)) + if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list)) return NULL; CHECK_STRING_LENGTH(list); if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR) { PyMem_Free(list); - return Tkinter_Error(self); + return Tkinter_Error((PyObject *)self); } if (!(v = PyTuple_New(argc))) @@ -2125,14 +2214,21 @@ return v; } +/*[clinic input] +_tkinter.tkapp.split + + arg: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_Split(PyObject *self, PyObject *args) +_tkinter_tkapp_split(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/ { - PyObject *arg, *v; + PyObject *v; char *list; - if (!PyArg_ParseTuple(args, "O:split", &arg)) - return NULL; if (PyTclObject_Check(arg)) { Tcl_Obj *value = ((PyTclObject*)arg)->value; int objc; @@ -2140,16 +2236,16 @@ int i; if (Tcl_ListObjGetElements(Tkapp_Interp(self), value, &objc, &objv) == TCL_ERROR) { - return FromObj(self, value); + return FromObj((PyObject*)self, value); } if (objc == 0) return PyUnicode_FromString(""); if (objc == 1) - return FromObj(self, objv[0]); + return FromObj((PyObject*)self, objv[0]); if (!(v = PyTuple_New(objc))) return NULL; for (i = 0; i < objc; i++) { - PyObject *s = FromObj(self, objv[i]); + PyObject *s = FromObj((PyObject*)self, objv[i]); if (!s || PyTuple_SetItem(v, i, s)) { Py_DECREF(v); return NULL; @@ -2160,7 +2256,7 @@ if (PyTuple_Check(arg) || PyList_Check(arg)) return SplitObj(arg); - if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list)) + if (!PyArg_Parse(arg, "et:split", "utf-8", &list)) return NULL; CHECK_STRING_LENGTH(list); v = Split(list); @@ -2260,7 +2356,7 @@ typedef struct CommandEvent{ Tcl_Event ev; Tcl_Interp* interp; - char *name; + const char *name; int create; int *status; ClientData *data; @@ -2283,18 +2379,25 @@ } #endif +/*[clinic input] +_tkinter.tkapp.createcommand + + self: self(type="TkappObject *") + name: str + func: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) +_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name, + PyObject *func) +/*[clinic end generated code: output=2a1c79a4ee2af410 input=2bc2c046a0914234]*/ { - TkappObject *self = (TkappObject*)selfptr; PythonCmd_ClientData *data; - char *cmdName; - PyObject *func; int err; - if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func)) - return NULL; - CHECK_STRING_LENGTH(cmdName); + CHECK_STRING_LENGTH(name); if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "command not callable"); return NULL; @@ -2311,7 +2414,7 @@ return PyErr_NoMemory(); Py_INCREF(self); Py_INCREF(func); - data->self = selfptr; + data->self = (PyObject *) self; data->func = func; #ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { @@ -2325,7 +2428,7 @@ ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; ev->interp = self->interp; ev->create = 1; - ev->name = cmdName; + ev->name = name; ev->data = (ClientData)data; ev->status = &err; ev->done = &cond; @@ -2337,7 +2440,7 @@ { ENTER_TCL err = Tcl_CreateCommand( - Tkapp_Interp(self), cmdName, PythonCmd, + Tkapp_Interp(self), name, PythonCmd, (ClientData)data, PythonCmdDelete) == NULL; LEAVE_TCL } @@ -2352,16 +2455,22 @@ +/*[clinic input] +_tkinter.tkapp.deletecommand + + self: self(type="TkappObject *") + name: str + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args) +_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name) +/*[clinic end generated code: output=a67e8cb5845e0d2d input=b6306468f10b219c]*/ { - TkappObject *self = (TkappObject*)selfptr; - char *cmdName; int err; - if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) - return NULL; - CHECK_STRING_LENGTH(cmdName); + CHECK_STRING_LENGTH(name); #ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { @@ -2375,7 +2484,7 @@ ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; ev->interp = self->interp; ev->create = 0; - ev->name = cmdName; + ev->name = name; ev->status = &err; ev->done = &cond; Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, @@ -2386,7 +2495,7 @@ #endif { ENTER_TCL - err = Tcl_DeleteCommand(self->interp, cmdName); + err = Tcl_DeleteCommand(self->interp, name); LEAVE_TCL } if (err == -1) { @@ -2467,17 +2576,23 @@ LEAVE_PYTHON } +/*[clinic input] +_tkinter.tkapp.createfilehandler + + file: object + mask: int + func: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_CreateFileHandler(PyObject *self, PyObject *args) - /* args is (file, mask, func) */ +_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file, + int mask, PyObject *func) +/*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/ { FileHandler_ClientData *data; - PyObject *file, *func; - int mask, tfile; - - if (!PyArg_ParseTuple(args, "OiO:createfilehandler", - &file, &mask, &func)) - return NULL; + int tfile; CHECK_TCL_APPARTMENT; @@ -2500,15 +2615,20 @@ Py_RETURN_NONE; } +/*[clinic input] +_tkinter.tkapp.deletefilehandler + + file: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_DeleteFileHandler(PyObject *self, PyObject *args) +_tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file) +/*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/ { - PyObject *file; int tfile; - if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file)) - return NULL; - CHECK_TCL_APPARTMENT; tfile = PyObject_AsFileDescriptor(file); @@ -2536,14 +2656,20 @@ PyObject *func; } TkttObject; +/*[clinic input] +_tkinter.tktimertoken.deletetimerhandler + + self: self(type="TkttObject *") + +[clinic start generated code]*/ + static PyObject * -Tktt_DeleteTimerHandler(PyObject *self, PyObject *args) +_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self) +/*[clinic end generated code: output=bd7fe17f328cfa55 input=25ba5dd594e52084]*/ { - TkttObject *v = (TkttObject *)self; + TkttObject *v = self; PyObject *func = v->func; - if (!PyArg_ParseTuple(args, ":deletetimerhandler")) - return NULL; if (v->token != NULL) { Tcl_DeleteTimerHandler(v->token); v->token = NULL; @@ -2556,11 +2682,7 @@ Py_RETURN_NONE; } -static PyMethodDef Tktt_methods[] = -{ - {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS}, - {NULL, NULL} -}; +static PyMethodDef Tktt_methods[]; static TkttObject * Tktt_New(PyObject *func) @@ -2649,16 +2771,22 @@ LEAVE_PYTHON } +/*[clinic input] +_tkinter.tkapp.createtimerhandler + + milliseconds: int + func: object + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_CreateTimerHandler(PyObject *self, PyObject *args) +_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds, + PyObject *func) +/*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/ { - int milliseconds; - PyObject *func; TkttObject *v; - if (!PyArg_ParseTuple(args, "iO:createtimerhandler", - &milliseconds, &func)) - return NULL; if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "bad argument list"); return NULL; @@ -2678,18 +2806,23 @@ /** Event Loop **/ +/*[clinic input] +_tkinter.tkapp.mainloop + + self: self(type="TkappObject *") + threshold: int = 0 + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_MainLoop(PyObject *selfptr, PyObject *args) +_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold) +/*[clinic end generated code: output=0ba8eabbe57841b0 input=ad57c9c1dd2b9470]*/ { - int threshold = 0; - TkappObject *self = (TkappObject*)selfptr; #ifdef WITH_THREAD PyThreadState *tstate = PyThreadState_Get(); #endif - if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold)) - return NULL; - CHECK_TCL_APPARTMENT; self->dispatching = 1; @@ -2741,44 +2874,56 @@ Py_RETURN_NONE; } +/*[clinic input] +_tkinter.tkapp.dooneevent + + flags: int = 0 + / + +[clinic start generated code]*/ + static PyObject * -Tkapp_DoOneEvent(PyObject *self, PyObject *args) +_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags) +/*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/ { - int flags = 0; int rv; - if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags)) - return NULL; - ENTER_TCL rv = Tcl_DoOneEvent(flags); LEAVE_TCL return Py_BuildValue("i", rv); } +/*[clinic input] +_tkinter.tkapp.quit +[clinic start generated code]*/ + static PyObject * -Tkapp_Quit(PyObject *self, PyObject *args) +_tkinter_tkapp_quit_impl(TkappObject *self) +/*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/ { - - if (!PyArg_ParseTuple(args, ":quit")) - return NULL; - quitMainLoop = 1; Py_RETURN_NONE; } +/*[clinic input] +_tkinter.tkapp.interpaddr +[clinic start generated code]*/ + static PyObject * -Tkapp_InterpAddr(PyObject *self, PyObject *args) +_tkinter_tkapp_interpaddr_impl(TkappObject *self) +/*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/ { - - if (!PyArg_ParseTuple(args, ":interpaddr")) - return NULL; - return PyLong_FromVoidPtr(Tkapp_Interp(self)); } +/*[clinic input] +_tkinter.tkapp.loadtk +[clinic start generated code]*/ + static PyObject * -Tkapp_TkInit(PyObject *self, PyObject *args) +_tkinter_tkapp_loadtk_impl(TkappObject *self) +/*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/ { Tcl_Interp *interp = Tkapp_Interp(self); const char * _tk_exists = NULL; @@ -2804,7 +2949,7 @@ if (err == TCL_ERROR) { /* This sets an exception, but we cannot return right away because we need to exit the overlap first. */ - Tkinter_Error(self); + Tkinter_Error((PyObject *)self); } else { _tk_exists = Tkapp_Result(self); } @@ -2839,11 +2984,18 @@ Py_RETURN_NONE; } +/*[clinic input] +_tkinter.tkapp.willdispatch + + self: self(type="TkappObject *") + +[clinic start generated code]*/ + static PyObject * -Tkapp_WillDispatch(PyObject *self, PyObject *args) +_tkinter_tkapp_willdispatch_impl(TkappObject *self) +/*[clinic end generated code: output=0e3f46d244642155 input=2630699767808970]*/ { - - ((TkappObject*)self)->dispatching = 1; + self->dispatching = 1; Py_RETURN_NONE; } @@ -2851,45 +3003,7 @@ /**** Tkapp Method List ****/ -static PyMethodDef Tkapp_methods[] = -{ - {"willdispatch", Tkapp_WillDispatch, METH_NOARGS}, - {"wantobjects", Tkapp_WantObjects, METH_VARARGS}, - {"call", Tkapp_Call, METH_VARARGS}, - {"eval", Tkapp_Eval, METH_VARARGS}, - {"evalfile", Tkapp_EvalFile, METH_VARARGS}, - {"record", Tkapp_Record, METH_VARARGS}, - {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS}, - {"setvar", Tkapp_SetVar, METH_VARARGS}, - {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS}, - {"getvar", Tkapp_GetVar, METH_VARARGS}, - {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS}, - {"unsetvar", Tkapp_UnsetVar, METH_VARARGS}, - {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, - {"getint", Tkapp_GetInt, METH_VARARGS}, - {"getdouble", Tkapp_GetDouble, METH_VARARGS}, - {"getboolean", Tkapp_GetBoolean, METH_O}, - {"exprstring", Tkapp_ExprString, METH_VARARGS}, - {"exprlong", Tkapp_ExprLong, METH_VARARGS}, - {"exprdouble", Tkapp_ExprDouble, METH_VARARGS}, - {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS}, - {"splitlist", Tkapp_SplitList, METH_VARARGS}, - {"split", Tkapp_Split, METH_VARARGS}, - {"createcommand", Tkapp_CreateCommand, METH_VARARGS}, - {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS}, -#ifdef HAVE_CREATEFILEHANDLER - {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS}, - {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS}, -#endif - {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS}, - {"mainloop", Tkapp_MainLoop, METH_VARARGS}, - {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS}, - {"quit", Tkapp_Quit, METH_VARARGS}, - {"interpaddr", Tkapp_InterpAddr, METH_VARARGS}, - {"loadtk", Tkapp_TkInit, METH_NOARGS}, - {NULL, NULL} -}; - +static PyMethodDef Tkapp_methods[]; /**** Tkapp Type Methods ****/ @@ -2987,14 +3101,19 @@ return 1; } +/*[clinic input] +_tkinter._flatten + + item: object + / + +[clinic start generated code]*/ + static PyObject * -Tkinter_Flatten(PyObject* self, PyObject* args) +_tkinter__flatten(PyModuleDef *module, PyObject *item) +/*[clinic end generated code: output=9505049ec74c3480 input=6b9c12260aa1157f]*/ { FlattenContext context; - PyObject* item; - - if (!PyArg_ParseTuple(args, "O:_flatten", &item)) - return NULL; context.maxsize = PySequence_Size(item); if (context.maxsize < 0) @@ -3017,26 +3136,33 @@ return context.tuple; } +/*[clinic input] +_tkinter.create + + screenName: str(nullable=True) = NULL + baseName: str = NULL + className: str = "Tk" + interactive: int(c_default="0") = False + wantobjects: int(c_default="0") = False + wantTk: int(c_default="1") = True + if false, then Tk_Init() doesn't get called + sync: int(c_default="0") = False + if true, then pass -sync to wish + use: str(nullable=True) = NULL + if not None, then pass -use to wish + / + +[clinic start generated code]*/ + static PyObject * -Tkinter_Create(PyObject *self, PyObject *args) +_tkinter_create_impl(PyModuleDef *module, const char *screenName, + const char *baseName, const char *className, + int interactive, int wantobjects, int wantTk, int sync, + const char *use) +/*[clinic end generated code: output=b8847800fc3b27eb input=c133c59a99dd0086]*/ { - char *screenName = NULL; - char *baseName = NULL; /* XXX this is not used anymore; - try getting rid of it. */ - char *className = NULL; - int interactive = 0; - int wantobjects = 1; - int wantTk = 1; /* If false, then Tk_Init() doesn't get called */ - int sync = 0; /* pass -sync to wish */ - char *use = NULL; /* pass -use to wish */ - - className = "Tk"; - - if (!PyArg_ParseTuple(args, "|zssiiiiz:create", - &screenName, &baseName, &className, - &interactive, &wantobjects, &wantTk, - &sync, &use)) - return NULL; + /* XXX baseName is not used anymore; + * try getting rid of it. */ CHECK_STRING_LENGTH(screenName); CHECK_STRING_LENGTH(baseName); CHECK_STRING_LENGTH(className); @@ -3047,12 +3173,21 @@ sync, use); } +/*[clinic input] +_tkinter.setbusywaitinterval + + new_val: int + / + +Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter. + +It should be set to a divisor of the maximum time between frames in an animation. +[clinic start generated code]*/ + static PyObject * -Tkinter_setbusywaitinterval(PyObject *self, PyObject *args) +_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val) +/*[clinic end generated code: output=0b9d7ef7940461ea input=deca1d6f9e6dae47]*/ { - int new_val; - if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val)) - return NULL; if (new_val < 0) { PyErr_SetString(PyExc_ValueError, "busywaitinterval must be >= 0"); @@ -3062,34 +3197,70 @@ Py_RETURN_NONE; } -static char setbusywaitinterval_doc[] = -"setbusywaitinterval(n) -> None\n\ -\n\ -Set the busy-wait interval in milliseconds between successive\n\ -calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\ -It should be set to a divisor of the maximum time between\n\ -frames in an animation."; - -static PyObject * -Tkinter_getbusywaitinterval(PyObject *self, PyObject *args) +/*[clinic input] +_tkinter.getbusywaitinterval -> int + +Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter. +[clinic start generated code]*/ + +static int +_tkinter_getbusywaitinterval_impl(PyModuleDef *module) +/*[clinic end generated code: output=9d09eee026e96971 input=a695878d2d576a84]*/ { - return PyLong_FromLong(Tkinter_busywaitinterval); + return Tkinter_busywaitinterval; } -static char getbusywaitinterval_doc[] = -"getbusywaitinterval() -> int\n\ -\n\ -Return the current busy-wait interval between successive\n\ -calls to Tcl_DoOneEvent in a threaded Python interpreter."; +#include "clinic/_tkinter.c.h" + +static PyMethodDef Tktt_methods[] = +{ + _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF + {NULL, NULL} +}; + +static PyMethodDef Tkapp_methods[] = +{ + _TKINTER_TKAPP_WILLDISPATCH_METHODDEF + {"wantobjects", Tkapp_WantObjects, METH_VARARGS}, + {"call", Tkapp_Call, METH_VARARGS}, + _TKINTER_TKAPP_EVAL_METHODDEF + _TKINTER_TKAPP_EVALFILE_METHODDEF + _TKINTER_TKAPP_RECORD_METHODDEF + _TKINTER_TKAPP_ADDERRINFO_METHODDEF + {"setvar", Tkapp_SetVar, METH_VARARGS}, + {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS}, + {"getvar", Tkapp_GetVar, METH_VARARGS}, + {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS}, + {"unsetvar", Tkapp_UnsetVar, METH_VARARGS}, + {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, + _TKINTER_TKAPP_GETINT_METHODDEF + _TKINTER_TKAPP_GETDOUBLE_METHODDEF + _TKINTER_TKAPP_GETBOOLEAN_METHODDEF + _TKINTER_TKAPP_EXPRSTRING_METHODDEF + _TKINTER_TKAPP_EXPRLONG_METHODDEF + _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF + _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF + _TKINTER_TKAPP_SPLITLIST_METHODDEF + _TKINTER_TKAPP_SPLIT_METHODDEF + _TKINTER_TKAPP_CREATECOMMAND_METHODDEF + _TKINTER_TKAPP_DELETECOMMAND_METHODDEF + _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF + _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF + _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF + _TKINTER_TKAPP_MAINLOOP_METHODDEF + _TKINTER_TKAPP_DOONEEVENT_METHODDEF + _TKINTER_TKAPP_QUIT_METHODDEF + _TKINTER_TKAPP_INTERPADDR_METHODDEF + _TKINTER_TKAPP_LOADTK_METHODDEF + {NULL, NULL} +}; static PyMethodDef moduleMethods[] = { - {"_flatten", Tkinter_Flatten, METH_VARARGS}, - {"create", Tkinter_Create, METH_VARARGS}, - {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS, - setbusywaitinterval_doc}, - {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval, - METH_NOARGS, getbusywaitinterval_doc}, + _TKINTER__FLATTEN_METHODDEF + _TKINTER_CREATE_METHODDEF + _TKINTER_SETBUSYWAITINTERVAL_METHODDEF + _TKINTER_GETBUSYWAITINTERVAL_METHODDEF {NULL, NULL} }; diff --git a/Modules/_tkinter.c b/Modules/clinic/_tkinter.c.h copy from Modules/_tkinter.c copy to Modules/clinic/_tkinter.c.h --- a/Modules/_tkinter.c +++ b/Modules/clinic/_tkinter.c.h @@ -1,3354 +1,624 @@ -/*********************************************************** -Copyright (C) 1994 Steen Lumholt. +/*[clinic input] +preserve +[clinic start generated code]*/ - All Rights Reserved +PyDoc_STRVAR(_tkinter_tkapp_eval__doc__, +"eval($self, script, /)\n" +"--\n" +"\n"); -******************************************************************/ - -/* _tkinter.c -- Interface to libtk.a and libtcl.a. */ - -/* TCL/TK VERSION INFO: - - Only Tcl/Tk 8.4 and later are supported. Older versions are not - supported. Use Python 3.4 or older if you cannot upgrade your - Tcl/Tk libraries. -*/ - -/* XXX Further speed-up ideas, involving Tcl 8.0 features: - - - Register a new Tcl type, "Python callable", which can be called more - efficiently and passed to Tcl_EvalObj() directly (if this is possible). - -*/ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include - -#ifdef WITH_THREAD -#include "pythread.h" -#endif - -#ifdef MS_WINDOWS -#include -#endif - -#define CHECK_SIZE(size, elemsize) \ - ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize))) - -/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define - it always; if Tcl is not threaded, the thread functions in - Tcl are empty. */ -#define TCL_THREADS - -#ifdef TK_FRAMEWORK -#include -#include -#else -#include -#include -#endif - -#include "tkinter.h" - -#if TK_HEX_VERSION < 0x08040200 -#error "Tk older than 8.4 not supported" -#endif - -#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \ - TK_HEX_VERSION >= 0x08060200 -#define HAVE_LIBTOMMAMTH -#include -#endif - -#if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) -#define HAVE_CREATEFILEHANDLER -#endif - -#ifdef HAVE_CREATEFILEHANDLER - -/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere - with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */ -#ifndef TCL_UNIX_FD -# ifdef TCL_WIN_SOCKET -# define TCL_UNIX_FD (! TCL_WIN_SOCKET) -# else -# define TCL_UNIX_FD 1 -# endif -#endif - -/* Tcl_CreateFileHandler() changed several times; these macros deal with the - messiness. In Tcl 8.0 and later, it is not available on Windows (and on - Unix, only because Jack added it back); when available on Windows, it only - applies to sockets. */ - -#ifdef MS_WINDOWS -#define FHANDLETYPE TCL_WIN_SOCKET -#else -#define FHANDLETYPE TCL_UNIX_FD -#endif - -/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine - which uses this to handle Tcl events while the user is typing commands. */ - -#if FHANDLETYPE == TCL_UNIX_FD -#define WAIT_FOR_STDIN -#endif - -#endif /* HAVE_CREATEFILEHANDLER */ - -#ifdef MS_WINDOWS -#include -#define WAIT_FOR_STDIN -#endif - -#ifdef WITH_THREAD - -/* The threading situation is complicated. Tcl is not thread-safe, except - when configured with --enable-threads. - - So we need to use a lock around all uses of Tcl. Previously, the - Python interpreter lock was used for this. However, this causes - problems when other Python threads need to run while Tcl is blocked - waiting for events. - - To solve this problem, a separate lock for Tcl is introduced. - Holding it is incompatible with holding Python's interpreter lock. - The following four macros manipulate both locks together. - - ENTER_TCL and LEAVE_TCL are brackets, just like - Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be - used whenever a call into Tcl is made that could call an event - handler, or otherwise affect the state of a Tcl interpreter. These - assume that the surrounding code has the Python interpreter lock; - inside the brackets, the Python interpreter lock has been released - and the lock for Tcl has been acquired. - - Sometimes, it is necessary to have both the Python lock and the Tcl - lock. (For example, when transferring data from the Tcl - interpreter result to a Python string object.) This can be done by - using different macros to close the ENTER_TCL block: ENTER_OVERLAP - reacquires the Python lock (and restores the thread state) but - doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl - lock. - - By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event - handlers when the handler needs to use Python. Such event handlers - are entered while the lock for Tcl is held; the event handler - presumably needs to use Python. ENTER_PYTHON releases the lock for - Tcl and acquires the Python interpreter lock, restoring the - appropriate thread state, and LEAVE_PYTHON releases the Python - interpreter lock and re-acquires the lock for Tcl. It is okay for - ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between - ENTER_PYTHON and LEAVE_PYTHON. - - These locks expand to several statements and brackets; they should - not be used in branches of if statements and the like. - - If Tcl is threaded, this approach won't work anymore. The Tcl - interpreter is only valid in the thread that created it, and all Tk - activity must happen in this thread, also. That means that the - mainloop must be invoked in the thread that created the - interpreter. Invoking commands from other threads is possible; - _tkinter will queue an event for the interpreter thread, which will - then execute the command and pass back the result. If the main - thread is not in the mainloop, and invoking commands causes an - exception; if the main loop is running but not processing events, - the command invocation will block. - - In addition, for a threaded Tcl, a single global tcl_tstate won't - be sufficient anymore, since multiple Tcl interpreters may - simultaneously dispatch in different threads. So we use the Tcl TLS - API. - -*/ - -static PyThread_type_lock tcl_lock = 0; - -#ifdef TCL_THREADS -static Tcl_ThreadDataKey state_key; -typedef PyThreadState *ThreadSpecificData; -#define tcl_tstate \ - (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*))) -#else -static PyThreadState *tcl_tstate = NULL; -#endif - -#define ENTER_TCL \ - { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \ - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; - -#define LEAVE_TCL \ - tcl_tstate = NULL; \ - if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS} - -#define ENTER_OVERLAP \ - Py_END_ALLOW_THREADS - -#define LEAVE_OVERLAP_TCL \ - tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); } - -#define ENTER_PYTHON \ - { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \ - if(tcl_lock) \ - PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); } - -#define LEAVE_PYTHON \ - { PyThreadState *tstate = PyEval_SaveThread(); \ - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; } - -#define CHECK_TCL_APPARTMENT \ - if (((TkappObject *)self)->threaded && \ - ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \ - PyErr_SetString(PyExc_RuntimeError, \ - "Calling Tcl from different appartment"); \ - return 0; \ - } - -#else - -#define ENTER_TCL -#define LEAVE_TCL -#define ENTER_OVERLAP -#define LEAVE_OVERLAP_TCL -#define ENTER_PYTHON -#define LEAVE_PYTHON -#define CHECK_TCL_APPARTMENT - -#endif - -#ifndef FREECAST -#define FREECAST (char *) -#endif - -/**** Tkapp Object Declaration ****/ - -static PyObject *Tkapp_Type; - -typedef struct { - PyObject_HEAD - Tcl_Interp *interp; - int wantobjects; - int threaded; /* True if tcl_platform[threaded] */ - Tcl_ThreadId thread_id; - int dispatching; - /* We cannot include tclInt.h, as this is internal. - So we cache interesting types here. */ - const Tcl_ObjType *OldBooleanType; - const Tcl_ObjType *BooleanType; - const Tcl_ObjType *ByteArrayType; - const Tcl_ObjType *DoubleType; - const Tcl_ObjType *IntType; - const Tcl_ObjType *WideIntType; - const Tcl_ObjType *BignumType; - const Tcl_ObjType *ListType; - const Tcl_ObjType *ProcBodyType; - const Tcl_ObjType *StringType; -} TkappObject; - -#define Tkapp_Interp(v) (((TkappObject *) (v))->interp) -#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v)) - -#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \ -(void *) v, Py_REFCNT(v))) - - - -/**** Error Handling ****/ - -static PyObject *Tkinter_TclError; -static int quitMainLoop = 0; -static int errorInCmd = 0; -static PyObject *excInCmd; -static PyObject *valInCmd; -static PyObject *trbInCmd; - -#ifdef TKINTER_PROTECT_LOADTK -static int tk_load_failed = 0; -#endif - +#define _TKINTER_TKAPP_EVAL_METHODDEF \ + {"eval", (PyCFunction)_tkinter_tkapp_eval, METH_O, _tkinter_tkapp_eval__doc__}, static PyObject * -Tkinter_Error(PyObject *v) +_tkinter_tkapp_eval_impl(TkappObject *self, const char *script); + +static PyObject * +_tkinter_tkapp_eval(TkappObject *self, PyObject *arg) { - PyErr_SetString(Tkinter_TclError, Tkapp_Result(v)); - return NULL; + PyObject *return_value = NULL; + const char *script; + + if (!PyArg_Parse(arg, "s:eval", &script)) + goto exit; + return_value = _tkinter_tkapp_eval_impl(self, script); + +exit: + return return_value; } +PyDoc_STRVAR(_tkinter_tkapp_evalfile__doc__, +"evalfile($self, fileName, /)\n" +"--\n" +"\n"); +#define _TKINTER_TKAPP_EVALFILE_METHODDEF \ + {"evalfile", (PyCFunction)_tkinter_tkapp_evalfile, METH_O, _tkinter_tkapp_evalfile__doc__}, -/**** Utils ****/ +static PyObject * +_tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName); -static int Tkinter_busywaitinterval = 20; +static PyObject * +_tkinter_tkapp_evalfile(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *fileName; -#ifdef WITH_THREAD -#ifndef MS_WINDOWS + if (!PyArg_Parse(arg, "s:evalfile", &fileName)) + goto exit; + return_value = _tkinter_tkapp_evalfile_impl(self, fileName); -/* Millisecond sleep() for Unix platforms. */ +exit: + return return_value; +} -static void -Sleep(int milli) +PyDoc_STRVAR(_tkinter_tkapp_record__doc__, +"record($self, script, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_RECORD_METHODDEF \ + {"record", (PyCFunction)_tkinter_tkapp_record, METH_O, _tkinter_tkapp_record__doc__}, + +static PyObject * +_tkinter_tkapp_record_impl(TkappObject *self, const char *script); + +static PyObject * +_tkinter_tkapp_record(TkappObject *self, PyObject *arg) { - /* XXX Too bad if you don't have select(). */ - struct timeval t; - t.tv_sec = milli/1000; - t.tv_usec = (milli%1000) * 1000; - select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t); + PyObject *return_value = NULL; + const char *script; + + if (!PyArg_Parse(arg, "s:record", &script)) + goto exit; + return_value = _tkinter_tkapp_record_impl(self, script); + +exit: + return return_value; } -#endif /* MS_WINDOWS */ -/* Wait up to 1s for the mainloop to come up. */ +PyDoc_STRVAR(_tkinter_tkapp_adderrinfo__doc__, +"adderrinfo($self, msg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_ADDERRINFO_METHODDEF \ + {"adderrinfo", (PyCFunction)_tkinter_tkapp_adderrinfo, METH_O, _tkinter_tkapp_adderrinfo__doc__}, + +static PyObject * +_tkinter_tkapp_adderrinfo_impl(TkappObject *self, const char *msg); + +static PyObject * +_tkinter_tkapp_adderrinfo(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *msg; + + if (!PyArg_Parse(arg, "s:adderrinfo", &msg)) + goto exit; + return_value = _tkinter_tkapp_adderrinfo_impl(self, msg); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_getint__doc__, +"getint($self, arg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_GETINT_METHODDEF \ + {"getint", (PyCFunction)_tkinter_tkapp_getint, METH_O, _tkinter_tkapp_getint__doc__}, + +PyDoc_STRVAR(_tkinter_tkapp_getdouble__doc__, +"getdouble($self, arg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_GETDOUBLE_METHODDEF \ + {"getdouble", (PyCFunction)_tkinter_tkapp_getdouble, METH_O, _tkinter_tkapp_getdouble__doc__}, + +PyDoc_STRVAR(_tkinter_tkapp_getboolean__doc__, +"getboolean($self, arg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_GETBOOLEAN_METHODDEF \ + {"getboolean", (PyCFunction)_tkinter_tkapp_getboolean, METH_O, _tkinter_tkapp_getboolean__doc__}, + +PyDoc_STRVAR(_tkinter_tkapp_exprstring__doc__, +"exprstring($self, s, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_EXPRSTRING_METHODDEF \ + {"exprstring", (PyCFunction)_tkinter_tkapp_exprstring, METH_O, _tkinter_tkapp_exprstring__doc__}, + +static PyObject * +_tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s); + +static PyObject * +_tkinter_tkapp_exprstring(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *s; + + if (!PyArg_Parse(arg, "s:exprstring", &s)) + goto exit; + return_value = _tkinter_tkapp_exprstring_impl(self, s); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_exprlong__doc__, +"exprlong($self, s, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_EXPRLONG_METHODDEF \ + {"exprlong", (PyCFunction)_tkinter_tkapp_exprlong, METH_O, _tkinter_tkapp_exprlong__doc__}, + +static PyObject * +_tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s); + +static PyObject * +_tkinter_tkapp_exprlong(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *s; + + if (!PyArg_Parse(arg, "s:exprlong", &s)) + goto exit; + return_value = _tkinter_tkapp_exprlong_impl(self, s); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_exprdouble__doc__, +"exprdouble($self, s, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF \ + {"exprdouble", (PyCFunction)_tkinter_tkapp_exprdouble, METH_O, _tkinter_tkapp_exprdouble__doc__}, + +static PyObject * +_tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s); + +static PyObject * +_tkinter_tkapp_exprdouble(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *s; + + if (!PyArg_Parse(arg, "s:exprdouble", &s)) + goto exit; + return_value = _tkinter_tkapp_exprdouble_impl(self, s); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_exprboolean__doc__, +"exprboolean($self, s, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF \ + {"exprboolean", (PyCFunction)_tkinter_tkapp_exprboolean, METH_O, _tkinter_tkapp_exprboolean__doc__}, + +static PyObject * +_tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s); + +static PyObject * +_tkinter_tkapp_exprboolean(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *s; + + if (!PyArg_Parse(arg, "s:exprboolean", &s)) + goto exit; + return_value = _tkinter_tkapp_exprboolean_impl(self, s); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_splitlist__doc__, +"splitlist($self, arg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_SPLITLIST_METHODDEF \ + {"splitlist", (PyCFunction)_tkinter_tkapp_splitlist, METH_O, _tkinter_tkapp_splitlist__doc__}, + +PyDoc_STRVAR(_tkinter_tkapp_split__doc__, +"split($self, arg, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_SPLIT_METHODDEF \ + {"split", (PyCFunction)_tkinter_tkapp_split, METH_O, _tkinter_tkapp_split__doc__}, + +PyDoc_STRVAR(_tkinter_tkapp_createcommand__doc__, +"createcommand($self, name, func, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_CREATECOMMAND_METHODDEF \ + {"createcommand", (PyCFunction)_tkinter_tkapp_createcommand, METH_VARARGS, _tkinter_tkapp_createcommand__doc__}, + +static PyObject * +_tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name, + PyObject *func); + +static PyObject * +_tkinter_tkapp_createcommand(TkappObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + const char *name; + PyObject *func; + + if (!PyArg_ParseTuple(args, "sO:createcommand", + &name, &func)) + goto exit; + return_value = _tkinter_tkapp_createcommand_impl(self, name, func); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_deletecommand__doc__, +"deletecommand($self, name, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_DELETECOMMAND_METHODDEF \ + {"deletecommand", (PyCFunction)_tkinter_tkapp_deletecommand, METH_O, _tkinter_tkapp_deletecommand__doc__}, + +static PyObject * +_tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name); + +static PyObject * +_tkinter_tkapp_deletecommand(TkappObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *name; + + if (!PyArg_Parse(arg, "s:deletecommand", &name)) + goto exit; + return_value = _tkinter_tkapp_deletecommand_impl(self, name); + +exit: + return return_value; +} + +#if defined(HAVE_CREATEFILEHANDLER) + +PyDoc_STRVAR(_tkinter_tkapp_createfilehandler__doc__, +"createfilehandler($self, file, mask, func, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF \ + {"createfilehandler", (PyCFunction)_tkinter_tkapp_createfilehandler, METH_VARARGS, _tkinter_tkapp_createfilehandler__doc__}, + +static PyObject * +_tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file, + int mask, PyObject *func); + +static PyObject * +_tkinter_tkapp_createfilehandler(TkappObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *file; + int mask; + PyObject *func; + + if (!PyArg_ParseTuple(args, "OiO:createfilehandler", + &file, &mask, &func)) + goto exit; + return_value = _tkinter_tkapp_createfilehandler_impl(self, file, mask, func); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CREATEFILEHANDLER) */ + +#if defined(HAVE_CREATEFILEHANDLER) + +PyDoc_STRVAR(_tkinter_tkapp_deletefilehandler__doc__, +"deletefilehandler($self, file, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF \ + {"deletefilehandler", (PyCFunction)_tkinter_tkapp_deletefilehandler, METH_O, _tkinter_tkapp_deletefilehandler__doc__}, + +#endif /* defined(HAVE_CREATEFILEHANDLER) */ + +PyDoc_STRVAR(_tkinter_tktimertoken_deletetimerhandler__doc__, +"deletetimerhandler($self, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF \ + {"deletetimerhandler", (PyCFunction)_tkinter_tktimertoken_deletetimerhandler, METH_NOARGS, _tkinter_tktimertoken_deletetimerhandler__doc__}, + +static PyObject * +_tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self); + +static PyObject * +_tkinter_tktimertoken_deletetimerhandler(TkttObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _tkinter_tktimertoken_deletetimerhandler_impl(self); +} + +PyDoc_STRVAR(_tkinter_tkapp_createtimerhandler__doc__, +"createtimerhandler($self, milliseconds, func, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF \ + {"createtimerhandler", (PyCFunction)_tkinter_tkapp_createtimerhandler, METH_VARARGS, _tkinter_tkapp_createtimerhandler__doc__}, + +static PyObject * +_tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds, + PyObject *func); + +static PyObject * +_tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int milliseconds; + PyObject *func; + + if (!PyArg_ParseTuple(args, "iO:createtimerhandler", + &milliseconds, &func)) + goto exit; + return_value = _tkinter_tkapp_createtimerhandler_impl(self, milliseconds, func); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_mainloop__doc__, +"mainloop($self, threshold=0, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_MAINLOOP_METHODDEF \ + {"mainloop", (PyCFunction)_tkinter_tkapp_mainloop, METH_VARARGS, _tkinter_tkapp_mainloop__doc__}, + +static PyObject * +_tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold); + +static PyObject * +_tkinter_tkapp_mainloop(TkappObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int threshold = 0; + + if (!PyArg_ParseTuple(args, "|i:mainloop", + &threshold)) + goto exit; + return_value = _tkinter_tkapp_mainloop_impl(self, threshold); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_dooneevent__doc__, +"dooneevent($self, flags=0, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_DOONEEVENT_METHODDEF \ + {"dooneevent", (PyCFunction)_tkinter_tkapp_dooneevent, METH_VARARGS, _tkinter_tkapp_dooneevent__doc__}, + +static PyObject * +_tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags); + +static PyObject * +_tkinter_tkapp_dooneevent(TkappObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int flags = 0; + + if (!PyArg_ParseTuple(args, "|i:dooneevent", + &flags)) + goto exit; + return_value = _tkinter_tkapp_dooneevent_impl(self, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_tkapp_quit__doc__, +"quit($self, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_QUIT_METHODDEF \ + {"quit", (PyCFunction)_tkinter_tkapp_quit, METH_NOARGS, _tkinter_tkapp_quit__doc__}, + +static PyObject * +_tkinter_tkapp_quit_impl(TkappObject *self); + +static PyObject * +_tkinter_tkapp_quit(TkappObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _tkinter_tkapp_quit_impl(self); +} + +PyDoc_STRVAR(_tkinter_tkapp_interpaddr__doc__, +"interpaddr($self, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_INTERPADDR_METHODDEF \ + {"interpaddr", (PyCFunction)_tkinter_tkapp_interpaddr, METH_NOARGS, _tkinter_tkapp_interpaddr__doc__}, + +static PyObject * +_tkinter_tkapp_interpaddr_impl(TkappObject *self); + +static PyObject * +_tkinter_tkapp_interpaddr(TkappObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _tkinter_tkapp_interpaddr_impl(self); +} + +PyDoc_STRVAR(_tkinter_tkapp_loadtk__doc__, +"loadtk($self, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_LOADTK_METHODDEF \ + {"loadtk", (PyCFunction)_tkinter_tkapp_loadtk, METH_NOARGS, _tkinter_tkapp_loadtk__doc__}, + +static PyObject * +_tkinter_tkapp_loadtk_impl(TkappObject *self); + +static PyObject * +_tkinter_tkapp_loadtk(TkappObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _tkinter_tkapp_loadtk_impl(self); +} + +PyDoc_STRVAR(_tkinter_tkapp_willdispatch__doc__, +"willdispatch($self, /)\n" +"--\n" +"\n"); + +#define _TKINTER_TKAPP_WILLDISPATCH_METHODDEF \ + {"willdispatch", (PyCFunction)_tkinter_tkapp_willdispatch, METH_NOARGS, _tkinter_tkapp_willdispatch__doc__}, + +static PyObject * +_tkinter_tkapp_willdispatch_impl(TkappObject *self); + +static PyObject * +_tkinter_tkapp_willdispatch(TkappObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _tkinter_tkapp_willdispatch_impl(self); +} + +PyDoc_STRVAR(_tkinter__flatten__doc__, +"_flatten($module, item, /)\n" +"--\n" +"\n"); + +#define _TKINTER__FLATTEN_METHODDEF \ + {"_flatten", (PyCFunction)_tkinter__flatten, METH_O, _tkinter__flatten__doc__}, + +PyDoc_STRVAR(_tkinter_create__doc__, +"create($module, screenName=None, baseName=None, className=\'Tk\',\n" +" interactive=False, wantobjects=False, wantTk=True, sync=False,\n" +" use=None, /)\n" +"--\n" +"\n" +"\n" +"\n" +" wantTk\n" +" if false, then Tk_Init() doesn\'t get called\n" +" sync\n" +" if true, then pass -sync to wish\n" +" use\n" +" if not None, then pass -use to wish"); + +#define _TKINTER_CREATE_METHODDEF \ + {"create", (PyCFunction)_tkinter_create, METH_VARARGS, _tkinter_create__doc__}, + +static PyObject * +_tkinter_create_impl(PyModuleDef *module, const char *screenName, + const char *baseName, const char *className, + int interactive, int wantobjects, int wantTk, int sync, + const char *use); + +static PyObject * +_tkinter_create(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + const char *screenName = NULL; + const char *baseName = NULL; + const char *className = "Tk"; + int interactive = 0; + int wantobjects = 0; + int wantTk = 1; + int sync = 0; + const char *use = NULL; + + if (!PyArg_ParseTuple(args, "|zssiiiiz:create", + &screenName, &baseName, &className, &interactive, &wantobjects, &wantTk, &sync, &use)) + goto exit; + return_value = _tkinter_create_impl(module, screenName, baseName, className, interactive, wantobjects, wantTk, sync, use); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_setbusywaitinterval__doc__, +"setbusywaitinterval($module, new_val, /)\n" +"--\n" +"\n" +"Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.\n" +"\n" +"It should be set to a divisor of the maximum time between frames in an animation."); + +#define _TKINTER_SETBUSYWAITINTERVAL_METHODDEF \ + {"setbusywaitinterval", (PyCFunction)_tkinter_setbusywaitinterval, METH_O, _tkinter_setbusywaitinterval__doc__}, + +static PyObject * +_tkinter_setbusywaitinterval_impl(PyModuleDef *module, int new_val); + +static PyObject * +_tkinter_setbusywaitinterval(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int new_val; + + if (!PyArg_Parse(arg, "i:setbusywaitinterval", &new_val)) + goto exit; + return_value = _tkinter_setbusywaitinterval_impl(module, new_val); + +exit: + return return_value; +} + +PyDoc_STRVAR(_tkinter_getbusywaitinterval__doc__, +"getbusywaitinterval($module, /)\n" +"--\n" +"\n" +"Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter."); + +#define _TKINTER_GETBUSYWAITINTERVAL_METHODDEF \ + {"getbusywaitinterval", (PyCFunction)_tkinter_getbusywaitinterval, METH_NOARGS, _tkinter_getbusywaitinterval__doc__}, static int -WaitForMainloop(TkappObject* self) -{ - int i; - for (i = 0; i < 10; i++) { - if (self->dispatching) - return 1; - Py_BEGIN_ALLOW_THREADS - Sleep(100); - Py_END_ALLOW_THREADS - } - if (self->dispatching) - return 1; - PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop"); - return 0; -} -#endif /* WITH_THREAD */ - - - -#define ARGSZ 64 - - +_tkinter_getbusywaitinterval_impl(PyModuleDef *module); static PyObject * -unicodeFromTclStringAndSize(const char *s, Py_ssize_t size) +_tkinter_getbusywaitinterval(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); - if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { - /* Tcl encodes null character as \xc0\x80 */ - if (memchr(s, '\xc0', size)) { - char *buf, *q; - const char *e = s + size; - PyErr_Clear(); - q = buf = (char *)PyMem_Malloc(size); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - while (s != e) { - if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { - *q++ = '\0'; - s += 2; - } - else - *q++ = *s++; - } - s = buf; - size = q - s; - r = PyUnicode_DecodeUTF8(s, size, NULL); - PyMem_Free(buf); - } - } - return r; + PyObject *return_value = NULL; + int _return_value; + + _return_value = _tkinter_getbusywaitinterval_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; } -static PyObject * -unicodeFromTclString(const char *s) -{ - return unicodeFromTclStringAndSize(s, strlen(s)); -} +#ifndef _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF + #define _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF +#endif /* !defined(_TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF) */ -static PyObject * -unicodeFromTclObj(Tcl_Obj *value) -{ - int len; - char *s = Tcl_GetStringFromObj(value, &len); - return unicodeFromTclStringAndSize(s, len); -} - - -static PyObject * -Split(const char *list) -{ - int argc; - const char **argv; - PyObject *v; - - if (list == NULL) { - Py_RETURN_NONE; - } - - if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { - /* Not a list. - * Could be a quoted string containing funnies, e.g. {"}. - * Return the string itself. - */ - return unicodeFromTclString(list); - } - - if (argc == 0) - v = PyUnicode_FromString(""); - else if (argc == 1) - v = unicodeFromTclString(argv[0]); - else if ((v = PyTuple_New(argc)) != NULL) { - int i; - PyObject *w; - - for (i = 0; i < argc; i++) { - if ((w = Split(argv[i])) == NULL) { - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SetItem(v, i, w); - } - } - Tcl_Free(FREECAST argv); - return v; -} - -/* In some cases, Tcl will still return strings that are supposed to - be lists. SplitObj walks through a nested tuple, finding string - objects that need to be split. */ - -static PyObject * -SplitObj(PyObject *arg) -{ - if (PyTuple_Check(arg)) { - Py_ssize_t i, size; - PyObject *elem, *newelem, *result; - - size = PyTuple_Size(arg); - result = NULL; - /* Recursively invoke SplitObj for all tuple items. - If this does not return a new object, no action is - needed. */ - for(i = 0; i < size; i++) { - elem = PyTuple_GetItem(arg, i); - newelem = SplitObj(elem); - if (!newelem) { - Py_XDECREF(result); - return NULL; - } - if (!result) { - Py_ssize_t k; - if (newelem == elem) { - Py_DECREF(newelem); - continue; - } - result = PyTuple_New(size); - if (!result) - return NULL; - for(k = 0; k < i; k++) { - elem = PyTuple_GetItem(arg, k); - Py_INCREF(elem); - PyTuple_SetItem(result, k, elem); - } - } - PyTuple_SetItem(result, i, newelem); - } - if (result) - return result; - /* Fall through, returning arg. */ - } - else if (PyList_Check(arg)) { - Py_ssize_t i, size; - PyObject *elem, *newelem, *result; - - size = PyList_GET_SIZE(arg); - result = PyTuple_New(size); - if (!result) - return NULL; - /* Recursively invoke SplitObj for all list items. */ - for(i = 0; i < size; i++) { - elem = PyList_GET_ITEM(arg, i); - newelem = SplitObj(elem); - if (!newelem) { - Py_XDECREF(result); - return NULL; - } - PyTuple_SetItem(result, i, newelem); - } - return result; - } - else if (PyUnicode_Check(arg)) { - int argc; - const char **argv; - char *list = PyUnicode_AsUTF8(arg); - - if (list == NULL || - Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { - Py_INCREF(arg); - return arg; - } - Tcl_Free(FREECAST argv); - if (argc > 1) - return Split(list); - /* Fall through, returning arg. */ - } - else if (PyBytes_Check(arg)) { - int argc; - const char **argv; - char *list = PyBytes_AsString(arg); - - if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { - Py_INCREF(arg); - return arg; - } - Tcl_Free(FREECAST argv); - if (argc > 1) - return Split(PyBytes_AsString(arg)); - /* Fall through, returning arg. */ - } - Py_INCREF(arg); - return arg; -} - - -/**** Tkapp Object ****/ - -#ifndef WITH_APPINIT -int -Tcl_AppInit(Tcl_Interp *interp) -{ - const char * _tkinter_skip_tk_init; - - if (Tcl_Init(interp) == TCL_ERROR) { - PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp)); - return TCL_ERROR; - } - - _tkinter_skip_tk_init = Tcl_GetVar(interp, - "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY); - if (_tkinter_skip_tk_init != NULL && - strcmp(_tkinter_skip_tk_init, "1") == 0) { - return TCL_OK; - } - -#ifdef TKINTER_PROTECT_LOADTK - if (tk_load_failed) { - PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG); - return TCL_ERROR; - } -#endif - - if (Tk_Init(interp) == TCL_ERROR) { -#ifdef TKINTER_PROTECT_LOADTK - tk_load_failed = 1; -#endif - PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp)); - return TCL_ERROR; - } - - return TCL_OK; -} -#endif /* !WITH_APPINIT */ - - - - -/* Initialize the Tk application; see the `main' function in - * `tkMain.c'. - */ - -static void EnableEventHook(void); /* Forward */ -static void DisableEventHook(void); /* Forward */ - -static TkappObject * -Tkapp_New(const char *screenName, const char *className, - int interactive, int wantobjects, int wantTk, int sync, - const char *use) -{ - TkappObject *v; - char *argv0; - - v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type); - if (v == NULL) - return NULL; - Py_INCREF(Tkapp_Type); - - v->interp = Tcl_CreateInterp(); - v->wantobjects = wantobjects; - v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded", - TCL_GLOBAL_ONLY) != NULL; - v->thread_id = Tcl_GetCurrentThread(); - v->dispatching = 0; - -#ifndef TCL_THREADS - if (v->threaded) { - PyErr_SetString(PyExc_RuntimeError, - "Tcl is threaded but _tkinter is not"); - Py_DECREF(v); - return 0; - } -#endif -#ifdef WITH_THREAD - if (v->threaded && tcl_lock) { - /* If Tcl is threaded, we don't need the lock. */ - PyThread_free_lock(tcl_lock); - tcl_lock = NULL; - } -#endif - - v->OldBooleanType = Tcl_GetObjType("boolean"); - v->BooleanType = Tcl_GetObjType("booleanString"); - v->ByteArrayType = Tcl_GetObjType("bytearray"); - v->DoubleType = Tcl_GetObjType("double"); - v->IntType = Tcl_GetObjType("int"); - v->WideIntType = Tcl_GetObjType("wideInt"); - v->BignumType = Tcl_GetObjType("bignum"); - v->ListType = Tcl_GetObjType("list"); - v->ProcBodyType = Tcl_GetObjType("procbody"); - v->StringType = Tcl_GetObjType("string"); - - /* Delete the 'exit' command, which can screw things up */ - Tcl_DeleteCommand(v->interp, "exit"); - - if (screenName != NULL) - Tcl_SetVar2(v->interp, "env", "DISPLAY", - screenName, TCL_GLOBAL_ONLY); - - if (interactive) - Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); - else - Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); - - /* This is used to get the application class for Tk 4.1 and up */ - argv0 = (char*)PyMem_Malloc(strlen(className) + 1); - if (!argv0) { - PyErr_NoMemory(); - Py_DECREF(v); - return NULL; - } - - strcpy(argv0, className); - if (Py_ISUPPER(Py_CHARMASK(argv0[0]))) - argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0])); - Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY); - PyMem_Free(argv0); - - if (! wantTk) { - Tcl_SetVar(v->interp, - "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY); - } -#ifdef TKINTER_PROTECT_LOADTK - else if (tk_load_failed) { - Tcl_SetVar(v->interp, - "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY); - } -#endif - - /* some initial arguments need to be in argv */ - if (sync || use) { - char *args; - Py_ssize_t len = 0; - - if (sync) - len += sizeof "-sync"; - if (use) - len += strlen(use) + sizeof "-use "; /* never overflows */ - - args = (char*)PyMem_Malloc(len); - if (!args) { - PyErr_NoMemory(); - Py_DECREF(v); - return NULL; - } - - args[0] = '\0'; - if (sync) - strcat(args, "-sync"); - if (use) { - if (sync) - strcat(args, " "); - strcat(args, "-use "); - strcat(args, use); - } - - Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY); - PyMem_Free(args); - } - - if (Tcl_AppInit(v->interp) != TCL_OK) { - PyObject *result = Tkinter_Error((PyObject *)v); -#ifdef TKINTER_PROTECT_LOADTK - if (wantTk) { - const char *_tkinter_tk_failed; - _tkinter_tk_failed = Tcl_GetVar(v->interp, - "_tkinter_tk_failed", TCL_GLOBAL_ONLY); - - if ( _tkinter_tk_failed != NULL && - strcmp(_tkinter_tk_failed, "1") == 0) { - tk_load_failed = 1; - } - } -#endif - Py_DECREF((PyObject *)v); - return (TkappObject *)result; - } - - EnableEventHook(); - - return v; -} - - -#ifdef WITH_THREAD -static void -Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev, - Tcl_Condition *cond, Tcl_Mutex *mutex) -{ - Py_BEGIN_ALLOW_THREADS; - Tcl_MutexLock(mutex); - Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(self->thread_id); - Tcl_ConditionWait(cond, mutex, NULL); - Tcl_MutexUnlock(mutex); - Py_END_ALLOW_THREADS -} -#endif - - -/** Tcl Eval **/ - -typedef struct { - PyObject_HEAD - Tcl_Obj *value; - PyObject *string; /* This cannot cause cycles. */ -} PyTclObject; - -static PyObject *PyTclObject_Type; -#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type) - -static PyObject * -newPyTclObject(Tcl_Obj *arg) -{ - PyTclObject *self; - self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type); - if (self == NULL) - return NULL; - Py_INCREF(PyTclObject_Type); - Tcl_IncrRefCount(arg); - self->value = arg; - self->string = NULL; - return (PyObject*)self; -} - -static void -PyTclObject_dealloc(PyTclObject *self) -{ - PyObject *tp = (PyObject *) Py_TYPE(self); - Tcl_DecrRefCount(self->value); - Py_XDECREF(self->string); - PyObject_Del(self); - Py_DECREF(tp); -} - -static char* -PyTclObject_TclString(PyObject *self) -{ - return Tcl_GetString(((PyTclObject*)self)->value); -} - -/* Like _str, but create Unicode if necessary. */ -PyDoc_STRVAR(PyTclObject_string__doc__, -"the string representation of this object, either as str or bytes"); - -static PyObject * -PyTclObject_string(PyTclObject *self, void *ignored) -{ - if (!self->string) { - self->string = unicodeFromTclObj(self->value); - if (!self->string) - return NULL; - } - Py_INCREF(self->string); - return self->string; -} - -static PyObject * -PyTclObject_str(PyTclObject *self, void *ignored) -{ - if (self->string) { - Py_INCREF(self->string); - return self->string; - } - /* XXX Could chache result if it is non-ASCII. */ - return unicodeFromTclObj(self->value); -} - -static PyObject * -PyTclObject_repr(PyTclObject *self) -{ - PyObject *repr, *str = PyTclObject_str(self, NULL); - if (str == NULL) - return NULL; - repr = PyUnicode_FromFormat("<%s object: %R>", - self->value->typePtr->name, str); - Py_DECREF(str); - return repr; -} - -#define TEST_COND(cond) ((cond) ? Py_True : Py_False) - -static PyObject * -PyTclObject_richcompare(PyObject *self, PyObject *other, int op) -{ - int result; - PyObject *v; - - /* neither argument should be NULL, unless something's gone wrong */ - if (self == NULL || other == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - /* both arguments should be instances of PyTclObject */ - if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) { - v = Py_NotImplemented; - goto finished; - } - - if (self == other) - /* fast path when self and other are identical */ - result = 0; - else - result = strcmp(Tcl_GetString(((PyTclObject *)self)->value), - Tcl_GetString(((PyTclObject *)other)->value)); - /* Convert return value to a Boolean */ - switch (op) { - case Py_EQ: - v = TEST_COND(result == 0); - break; - case Py_NE: - v = TEST_COND(result != 0); - break; - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result < 0); - break; - case Py_GT: - v = TEST_COND(result > 0); - break; - default: - PyErr_BadArgument(); - return NULL; - } - finished: - Py_INCREF(v); - return v; -} - -PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type"); - -static PyObject* -get_typename(PyTclObject* obj, void* ignored) -{ - return unicodeFromTclString(obj->value->typePtr->name); -} - - -static PyGetSetDef PyTclObject_getsetlist[] = { - {"typename", (getter)get_typename, NULL, get_typename__doc__}, - {"string", (getter)PyTclObject_string, NULL, - PyTclObject_string__doc__}, - {0}, -}; - -static PyType_Slot PyTclObject_Type_slots[] = { - {Py_tp_dealloc, (destructor)PyTclObject_dealloc}, - {Py_tp_repr, (reprfunc)PyTclObject_repr}, - {Py_tp_str, (reprfunc)PyTclObject_str}, - {Py_tp_getattro, PyObject_GenericGetAttr}, - {Py_tp_richcompare, PyTclObject_richcompare}, - {Py_tp_getset, PyTclObject_getsetlist}, - {0, 0} -}; - -static PyType_Spec PyTclObject_Type_spec = { - "_tkinter.Tcl_Obj", - sizeof(PyTclObject), - 0, - Py_TPFLAGS_DEFAULT, - PyTclObject_Type_slots, -}; - - -#if PY_SIZE_MAX > INT_MAX -#define CHECK_STRING_LENGTH(s) do { \ - if (s != NULL && strlen(s) >= INT_MAX) { \ - PyErr_SetString(PyExc_OverflowError, "string is too long"); \ - return NULL; \ - } } while(0) -#else -#define CHECK_STRING_LENGTH(s) -#endif - -#ifdef HAVE_LIBTOMMAMTH -static Tcl_Obj* -asBignumObj(PyObject *value) -{ - Tcl_Obj *result; - int neg; - PyObject *hexstr; - char *hexchars; - mp_int bigValue; - - neg = Py_SIZE(value) < 0; - hexstr = _PyLong_Format(value, 16); - if (hexstr == NULL) - return NULL; - hexchars = PyUnicode_AsUTF8(hexstr); - if (hexchars == NULL) { - Py_DECREF(hexstr); - return NULL; - } - hexchars += neg + 2; /* skip sign and "0x" */ - mp_init(&bigValue); - if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) { - mp_clear(&bigValue); - Py_DECREF(hexstr); - PyErr_NoMemory(); - return NULL; - } - Py_DECREF(hexstr); - bigValue.sign = neg ? MP_NEG : MP_ZPOS; - result = Tcl_NewBignumObj(&bigValue); - mp_clear(&bigValue); - if (result == NULL) { - PyErr_NoMemory(); - return NULL; - } - return result; -} -#endif - -static Tcl_Obj* -AsObj(PyObject *value) -{ - Tcl_Obj *result; - - if (PyBytes_Check(value)) { - if (PyBytes_GET_SIZE(value) >= INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "bytes object is too long"); - return NULL; - } - return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value), - (int)PyBytes_GET_SIZE(value)); - } - - if (PyBool_Check(value)) - return Tcl_NewBooleanObj(PyObject_IsTrue(value)); - - if (PyLong_CheckExact(value)) { - int overflow; - long longValue; -#ifdef TCL_WIDE_INT_TYPE - Tcl_WideInt wideValue; -#endif - longValue = PyLong_AsLongAndOverflow(value, &overflow); - if (!overflow) { - return Tcl_NewLongObj(longValue); - } - /* If there is an overflow in the long conversion, - fall through to wideInt handling. */ -#ifdef TCL_WIDE_INT_TYPE - if (_PyLong_AsByteArray((PyLongObject *)value, - (unsigned char *)(void *)&wideValue, - sizeof(wideValue), - PY_LITTLE_ENDIAN, - /* signed */ 1) == 0) { - return Tcl_NewWideIntObj(wideValue); - } - PyErr_Clear(); -#endif - /* If there is an overflow in the wideInt conversion, - fall through to bignum handling. */ -#ifdef HAVE_LIBTOMMAMTH - return asBignumObj(value); -#endif - /* If there is no wideInt or bignum support, - fall through to default object handling. */ - } - - if (PyFloat_Check(value)) - return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - - if (PyTuple_Check(value) || PyList_Check(value)) { - Tcl_Obj **argv; - Py_ssize_t size, i; - - size = PySequence_Fast_GET_SIZE(value); - if (size == 0) - return Tcl_NewListObj(0, NULL); - if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, - PyTuple_Check(value) ? "tuple is too long" : - "list is too long"); - return NULL; - } - argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *)); - if (!argv) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < size; i++) - argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i)); - result = Tcl_NewListObj((int)size, argv); - PyMem_Free(argv); - return result; - } - - if (PyUnicode_Check(value)) { - void *inbuf; - Py_ssize_t size; - int kind; - Tcl_UniChar *outbuf = NULL; - Py_ssize_t i; - size_t allocsize; - - if (PyUnicode_READY(value) == -1) - return NULL; - - inbuf = PyUnicode_DATA(value); - size = PyUnicode_GET_LENGTH(value); - if (size == 0) - return Tcl_NewUnicodeObj((const void *)"", 0); - if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) { - PyErr_SetString(PyExc_OverflowError, "string is too long"); - return NULL; - } - kind = PyUnicode_KIND(value); - if (kind == sizeof(Tcl_UniChar)) - return Tcl_NewUnicodeObj(inbuf, (int)size); - allocsize = ((size_t)size) * sizeof(Tcl_UniChar); - outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize); - /* Else overflow occurred, and we take the next exit */ - if (!outbuf) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < size; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i); - /* We cannot test for sizeof(Tcl_UniChar) directly, - so we test for UTF-8 size instead. */ -#if TCL_UTF_MAX == 3 - if (ch >= 0x10000) { - /* Tcl doesn't do UTF-16, yet. */ - PyErr_Format(Tkinter_TclError, - "character U+%x is above the range " - "(U+0000-U+FFFF) allowed by Tcl", - ch); - PyMem_Free(outbuf); - return NULL; - } -#endif - outbuf[i] = ch; - } - result = Tcl_NewUnicodeObj(outbuf, (int)size); - PyMem_Free(outbuf); - return result; - } - - if (PyTclObject_Check(value)) { - Tcl_Obj *v = ((PyTclObject*)value)->value; - Tcl_IncrRefCount(v); - return v; - } - - { - PyObject *v = PyObject_Str(value); - if (!v) - return 0; - result = AsObj(v); - Py_DECREF(v); - return result; - } -} - -static PyObject * -fromBoolean(PyObject* tkapp, Tcl_Obj *value) -{ - int boolValue; - if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) - return Tkinter_Error(tkapp); - return PyBool_FromLong(boolValue); -} - -static PyObject* -fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) -{ - Tcl_WideInt wideValue; - if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) { -#ifdef HAVE_LONG_LONG - if (sizeof(wideValue) <= SIZEOF_LONG_LONG) - return PyLong_FromLongLong(wideValue); -#endif - return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue, - sizeof(wideValue), - PY_LITTLE_ENDIAN, - /* signed */ 1); - } - return NULL; -} - -#ifdef HAVE_LIBTOMMAMTH -static PyObject* -fromBignumObj(PyObject* tkapp, Tcl_Obj *value) -{ - mp_int bigValue; - unsigned long numBytes; - unsigned char *bytes; - PyObject *res; - - if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK) - return Tkinter_Error(tkapp); - numBytes = mp_unsigned_bin_size(&bigValue); - bytes = PyMem_Malloc(numBytes); - if (bytes == NULL) { - mp_clear(&bigValue); - return PyErr_NoMemory(); - } - if (mp_to_unsigned_bin_n(&bigValue, bytes, - &numBytes) != MP_OKAY) { - mp_clear(&bigValue); - PyMem_Free(bytes); - return PyErr_NoMemory(); - } - res = _PyLong_FromByteArray(bytes, numBytes, - /* big-endian */ 0, - /* unsigned */ 0); - PyMem_Free(bytes); - if (res != NULL && bigValue.sign == MP_NEG) { - PyObject *res2 = PyNumber_Negative(res); - Py_DECREF(res); - res = res2; - } - mp_clear(&bigValue); - return res; -} -#endif - -static PyObject* -FromObj(PyObject* tkapp, Tcl_Obj *value) -{ - PyObject *result = NULL; - TkappObject *app = (TkappObject*)tkapp; - Tcl_Interp *interp = Tkapp_Interp(tkapp); - - if (value->typePtr == NULL) { - return unicodeFromTclStringAndSize(value->bytes, value->length); - } - - if (value->typePtr == app->BooleanType || - value->typePtr == app->OldBooleanType) { - return fromBoolean(tkapp, value); - } - - if (value->typePtr == app->ByteArrayType) { - int size; - char *data = (char*)Tcl_GetByteArrayFromObj(value, &size); - return PyBytes_FromStringAndSize(data, size); - } - - if (value->typePtr == app->DoubleType) { - return PyFloat_FromDouble(value->internalRep.doubleValue); - } - - if (value->typePtr == app->IntType) { - long longValue; - if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) - return PyLong_FromLong(longValue); - /* If there is an error in the long conversion, - fall through to wideInt handling. */ - } - - if (value->typePtr == app->IntType || - value->typePtr == app->WideIntType) { - result = fromWideIntObj(tkapp, value); - if (result != NULL || PyErr_Occurred()) - return result; - Tcl_ResetResult(interp); - /* If there is an error in the wideInt conversion, - fall through to bignum handling. */ - } - -#ifdef HAVE_LIBTOMMAMTH - if (value->typePtr == app->IntType || - value->typePtr == app->WideIntType || - value->typePtr == app->BignumType) { - return fromBignumObj(tkapp, value); - } -#endif - - if (value->typePtr == app->ListType) { - int size; - int i, status; - PyObject *elem; - Tcl_Obj *tcl_elem; - - status = Tcl_ListObjLength(interp, value, &size); - if (status == TCL_ERROR) - return Tkinter_Error(tkapp); - result = PyTuple_New(size); - if (!result) - return NULL; - for (i = 0; i < size; i++) { - status = Tcl_ListObjIndex(interp, value, i, &tcl_elem); - if (status == TCL_ERROR) { - Py_DECREF(result); - return Tkinter_Error(tkapp); - } - elem = FromObj(tkapp, tcl_elem); - if (!elem) { - Py_DECREF(result); - return NULL; - } - PyTuple_SetItem(result, i, elem); - } - return result; - } - - if (value->typePtr == app->ProcBodyType) { - /* fall through: return tcl object. */ - } - - if (value->typePtr == app->StringType) { - return PyUnicode_FromKindAndData( - sizeof(Tcl_UniChar), Tcl_GetUnicode(value), - Tcl_GetCharLength(value)); - } - -#if TK_HEX_VERSION >= 0x08050000 - if (app->BooleanType == NULL && - strcmp(value->typePtr->name, "booleanString") == 0) { - /* booleanString type is not registered in Tcl */ - app->BooleanType = value->typePtr; - return fromBoolean(tkapp, value); - } -#endif - -#ifdef HAVE_LIBTOMMAMTH - if (app->BignumType == NULL && - strcmp(value->typePtr->name, "bignum") == 0) { - /* bignum type is not registered in Tcl */ - app->BignumType = value->typePtr; - return fromBignumObj(tkapp, value); - } -#endif - - return newPyTclObject(value); -} - -#ifdef WITH_THREAD -/* This mutex synchronizes inter-thread command calls. */ -TCL_DECLARE_MUTEX(call_mutex) - -typedef struct Tkapp_CallEvent { - Tcl_Event ev; /* Must be first */ - TkappObject *self; - PyObject *args; - int flags; - PyObject **res; - PyObject **exc_type, **exc_value, **exc_tb; - Tcl_Condition *done; -} Tkapp_CallEvent; -#endif - -void -Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) -{ - int i; - for (i = 0; i < objc; i++) - Tcl_DecrRefCount(objv[i]); - if (objv != objStore) - PyMem_Free(objv); -} - -/* Convert Python objects to Tcl objects. This must happen in the - interpreter thread, which may or may not be the calling thread. */ - -static Tcl_Obj** -Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) -{ - Tcl_Obj **objv = objStore; - Py_ssize_t objc = 0, i; - if (args == NULL) - /* do nothing */; - - else if (!(PyTuple_Check(args) || PyList_Check(args))) { - objv[0] = AsObj(args); - if (objv[0] == 0) - goto finally; - objc = 1; - Tcl_IncrRefCount(objv[0]); - } - else { - objc = PySequence_Fast_GET_SIZE(args); - - if (objc > ARGSZ) { - if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, - PyTuple_Check(args) ? "tuple is too long" : - "list is too long"); - return NULL; - } - objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *)); - if (objv == NULL) { - PyErr_NoMemory(); - objc = 0; - goto finally; - } - } - - for (i = 0; i < objc; i++) { - PyObject *v = PySequence_Fast_GET_ITEM(args, i); - if (v == Py_None) { - objc = i; - break; - } - objv[i] = AsObj(v); - if (!objv[i]) { - /* Reset objc, so it attempts to clear - objects only up to i. */ - objc = i; - goto finally; - } - Tcl_IncrRefCount(objv[i]); - } - } - *pobjc = (int)objc; - return objv; -finally: - Tkapp_CallDeallocArgs(objv, objStore, (int)objc); - return NULL; -} - -/* Convert the results of a command call into a Python objects. */ - -static PyObject* -Tkapp_CallResult(TkappObject *self) -{ - PyObject *res = NULL; - Tcl_Obj *value = Tcl_GetObjResult(self->interp); - if(self->wantobjects) { - /* Not sure whether the IncrRef is necessary, but something - may overwrite the interpreter result while we are - converting it. */ - Tcl_IncrRefCount(value); - res = FromObj((PyObject*)self, value); - Tcl_DecrRefCount(value); - } else { - res = unicodeFromTclObj(value); - } - return res; -} - -#ifdef WITH_THREAD - -/* Tkapp_CallProc is the event procedure that is executed in the context of - the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't - hold the Python lock. */ - -static int -Tkapp_CallProc(Tkapp_CallEvent *e, int flags) -{ - Tcl_Obj *objStore[ARGSZ]; - Tcl_Obj **objv; - int objc; - int i; - ENTER_PYTHON - objv = Tkapp_CallArgs(e->args, objStore, &objc); - if (!objv) { - PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb); - *(e->res) = NULL; - } - LEAVE_PYTHON - if (!objv) - goto done; - i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags); - ENTER_PYTHON - if (i == TCL_ERROR) { - *(e->res) = NULL; - *(e->exc_type) = NULL; - *(e->exc_tb) = NULL; - *(e->exc_value) = PyObject_CallFunction( - Tkinter_TclError, "s", - Tcl_GetStringResult(e->self->interp)); - } - else { - *(e->res) = Tkapp_CallResult(e->self); - } - LEAVE_PYTHON - - Tkapp_CallDeallocArgs(objv, objStore, objc); -done: - /* Wake up calling thread. */ - Tcl_MutexLock(&call_mutex); - Tcl_ConditionNotify(e->done); - Tcl_MutexUnlock(&call_mutex); - return 1; -} - -#endif - -/* This is the main entry point for calling a Tcl command. - It supports three cases, with regard to threading: - 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in - the context of the calling thread. - 2. Tcl is threaded, caller of the command is in the interpreter thread: - Execute the command in the calling thread. Since the Tcl lock will - not be used, we can merge that with case 1. - 3. Tcl is threaded, caller is in a different thread: Must queue an event to - the interpreter thread. Allocation of Tcl objects needs to occur in the - interpreter thread, so we ship the PyObject* args to the target thread, - and perform processing there. */ - -static PyObject * -Tkapp_Call(PyObject *selfptr, PyObject *args) -{ - Tcl_Obj *objStore[ARGSZ]; - Tcl_Obj **objv = NULL; - int objc, i; - PyObject *res = NULL; - TkappObject *self = (TkappObject*)selfptr; - int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL; - - /* If args is a single tuple, replace with contents of tuple */ - if (1 == PyTuple_Size(args)){ - PyObject* item = PyTuple_GetItem(args, 0); - if (PyTuple_Check(item)) - args = item; - } -#ifdef WITH_THREAD - if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { - /* We cannot call the command directly. Instead, we must - marshal the parameters to the interpreter thread. */ - Tkapp_CallEvent *ev; - Tcl_Condition cond = NULL; - PyObject *exc_type, *exc_value, *exc_tb; - if (!WaitForMainloop(self)) - return NULL; - ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent)); - if (ev == NULL) { - PyErr_NoMemory(); - return NULL; - } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc; - ev->self = self; - ev->args = args; - ev->res = &res; - ev->exc_type = &exc_type; - ev->exc_value = &exc_value; - ev->exc_tb = &exc_tb; - ev->done = &cond; - - Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex); - - if (res == NULL) { - if (exc_type) - PyErr_Restore(exc_type, exc_value, exc_tb); - else - PyErr_SetObject(Tkinter_TclError, exc_value); - } - Tcl_ConditionFinalize(&cond); - } - else -#endif - { - - objv = Tkapp_CallArgs(args, objStore, &objc); - if (!objv) - return NULL; - - ENTER_TCL - - i = Tcl_EvalObjv(self->interp, objc, objv, flags); - - ENTER_OVERLAP - - if (i == TCL_ERROR) - Tkinter_Error(selfptr); - else - res = Tkapp_CallResult(self); - - LEAVE_OVERLAP_TCL - - Tkapp_CallDeallocArgs(objv, objStore, objc); - } - return res; -} - - -static PyObject * -Tkapp_Eval(PyObject *self, PyObject *args) -{ - char *script; - PyObject *res = NULL; - int err; - - if (!PyArg_ParseTuple(args, "s:eval", &script)) - return NULL; - - CHECK_STRING_LENGTH(script); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - err = Tcl_Eval(Tkapp_Interp(self), script); - ENTER_OVERLAP - if (err == TCL_ERROR) - res = Tkinter_Error(self); - else - res = unicodeFromTclString(Tkapp_Result(self)); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_EvalFile(PyObject *self, PyObject *args) -{ - char *fileName; - PyObject *res = NULL; - int err; - - if (!PyArg_ParseTuple(args, "s:evalfile", &fileName)) - return NULL; - - CHECK_STRING_LENGTH(fileName); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - err = Tcl_EvalFile(Tkapp_Interp(self), fileName); - ENTER_OVERLAP - if (err == TCL_ERROR) - res = Tkinter_Error(self); - else - res = unicodeFromTclString(Tkapp_Result(self)); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_Record(PyObject *self, PyObject *args) -{ - char *script; - PyObject *res = NULL; - int err; - - if (!PyArg_ParseTuple(args, "s:record", &script)) - return NULL; - - CHECK_STRING_LENGTH(script); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL); - ENTER_OVERLAP - if (err == TCL_ERROR) - res = Tkinter_Error(self); - else - res = unicodeFromTclString(Tkapp_Result(self)); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_AddErrorInfo(PyObject *self, PyObject *args) -{ - char *msg; - - if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg)) - return NULL; - CHECK_STRING_LENGTH(msg); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - Tcl_AddErrorInfo(Tkapp_Interp(self), msg); - LEAVE_TCL - - Py_RETURN_NONE; -} - - - -/** Tcl Variable **/ - -typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); - -#ifdef WITH_THREAD -TCL_DECLARE_MUTEX(var_mutex) - -typedef struct VarEvent { - Tcl_Event ev; /* must be first */ - PyObject *self; - PyObject *args; - int flags; - EventFunc func; - PyObject **res; - PyObject **exc_type; - PyObject **exc_val; - Tcl_Condition *cond; -} VarEvent; -#endif - -static int -varname_converter(PyObject *in, void *_out) -{ - char *s; - char **out = (char**)_out; - if (PyBytes_Check(in)) { - if (PyBytes_Size(in) > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "bytes object is too long"); - return 0; - } - s = PyBytes_AsString(in); - if (strlen(s) != (size_t)PyBytes_Size(in)) { - PyErr_SetString(PyExc_ValueError, "embedded null byte"); - return 0; - } - *out = s; - return 1; - } - if (PyUnicode_Check(in)) { - Py_ssize_t size; - s = PyUnicode_AsUTF8AndSize(in, &size); - if (s == NULL) { - return 0; - } - if (size > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "string is too long"); - return 0; - } - if (strlen(s) != (size_t)size) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return 0; - } - *out = s; - return 1; - } - if (PyTclObject_Check(in)) { - *out = PyTclObject_TclString(in); - return 1; - } - PyErr_Format(PyExc_TypeError, - "must be str, bytes or Tcl_Obj, not %.50s", - in->ob_type->tp_name); - return 0; -} - -#ifdef WITH_THREAD - -static void -var_perform(VarEvent *ev) -{ - *(ev->res) = ev->func(ev->self, ev->args, ev->flags); - if (!*(ev->res)) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - PyErr_NormalizeException(&exc, &val, &tb); - *(ev->exc_type) = exc; - *(ev->exc_val) = val; - Py_DECREF(tb); - } - -} - -static int -var_proc(VarEvent* ev, int flags) -{ - ENTER_PYTHON - var_perform(ev); - Tcl_MutexLock(&var_mutex); - Tcl_ConditionNotify(ev->cond); - Tcl_MutexUnlock(&var_mutex); - LEAVE_PYTHON - return 1; -} - -#endif - -static PyObject* -var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) -{ -#ifdef WITH_THREAD - TkappObject *self = (TkappObject*)selfptr; - if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { - VarEvent *ev; - PyObject *res, *exc_type, *exc_val; - Tcl_Condition cond = NULL; - - /* The current thread is not the interpreter thread. Marshal - the call to the interpreter thread, then wait for - completion. */ - if (!WaitForMainloop(self)) - return NULL; - - ev = (VarEvent*)attemptckalloc(sizeof(VarEvent)); - if (ev == NULL) { - PyErr_NoMemory(); - return NULL; - } - ev->self = selfptr; - ev->args = args; - ev->flags = flags; - ev->func = func; - ev->res = &res; - ev->exc_type = &exc_type; - ev->exc_val = &exc_val; - ev->cond = &cond; - ev->ev.proc = (Tcl_EventProc*)var_proc; - Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex); - Tcl_ConditionFinalize(&cond); - if (!res) { - PyErr_SetObject(exc_type, exc_val); - Py_DECREF(exc_type); - Py_DECREF(exc_val); - return NULL; - } - return res; - } -#endif - /* Tcl is not threaded, or this is the interpreter thread. */ - return func(selfptr, args, flags); -} - -static PyObject * -SetVar(PyObject *self, PyObject *args, int flags) -{ - char *name1, *name2; - PyObject *newValue; - PyObject *res = NULL; - Tcl_Obj *newval, *ok; - - switch (PyTuple_GET_SIZE(args)) { - case 2: - if (!PyArg_ParseTuple(args, "O&O:setvar", - varname_converter, &name1, &newValue)) - return NULL; - /* XXX Acquire tcl lock??? */ - newval = AsObj(newValue); - if (newval == NULL) - return NULL; - ENTER_TCL - ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL, - newval, flags); - ENTER_OVERLAP - if (!ok) - Tkinter_Error(self); - else { - res = Py_None; - Py_INCREF(res); - } - LEAVE_OVERLAP_TCL - break; - case 3: - if (!PyArg_ParseTuple(args, "ssO:setvar", - &name1, &name2, &newValue)) - return NULL; - CHECK_STRING_LENGTH(name1); - CHECK_STRING_LENGTH(name2); - /* XXX must hold tcl lock already??? */ - newval = AsObj(newValue); - ENTER_TCL - ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); - ENTER_OVERLAP - if (!ok) - Tkinter_Error(self); - else { - res = Py_None; - Py_INCREF(res); - } - LEAVE_OVERLAP_TCL - break; - default: - PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments"); - return NULL; - } - return res; -} - -static PyObject * -Tkapp_SetVar(PyObject *self, PyObject *args) -{ - return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG); -} - -static PyObject * -Tkapp_GlobalSetVar(PyObject *self, PyObject *args) -{ - return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); -} - - - -static PyObject * -GetVar(PyObject *self, PyObject *args, int flags) -{ - char *name1, *name2=NULL; - PyObject *res = NULL; - Tcl_Obj *tres; - - if (!PyArg_ParseTuple(args, "O&|s:getvar", - varname_converter, &name1, &name2)) - return NULL; - - CHECK_STRING_LENGTH(name2); - ENTER_TCL - tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags); - ENTER_OVERLAP - if (tres == NULL) { - PyErr_SetString(Tkinter_TclError, - Tcl_GetStringResult(Tkapp_Interp(self))); - } else { - if (((TkappObject*)self)->wantobjects) { - res = FromObj(self, tres); - } - else { - res = unicodeFromTclObj(tres); - } - } - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_GetVar(PyObject *self, PyObject *args) -{ - return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG); -} - -static PyObject * -Tkapp_GlobalGetVar(PyObject *self, PyObject *args) -{ - return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); -} - - - -static PyObject * -UnsetVar(PyObject *self, PyObject *args, int flags) -{ - char *name1, *name2=NULL; - int code; - PyObject *res = NULL; - - if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2)) - return NULL; - - CHECK_STRING_LENGTH(name1); - CHECK_STRING_LENGTH(name2); - ENTER_TCL - code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags); - ENTER_OVERLAP - if (code == TCL_ERROR) - res = Tkinter_Error(self); - else { - Py_INCREF(Py_None); - res = Py_None; - } - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_UnsetVar(PyObject *self, PyObject *args) -{ - return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG); -} - -static PyObject * -Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args) -{ - return var_invoke(UnsetVar, self, args, - TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); -} - - - -/** Tcl to Python **/ - -static PyObject * -Tkapp_GetInt(PyObject *self, PyObject *args) -{ - char *s; - Tcl_Obj *value; - PyObject *result; - - if (PyTuple_Size(args) == 1) { - PyObject* o = PyTuple_GetItem(args, 0); - if (PyLong_Check(o)) { - Py_INCREF(o); - return o; - } - } - if (!PyArg_ParseTuple(args, "s:getint", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - value = Tcl_NewStringObj(s, -1); - if (value == NULL) - return Tkinter_Error(self); - /* Don't use Tcl_GetInt() because it returns ambiguous result for value - in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). - - Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for - value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). - */ -#ifdef HAVE_LIBTOMMAMTH - result = fromBignumObj(self, value); -#else - result = fromWideIntObj(self, value); -#endif - Tcl_DecrRefCount(value); - if (result != NULL || PyErr_Occurred()) - return result; - return Tkinter_Error(self); -} - -static PyObject * -Tkapp_GetDouble(PyObject *self, PyObject *args) -{ - char *s; - double v; - - if (PyTuple_Size(args) == 1) { - PyObject *o = PyTuple_GetItem(args, 0); - if (PyFloat_Check(o)) { - Py_INCREF(o); - return o; - } - } - if (!PyArg_ParseTuple(args, "s:getdouble", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error(self); - return Py_BuildValue("d", v); -} - -static PyObject * -Tkapp_GetBoolean(PyObject *self, PyObject *arg) -{ - char *s; - int v; - - if (PyLong_Check(arg)) { /* int or bool */ - return PyBool_FromLong(Py_SIZE(arg) != 0); - } - - if (PyTclObject_Check(arg)) { - if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), - ((PyTclObject*)arg)->value, - &v) == TCL_ERROR) - return Tkinter_Error(self); - return PyBool_FromLong(v); - } - - if (!PyArg_Parse(arg, "s:getboolean", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error(self); - return PyBool_FromLong(v); -} - -static PyObject * -Tkapp_ExprString(PyObject *self, PyObject *args) -{ - char *s; - PyObject *res = NULL; - int retval; - - if (!PyArg_ParseTuple(args, "s:exprstring", &s)) - return NULL; - - CHECK_STRING_LENGTH(s); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - retval = Tcl_ExprString(Tkapp_Interp(self), s); - ENTER_OVERLAP - if (retval == TCL_ERROR) - res = Tkinter_Error(self); - else - res = unicodeFromTclString(Tkapp_Result(self)); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_ExprLong(PyObject *self, PyObject *args) -{ - char *s; - PyObject *res = NULL; - int retval; - long v; - - if (!PyArg_ParseTuple(args, "s:exprlong", &s)) - return NULL; - - CHECK_STRING_LENGTH(s); - CHECK_TCL_APPARTMENT; - - ENTER_TCL - retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v); - ENTER_OVERLAP - if (retval == TCL_ERROR) - res = Tkinter_Error(self); - else - res = Py_BuildValue("l", v); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_ExprDouble(PyObject *self, PyObject *args) -{ - char *s; - PyObject *res = NULL; - double v; - int retval; - - if (!PyArg_ParseTuple(args, "s:exprdouble", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - CHECK_TCL_APPARTMENT; - PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0) - ENTER_TCL - retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v); - ENTER_OVERLAP - PyFPE_END_PROTECT(retval) - if (retval == TCL_ERROR) - res = Tkinter_Error(self); - else - res = Py_BuildValue("d", v); - LEAVE_OVERLAP_TCL - return res; -} - -static PyObject * -Tkapp_ExprBoolean(PyObject *self, PyObject *args) -{ - char *s; - PyObject *res = NULL; - int retval; - int v; - - if (!PyArg_ParseTuple(args, "s:exprboolean", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - CHECK_TCL_APPARTMENT; - ENTER_TCL - retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v); - ENTER_OVERLAP - if (retval == TCL_ERROR) - res = Tkinter_Error(self); - else - res = Py_BuildValue("i", v); - LEAVE_OVERLAP_TCL - return res; -} - - - -static PyObject * -Tkapp_SplitList(PyObject *self, PyObject *args) -{ - char *list; - int argc; - const char **argv; - PyObject *arg, *v; - int i; - - if (!PyArg_ParseTuple(args, "O:splitlist", &arg)) - return NULL; - if (PyTclObject_Check(arg)) { - int objc; - Tcl_Obj **objv; - if (Tcl_ListObjGetElements(Tkapp_Interp(self), - ((PyTclObject*)arg)->value, - &objc, &objv) == TCL_ERROR) { - return Tkinter_Error(self); - } - if (!(v = PyTuple_New(objc))) - return NULL; - for (i = 0; i < objc; i++) { - PyObject *s = FromObj(self, objv[i]); - if (!s || PyTuple_SetItem(v, i, s)) { - Py_DECREF(v); - return NULL; - } - } - return v; - } - if (PyTuple_Check(arg)) { - Py_INCREF(arg); - return arg; - } - if (PyList_Check(arg)) { - return PySequence_Tuple(arg); - } - - if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list)) - return NULL; - - CHECK_STRING_LENGTH(list); - if (Tcl_SplitList(Tkapp_Interp(self), list, - &argc, &argv) == TCL_ERROR) { - PyMem_Free(list); - return Tkinter_Error(self); - } - - if (!(v = PyTuple_New(argc))) - goto finally; - - for (i = 0; i < argc; i++) { - PyObject *s = unicodeFromTclString(argv[i]); - if (!s || PyTuple_SetItem(v, i, s)) { - Py_DECREF(v); - v = NULL; - goto finally; - } - } - - finally: - ckfree(FREECAST argv); - PyMem_Free(list); - return v; -} - -static PyObject * -Tkapp_Split(PyObject *self, PyObject *args) -{ - PyObject *arg, *v; - char *list; - - if (!PyArg_ParseTuple(args, "O:split", &arg)) - return NULL; - if (PyTclObject_Check(arg)) { - Tcl_Obj *value = ((PyTclObject*)arg)->value; - int objc; - Tcl_Obj **objv; - int i; - if (Tcl_ListObjGetElements(Tkapp_Interp(self), value, - &objc, &objv) == TCL_ERROR) { - return FromObj(self, value); - } - if (objc == 0) - return PyUnicode_FromString(""); - if (objc == 1) - return FromObj(self, objv[0]); - if (!(v = PyTuple_New(objc))) - return NULL; - for (i = 0; i < objc; i++) { - PyObject *s = FromObj(self, objv[i]); - if (!s || PyTuple_SetItem(v, i, s)) { - Py_DECREF(v); - return NULL; - } - } - return v; - } - if (PyTuple_Check(arg) || PyList_Check(arg)) - return SplitObj(arg); - - if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list)) - return NULL; - CHECK_STRING_LENGTH(list); - v = Split(list); - PyMem_Free(list); - return v; -} - - - -/** Tcl Command **/ - -/* Client data struct */ -typedef struct { - PyObject *self; - PyObject *func; -} PythonCmd_ClientData; - -static int -PythonCmd_Error(Tcl_Interp *interp) -{ - errorInCmd = 1; - PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd); - LEAVE_PYTHON - return TCL_ERROR; -} - -/* This is the Tcl command that acts as a wrapper for Python - * function or method. - */ -static int -PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) -{ - PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; - PyObject *func, *arg, *res; - int i, rv; - Tcl_Obj *obj_res; - - ENTER_PYTHON - - /* TBD: no error checking here since we know, via the - * Tkapp_CreateCommand() that the client data is a two-tuple - */ - func = data->func; - - /* Create argument list (argv1, ..., argvN) */ - if (!(arg = PyTuple_New(argc - 1))) - return PythonCmd_Error(interp); - - for (i = 0; i < (argc - 1); i++) { - PyObject *s = unicodeFromTclString(argv[i + 1]); - if (!s || PyTuple_SetItem(arg, i, s)) { - Py_DECREF(arg); - return PythonCmd_Error(interp); - } - } - res = PyEval_CallObject(func, arg); - Py_DECREF(arg); - - if (res == NULL) - return PythonCmd_Error(interp); - - obj_res = AsObj(res); - if (obj_res == NULL) { - Py_DECREF(res); - return PythonCmd_Error(interp); - } - else { - Tcl_SetObjResult(interp, obj_res); - rv = TCL_OK; - } - - Py_DECREF(res); - - LEAVE_PYTHON - - return rv; -} - -static void -PythonCmdDelete(ClientData clientData) -{ - PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; - - ENTER_PYTHON - Py_XDECREF(data->self); - Py_XDECREF(data->func); - PyMem_DEL(data); - LEAVE_PYTHON -} - - - - -#ifdef WITH_THREAD -TCL_DECLARE_MUTEX(command_mutex) - -typedef struct CommandEvent{ - Tcl_Event ev; - Tcl_Interp* interp; - char *name; - int create; - int *status; - ClientData *data; - Tcl_Condition *done; -} CommandEvent; - -static int -Tkapp_CommandProc(CommandEvent *ev, int flags) -{ - if (ev->create) - *ev->status = Tcl_CreateCommand( - ev->interp, ev->name, PythonCmd, - ev->data, PythonCmdDelete) == NULL; - else - *ev->status = Tcl_DeleteCommand(ev->interp, ev->name); - Tcl_MutexLock(&command_mutex); - Tcl_ConditionNotify(ev->done); - Tcl_MutexUnlock(&command_mutex); - return 1; -} -#endif - -static PyObject * -Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) -{ - TkappObject *self = (TkappObject*)selfptr; - PythonCmd_ClientData *data; - char *cmdName; - PyObject *func; - int err; - - if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func)) - return NULL; - CHECK_STRING_LENGTH(cmdName); - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, "command not callable"); - return NULL; - } - -#ifdef WITH_THREAD - if (self->threaded && self->thread_id != Tcl_GetCurrentThread() && - !WaitForMainloop(self)) - return NULL; -#endif - - data = PyMem_NEW(PythonCmd_ClientData, 1); - if (!data) - return PyErr_NoMemory(); - Py_INCREF(self); - Py_INCREF(func); - data->self = selfptr; - data->func = func; -#ifdef WITH_THREAD - if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { - Tcl_Condition cond = NULL; - CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent)); - if (ev == NULL) { - PyErr_NoMemory(); - PyMem_DEL(data); - return NULL; - } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; - ev->interp = self->interp; - ev->create = 1; - ev->name = cmdName; - ev->data = (ClientData)data; - ev->status = &err; - ev->done = &cond; - Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex); - Tcl_ConditionFinalize(&cond); - } - else -#endif - { - ENTER_TCL - err = Tcl_CreateCommand( - Tkapp_Interp(self), cmdName, PythonCmd, - (ClientData)data, PythonCmdDelete) == NULL; - LEAVE_TCL - } - if (err) { - PyErr_SetString(Tkinter_TclError, "can't create Tcl command"); - PyMem_DEL(data); - return NULL; - } - - Py_RETURN_NONE; -} - - - -static PyObject * -Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args) -{ - TkappObject *self = (TkappObject*)selfptr; - char *cmdName; - int err; - - if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) - return NULL; - CHECK_STRING_LENGTH(cmdName); - -#ifdef WITH_THREAD - if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { - Tcl_Condition cond = NULL; - CommandEvent *ev; - ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent)); - if (ev == NULL) { - PyErr_NoMemory(); - return NULL; - } - ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; - ev->interp = self->interp; - ev->create = 0; - ev->name = cmdName; - ev->status = &err; - ev->done = &cond; - Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, - &command_mutex); - Tcl_ConditionFinalize(&cond); - } - else -#endif - { - ENTER_TCL - err = Tcl_DeleteCommand(self->interp, cmdName); - LEAVE_TCL - } - if (err == -1) { - PyErr_SetString(Tkinter_TclError, "can't delete Tcl command"); - return NULL; - } - Py_RETURN_NONE; -} - - - -#ifdef HAVE_CREATEFILEHANDLER -/** File Handler **/ - -typedef struct _fhcdata { - PyObject *func; - PyObject *file; - int id; - struct _fhcdata *next; -} FileHandler_ClientData; - -static FileHandler_ClientData *HeadFHCD; - -static FileHandler_ClientData * -NewFHCD(PyObject *func, PyObject *file, int id) -{ - FileHandler_ClientData *p; - p = PyMem_NEW(FileHandler_ClientData, 1); - if (p != NULL) { - Py_XINCREF(func); - Py_XINCREF(file); - p->func = func; - p->file = file; - p->id = id; - p->next = HeadFHCD; - HeadFHCD = p; - } - return p; -} - -static void -DeleteFHCD(int id) -{ - FileHandler_ClientData *p, **pp; - - pp = &HeadFHCD; - while ((p = *pp) != NULL) { - if (p->id == id) { - *pp = p->next; - Py_XDECREF(p->func); - Py_XDECREF(p->file); - PyMem_DEL(p); - } - else - pp = &p->next; - } -} - -static void -FileHandler(ClientData clientData, int mask) -{ - FileHandler_ClientData *data = (FileHandler_ClientData *)clientData; - PyObject *func, *file, *arg, *res; - - ENTER_PYTHON - func = data->func; - file = data->file; - - arg = Py_BuildValue("(Oi)", file, (long) mask); - res = PyEval_CallObject(func, arg); - Py_DECREF(arg); - - if (res == NULL) { - errorInCmd = 1; - PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd); - } - Py_XDECREF(res); - LEAVE_PYTHON -} - -static PyObject * -Tkapp_CreateFileHandler(PyObject *self, PyObject *args) - /* args is (file, mask, func) */ -{ - FileHandler_ClientData *data; - PyObject *file, *func; - int mask, tfile; - - if (!PyArg_ParseTuple(args, "OiO:createfilehandler", - &file, &mask, &func)) - return NULL; - - CHECK_TCL_APPARTMENT; - - tfile = PyObject_AsFileDescriptor(file); - if (tfile < 0) - return NULL; - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, "bad argument list"); - return NULL; - } - - data = NewFHCD(func, file, tfile); - if (data == NULL) - return NULL; - - /* Ought to check for null Tcl_File object... */ - ENTER_TCL - Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data); - LEAVE_TCL - Py_RETURN_NONE; -} - -static PyObject * -Tkapp_DeleteFileHandler(PyObject *self, PyObject *args) -{ - PyObject *file; - int tfile; - - if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file)) - return NULL; - - CHECK_TCL_APPARTMENT; - - tfile = PyObject_AsFileDescriptor(file); - if (tfile < 0) - return NULL; - - DeleteFHCD(tfile); - - /* Ought to check for null Tcl_File object... */ - ENTER_TCL - Tcl_DeleteFileHandler(tfile); - LEAVE_TCL - Py_RETURN_NONE; -} -#endif /* HAVE_CREATEFILEHANDLER */ - - -/**** Tktt Object (timer token) ****/ - -static PyObject *Tktt_Type; - -typedef struct { - PyObject_HEAD - Tcl_TimerToken token; - PyObject *func; -} TkttObject; - -static PyObject * -Tktt_DeleteTimerHandler(PyObject *self, PyObject *args) -{ - TkttObject *v = (TkttObject *)self; - PyObject *func = v->func; - - if (!PyArg_ParseTuple(args, ":deletetimerhandler")) - return NULL; - if (v->token != NULL) { - Tcl_DeleteTimerHandler(v->token); - v->token = NULL; - } - if (func != NULL) { - v->func = NULL; - Py_DECREF(func); - Py_DECREF(v); /* See Tktt_New() */ - } - Py_RETURN_NONE; -} - -static PyMethodDef Tktt_methods[] = -{ - {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS}, - {NULL, NULL} -}; - -static TkttObject * -Tktt_New(PyObject *func) -{ - TkttObject *v; - - v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type); - if (v == NULL) - return NULL; - Py_INCREF(Tktt_Type); - - Py_INCREF(func); - v->token = NULL; - v->func = func; - - /* Extra reference, deleted when called or when handler is deleted */ - Py_INCREF(v); - return v; -} - -static void -Tktt_Dealloc(PyObject *self) -{ - TkttObject *v = (TkttObject *)self; - PyObject *func = v->func; - PyObject *tp = (PyObject *) Py_TYPE(self); - - Py_XDECREF(func); - - PyObject_Del(self); - Py_DECREF(tp); -} - -static PyObject * -Tktt_Repr(PyObject *self) -{ - TkttObject *v = (TkttObject *)self; - return PyUnicode_FromFormat("", - v, - v->func == NULL ? ", handler deleted" : ""); -} - -static PyType_Slot Tktt_Type_slots[] = { - {Py_tp_dealloc, Tktt_Dealloc}, - {Py_tp_repr, Tktt_Repr}, - {Py_tp_methods, Tktt_methods}, - {0, 0} -}; - -static PyType_Spec Tktt_Type_spec = { - "_tkinter.tktimertoken", - sizeof(TkttObject), - 0, - Py_TPFLAGS_DEFAULT, - Tktt_Type_slots, -}; - - -/** Timer Handler **/ - -static void -TimerHandler(ClientData clientData) -{ - TkttObject *v = (TkttObject *)clientData; - PyObject *func = v->func; - PyObject *res; - - if (func == NULL) - return; - - v->func = NULL; - - ENTER_PYTHON - - res = PyEval_CallObject(func, NULL); - Py_DECREF(func); - Py_DECREF(v); /* See Tktt_New() */ - - if (res == NULL) { - errorInCmd = 1; - PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd); - } - else - Py_DECREF(res); - - LEAVE_PYTHON -} - -static PyObject * -Tkapp_CreateTimerHandler(PyObject *self, PyObject *args) -{ - int milliseconds; - PyObject *func; - TkttObject *v; - - if (!PyArg_ParseTuple(args, "iO:createtimerhandler", - &milliseconds, &func)) - return NULL; - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, "bad argument list"); - return NULL; - } - - CHECK_TCL_APPARTMENT; - - v = Tktt_New(func); - if (v) { - v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler, - (ClientData)v); - } - - return (PyObject *) v; -} - - -/** Event Loop **/ - -static PyObject * -Tkapp_MainLoop(PyObject *selfptr, PyObject *args) -{ - int threshold = 0; - TkappObject *self = (TkappObject*)selfptr; -#ifdef WITH_THREAD - PyThreadState *tstate = PyThreadState_Get(); -#endif - - if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold)) - return NULL; - - CHECK_TCL_APPARTMENT; - self->dispatching = 1; - - quitMainLoop = 0; - while (Tk_GetNumMainWindows() > threshold && - !quitMainLoop && - !errorInCmd) - { - int result; - -#ifdef WITH_THREAD - if (self->threaded) { - /* Allow other Python threads to run. */ - ENTER_TCL - result = Tcl_DoOneEvent(0); - LEAVE_TCL - } - else { - Py_BEGIN_ALLOW_THREADS - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); - tcl_tstate = tstate; - result = Tcl_DoOneEvent(TCL_DONT_WAIT); - tcl_tstate = NULL; - if(tcl_lock)PyThread_release_lock(tcl_lock); - if (result == 0) - Sleep(Tkinter_busywaitinterval); - Py_END_ALLOW_THREADS - } -#else - result = Tcl_DoOneEvent(0); -#endif - - if (PyErr_CheckSignals() != 0) { - self->dispatching = 0; - return NULL; - } - if (result < 0) - break; - } - self->dispatching = 0; - quitMainLoop = 0; - - if (errorInCmd) { - errorInCmd = 0; - PyErr_Restore(excInCmd, valInCmd, trbInCmd); - excInCmd = valInCmd = trbInCmd = NULL; - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -Tkapp_DoOneEvent(PyObject *self, PyObject *args) -{ - int flags = 0; - int rv; - - if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags)) - return NULL; - - ENTER_TCL - rv = Tcl_DoOneEvent(flags); - LEAVE_TCL - return Py_BuildValue("i", rv); -} - -static PyObject * -Tkapp_Quit(PyObject *self, PyObject *args) -{ - - if (!PyArg_ParseTuple(args, ":quit")) - return NULL; - - quitMainLoop = 1; - Py_RETURN_NONE; -} - -static PyObject * -Tkapp_InterpAddr(PyObject *self, PyObject *args) -{ - - if (!PyArg_ParseTuple(args, ":interpaddr")) - return NULL; - - return PyLong_FromVoidPtr(Tkapp_Interp(self)); -} - -static PyObject * -Tkapp_TkInit(PyObject *self, PyObject *args) -{ - Tcl_Interp *interp = Tkapp_Interp(self); - const char * _tk_exists = NULL; - int err; - -#ifdef TKINTER_PROTECT_LOADTK - /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the - * first call failed. - * To avoid the deadlock, we just refuse the second call through - * a static variable. - */ - if (tk_load_failed) { - PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG); - return NULL; - } -#endif - - /* We want to guard against calling Tk_Init() multiple times */ - CHECK_TCL_APPARTMENT; - ENTER_TCL - err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version"); - ENTER_OVERLAP - if (err == TCL_ERROR) { - /* This sets an exception, but we cannot return right - away because we need to exit the overlap first. */ - Tkinter_Error(self); - } else { - _tk_exists = Tkapp_Result(self); - } - LEAVE_OVERLAP_TCL - if (err == TCL_ERROR) { - return NULL; - } - if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { - if (Tk_Init(interp) == TCL_ERROR) { - PyErr_SetString(Tkinter_TclError, - Tcl_GetStringResult(Tkapp_Interp(self))); -#ifdef TKINTER_PROTECT_LOADTK - tk_load_failed = 1; -#endif - return NULL; - } - } - Py_RETURN_NONE; -} - -static PyObject * -Tkapp_WantObjects(PyObject *self, PyObject *args) -{ - - int wantobjects = -1; - if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects)) - return NULL; - if (wantobjects == -1) - return PyBool_FromLong(((TkappObject*)self)->wantobjects); - ((TkappObject*)self)->wantobjects = wantobjects; - - Py_RETURN_NONE; -} - -static PyObject * -Tkapp_WillDispatch(PyObject *self, PyObject *args) -{ - - ((TkappObject*)self)->dispatching = 1; - - Py_RETURN_NONE; -} - - -/**** Tkapp Method List ****/ - -static PyMethodDef Tkapp_methods[] = -{ - {"willdispatch", Tkapp_WillDispatch, METH_NOARGS}, - {"wantobjects", Tkapp_WantObjects, METH_VARARGS}, - {"call", Tkapp_Call, METH_VARARGS}, - {"eval", Tkapp_Eval, METH_VARARGS}, - {"evalfile", Tkapp_EvalFile, METH_VARARGS}, - {"record", Tkapp_Record, METH_VARARGS}, - {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS}, - {"setvar", Tkapp_SetVar, METH_VARARGS}, - {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS}, - {"getvar", Tkapp_GetVar, METH_VARARGS}, - {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS}, - {"unsetvar", Tkapp_UnsetVar, METH_VARARGS}, - {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, - {"getint", Tkapp_GetInt, METH_VARARGS}, - {"getdouble", Tkapp_GetDouble, METH_VARARGS}, - {"getboolean", Tkapp_GetBoolean, METH_O}, - {"exprstring", Tkapp_ExprString, METH_VARARGS}, - {"exprlong", Tkapp_ExprLong, METH_VARARGS}, - {"exprdouble", Tkapp_ExprDouble, METH_VARARGS}, - {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS}, - {"splitlist", Tkapp_SplitList, METH_VARARGS}, - {"split", Tkapp_Split, METH_VARARGS}, - {"createcommand", Tkapp_CreateCommand, METH_VARARGS}, - {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS}, -#ifdef HAVE_CREATEFILEHANDLER - {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS}, - {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS}, -#endif - {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS}, - {"mainloop", Tkapp_MainLoop, METH_VARARGS}, - {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS}, - {"quit", Tkapp_Quit, METH_VARARGS}, - {"interpaddr", Tkapp_InterpAddr, METH_VARARGS}, - {"loadtk", Tkapp_TkInit, METH_NOARGS}, - {NULL, NULL} -}; - - - -/**** Tkapp Type Methods ****/ - -static void -Tkapp_Dealloc(PyObject *self) -{ - PyObject *tp = (PyObject *) Py_TYPE(self); - /*CHECK_TCL_APPARTMENT;*/ - ENTER_TCL - Tcl_DeleteInterp(Tkapp_Interp(self)); - LEAVE_TCL - PyObject_Del(self); - Py_DECREF(tp); - DisableEventHook(); -} - -static PyType_Slot Tkapp_Type_slots[] = { - {Py_tp_dealloc, Tkapp_Dealloc}, - {Py_tp_methods, Tkapp_methods}, - {0, 0} -}; - - -static PyType_Spec Tkapp_Type_spec = { - "_tkinter.tkapp", - sizeof(TkappObject), - 0, - Py_TPFLAGS_DEFAULT, - Tkapp_Type_slots, -}; - - - -/**** Tkinter Module ****/ - -typedef struct { - PyObject* tuple; - Py_ssize_t size; /* current size */ - Py_ssize_t maxsize; /* allocated size */ -} FlattenContext; - -static int -_bump(FlattenContext* context, Py_ssize_t size) -{ - /* expand tuple to hold (at least) size new items. - return true if successful, false if an exception was raised */ - - Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */ - - if (maxsize < context->size + size) - maxsize = context->size + size; /* never overflows */ - - context->maxsize = maxsize; - - return _PyTuple_Resize(&context->tuple, maxsize) >= 0; -} - -static int -_flatten1(FlattenContext* context, PyObject* item, int depth) -{ - /* add tuple or list to argument tuple (recursively) */ - - Py_ssize_t i, size; - - if (depth > 1000) { - PyErr_SetString(PyExc_ValueError, - "nesting too deep in _flatten"); - return 0; - } else if (PyTuple_Check(item) || PyList_Check(item)) { - size = PySequence_Fast_GET_SIZE(item); - /* preallocate (assume no nesting) */ - if (context->size + size > context->maxsize && - !_bump(context, size)) - return 0; - /* copy items to output tuple */ - for (i = 0; i < size; i++) { - PyObject *o = PySequence_Fast_GET_ITEM(item, i); - if (PyList_Check(o) || PyTuple_Check(o)) { - if (!_flatten1(context, o, depth + 1)) - return 0; - } else if (o != Py_None) { - if (context->size + 1 > context->maxsize && - !_bump(context, 1)) - return 0; - Py_INCREF(o); - PyTuple_SET_ITEM(context->tuple, - context->size++, o); - } - } - } else { - PyErr_SetString(PyExc_TypeError, "argument must be sequence"); - return 0; - } - return 1; -} - -static PyObject * -Tkinter_Flatten(PyObject* self, PyObject* args) -{ - FlattenContext context; - PyObject* item; - - if (!PyArg_ParseTuple(args, "O:_flatten", &item)) - return NULL; - - context.maxsize = PySequence_Size(item); - if (context.maxsize < 0) - return NULL; - if (context.maxsize == 0) - return PyTuple_New(0); - - context.tuple = PyTuple_New(context.maxsize); - if (!context.tuple) - return NULL; - - context.size = 0; - - if (!_flatten1(&context, item,0)) - return NULL; - - if (_PyTuple_Resize(&context.tuple, context.size)) - return NULL; - - return context.tuple; -} - -static PyObject * -Tkinter_Create(PyObject *self, PyObject *args) -{ - char *screenName = NULL; - char *baseName = NULL; /* XXX this is not used anymore; - try getting rid of it. */ - char *className = NULL; - int interactive = 0; - int wantobjects = 1; - int wantTk = 1; /* If false, then Tk_Init() doesn't get called */ - int sync = 0; /* pass -sync to wish */ - char *use = NULL; /* pass -use to wish */ - - className = "Tk"; - - if (!PyArg_ParseTuple(args, "|zssiiiiz:create", - &screenName, &baseName, &className, - &interactive, &wantobjects, &wantTk, - &sync, &use)) - return NULL; - CHECK_STRING_LENGTH(screenName); - CHECK_STRING_LENGTH(baseName); - CHECK_STRING_LENGTH(className); - CHECK_STRING_LENGTH(use); - - return (PyObject *) Tkapp_New(screenName, className, - interactive, wantobjects, wantTk, - sync, use); -} - -static PyObject * -Tkinter_setbusywaitinterval(PyObject *self, PyObject *args) -{ - int new_val; - if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val)) - return NULL; - if (new_val < 0) { - PyErr_SetString(PyExc_ValueError, - "busywaitinterval must be >= 0"); - return NULL; - } - Tkinter_busywaitinterval = new_val; - Py_RETURN_NONE; -} - -static char setbusywaitinterval_doc[] = -"setbusywaitinterval(n) -> None\n\ -\n\ -Set the busy-wait interval in milliseconds between successive\n\ -calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\ -It should be set to a divisor of the maximum time between\n\ -frames in an animation."; - -static PyObject * -Tkinter_getbusywaitinterval(PyObject *self, PyObject *args) -{ - return PyLong_FromLong(Tkinter_busywaitinterval); -} - -static char getbusywaitinterval_doc[] = -"getbusywaitinterval() -> int\n\ -\n\ -Return the current busy-wait interval between successive\n\ -calls to Tcl_DoOneEvent in a threaded Python interpreter."; - -static PyMethodDef moduleMethods[] = -{ - {"_flatten", Tkinter_Flatten, METH_VARARGS}, - {"create", Tkinter_Create, METH_VARARGS}, - {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS, - setbusywaitinterval_doc}, - {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval, - METH_NOARGS, getbusywaitinterval_doc}, - {NULL, NULL} -}; - -#ifdef WAIT_FOR_STDIN - -static int stdin_ready = 0; - -#ifndef MS_WINDOWS -static void -MyFileProc(void *clientData, int mask) -{ - stdin_ready = 1; -} -#endif - -#ifdef WITH_THREAD -static PyThreadState *event_tstate = NULL; -#endif - -static int -EventHook(void) -{ -#ifndef MS_WINDOWS - int tfile; -#endif -#ifdef WITH_THREAD - PyEval_RestoreThread(event_tstate); -#endif - stdin_ready = 0; - errorInCmd = 0; -#ifndef MS_WINDOWS - tfile = fileno(stdin); - Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL); -#endif - while (!errorInCmd && !stdin_ready) { - int result; -#ifdef MS_WINDOWS - if (_kbhit()) { - stdin_ready = 1; - break; - } -#endif -#if defined(WITH_THREAD) || defined(MS_WINDOWS) - Py_BEGIN_ALLOW_THREADS - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); - tcl_tstate = event_tstate; - - result = Tcl_DoOneEvent(TCL_DONT_WAIT); - - tcl_tstate = NULL; - if(tcl_lock)PyThread_release_lock(tcl_lock); - if (result == 0) - Sleep(Tkinter_busywaitinterval); - Py_END_ALLOW_THREADS -#else - result = Tcl_DoOneEvent(0); -#endif - - if (result < 0) - break; - } -#ifndef MS_WINDOWS - Tcl_DeleteFileHandler(tfile); -#endif - if (errorInCmd) { - errorInCmd = 0; - PyErr_Restore(excInCmd, valInCmd, trbInCmd); - excInCmd = valInCmd = trbInCmd = NULL; - PyErr_Print(); - } -#ifdef WITH_THREAD - PyEval_SaveThread(); -#endif - return 0; -} - -#endif - -static void -EnableEventHook(void) -{ -#ifdef WAIT_FOR_STDIN - if (PyOS_InputHook == NULL) { -#ifdef WITH_THREAD - event_tstate = PyThreadState_Get(); -#endif - PyOS_InputHook = EventHook; - } -#endif -} - -static void -DisableEventHook(void) -{ -#ifdef WAIT_FOR_STDIN - if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) { - PyOS_InputHook = NULL; - } -#endif -} - - -static struct PyModuleDef _tkintermodule = { - PyModuleDef_HEAD_INIT, - "_tkinter", - NULL, - -1, - moduleMethods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__tkinter(void) -{ - PyObject *m, *uexe, *cexe, *o; - -#ifdef WITH_THREAD - tcl_lock = PyThread_allocate_lock(); - if (tcl_lock == NULL) - return NULL; -#endif - - m = PyModule_Create(&_tkintermodule); - if (m == NULL) - return NULL; - - o = PyErr_NewException("_tkinter.TclError", NULL, NULL); - if (o == NULL) { - Py_DECREF(m); - return NULL; - } - Py_INCREF(o); - if (PyModule_AddObject(m, "TclError", o)) { - Py_DECREF(o); - Py_DECREF(m); - return NULL; - } - Tkinter_TclError = o; - - if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) { - Py_DECREF(m); - return NULL; - } - - o = PyType_FromSpec(&Tkapp_Type_spec); - if (o == NULL) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddObject(m, "TkappType", o)) { - Py_DECREF(o); - Py_DECREF(m); - return NULL; - } - Tkapp_Type = o; - - o = PyType_FromSpec(&Tktt_Type_spec); - if (o == NULL) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddObject(m, "TkttType", o)) { - Py_DECREF(o); - Py_DECREF(m); - return NULL; - } - Tktt_Type = o; - - o = PyType_FromSpec(&PyTclObject_Type_spec); - if (o == NULL) { - Py_DECREF(m); - return NULL; - } - if (PyModule_AddObject(m, "Tcl_Obj", o)) { - Py_DECREF(o); - Py_DECREF(m); - return NULL; - } - PyTclObject_Type = o; - -#ifdef TK_AQUA - /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems - * start waking up. Note that Tcl_FindExecutable will do this, this - * code must be above it! The original warning from - * tkMacOSXAppInit.c is copied below. - * - * NB - You have to swap in the Tk Notifier BEFORE you start up the - * Tcl interpreter for now. It probably should work to do this - * in the other order, but for now it doesn't seem to. - * - */ - Tk_MacOSXSetupTkNotifier(); -#endif - - - /* This helps the dynamic loader; in Unicode aware Tcl versions - it also helps Tcl find its encodings. */ - uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1); - if (uexe) { - cexe = PyUnicode_EncodeFSDefault(uexe); - if (cexe) - Tcl_FindExecutable(PyBytes_AsString(cexe)); - Py_XDECREF(cexe); - Py_DECREF(uexe); - } - - if (PyErr_Occurred()) { - Py_DECREF(m); - return NULL; - } - -#if 0 - /* This was not a good idea; through bindings, - Tcl_Finalize() may invoke Python code but at that point the - interpreter and thread state have already been destroyed! */ - Py_AtExit(Tcl_Finalize); -#endif - return m; -} +#ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF + #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF +#endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ +/*[clinic end generated code: output=6dd667b91cf8addd input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 15:18:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 03 May 2015 13:18:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320179=3A_Converte?= =?utf-8?q?d_the_=5Fssl_module_to_Argument_Clinic=2E?= Message-ID: <20150503131846.11948.14811@psf.io> https://hg.python.org/cpython/rev/1eaaf27b3956 changeset: 95869:1eaaf27b3956 user: Serhiy Storchaka date: Sun May 03 16:14:08 2015 +0300 summary: Issue #20179: Converted the _ssl module to Argument Clinic. files: Modules/_ssl.c | 1032 +++--- Modules/_ssl.c | 5604 ++++++----------------------------- 2 files changed, 1542 insertions(+), 5094 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -221,11 +221,17 @@ static PyTypeObject PySSLSocket_Type; static PyTypeObject PySSLMemoryBIO_Type; -static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); -static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); +/*[clinic input] +module _ssl +class _ssl._SSLContext "PySSLContext *" "&PySSLContext_Type" +class _ssl._SSLSocket "PySSLSocket *" "&PySSLSocket_Type" +class _ssl.MemoryBIO "PySSLMemoryBIO *" "&PySSLMemoryBIO_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7bf7cb832638e2e1]*/ + +#include "clinic/_ssl.c.h" + static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); -static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); -static PyObject *PySSL_cipher(PySSLSocket *self); #define PySSLContext_Check(v) (Py_TYPE(v) == &PySSLContext_Type) #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) @@ -563,7 +569,13 @@ /* SSL object methods */ -static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) +/*[clinic input] +_ssl._SSLSocket.do_handshake +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) +/*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/ { int ret; int err; @@ -1303,25 +1315,28 @@ return retval; } +/*[clinic input] +_ssl._test_decode_cert + path: object(converter="PyUnicode_FSConverter") + / + +[clinic start generated code]*/ + static PyObject * -PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { - +_ssl__test_decode_cert_impl(PyModuleDef *module, PyObject *path) +/*[clinic end generated code: output=679e01db282804e9 input=cdeaaf02d4346628]*/ +{ PyObject *retval = NULL; - PyObject *filename; X509 *x=NULL; BIO *cert; - if (!PyArg_ParseTuple(args, "O&:test_decode_certificate", - PyUnicode_FSConverter, &filename)) - return NULL; - if ((cert=BIO_new(BIO_s_file())) == NULL) { PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); goto fail0; } - if (BIO_read_filename(cert, PyBytes_AsString(filename)) <= 0) { + if (BIO_read_filename(cert, PyBytes_AsString(path)) <= 0) { PyErr_SetString(PySSLErrorObject, "Can't open file"); goto fail0; @@ -1338,20 +1353,33 @@ X509_free(x); fail0: - Py_DECREF(filename); + Py_DECREF(path); if (cert != NULL) BIO_free(cert); return retval; } +/*[clinic input] +_ssl._SSLSocket.peer_certificate + der as binary_mode: bool = False + / + +Returns the certificate for the peer. + +If no certificate was provided, returns None. If a certificate was +provided, but not validated, returns an empty dictionary. Otherwise +returns a dict containing information about the peer certificate. + +If the optional argument is True, returns a DER-encoded copy of the +peer certificate, or None if no certificate was provided. This will +return the certificate even if it wasn't validated. +[clinic start generated code]*/ + static PyObject * -PySSL_peercert(PySSLSocket *self, PyObject *args) +_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode) +/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/ { int verification; - int binary_mode = 0; - - if (!PyArg_ParseTuple(args, "|p:peer_certificate", &binary_mode)) - return NULL; if (!self->handshake_done) { PyErr_SetString(PyExc_ValueError, @@ -1373,18 +1401,6 @@ } } -PyDoc_STRVAR(PySSL_peercert_doc, -"peer_certificate([der=False]) -> certificate\n\ -\n\ -Returns the certificate for the peer. If no certificate was provided,\n\ -returns None. If a certificate was provided, but not validated, returns\n\ -an empty dictionary. Otherwise returns a dict containing information\n\ -about the peer certificate.\n\ -\n\ -If the optional argument is True, returns a DER-encoded copy of the\n\ -peer certificate, or None if no certificate was provided. This will\n\ -return the certificate even if it wasn't validated."); - static PyObject * cipher_to_tuple(const SSL_CIPHER *cipher) { @@ -1427,7 +1443,13 @@ return NULL; } -static PyObject *PySSL_shared_ciphers(PySSLSocket *self) +/*[clinic input] +_ssl._SSLSocket.shared_ciphers +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_shared_ciphers_impl(PySSLSocket *self) +/*[clinic end generated code: output=3d174ead2e42c4fd input=0bfe149da8fe6306]*/ { SSL_SESSION *sess = SSL_get_session(self->ssl); STACK_OF(SSL_CIPHER) *ciphers; @@ -1451,7 +1473,13 @@ return res; } -static PyObject *PySSL_cipher (PySSLSocket *self) +/*[clinic input] +_ssl._SSLSocket.cipher +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_cipher_impl(PySSLSocket *self) +/*[clinic end generated code: output=376417c16d0e5815 input=548fb0e27243796d]*/ { const SSL_CIPHER *current; @@ -1463,7 +1491,13 @@ return cipher_to_tuple(current); } -static PyObject *PySSL_version(PySSLSocket *self) +/*[clinic input] +_ssl._SSLSocket.version +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_version_impl(PySSLSocket *self) +/*[clinic end generated code: output=178aed33193b2cdb input=900186a503436fd6]*/ { const char *version; @@ -1476,7 +1510,14 @@ } #ifdef OPENSSL_NPN_NEGOTIATED -static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { +/*[clinic input] +_ssl._SSLSocket.selected_npn_protocol +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self) +/*[clinic end generated code: output=b91d494cd207ecf6 input=c28fde139204b826]*/ +{ const unsigned char *out; unsigned int outlen; @@ -1490,7 +1531,14 @@ #endif #ifdef HAVE_ALPN -static PyObject *PySSL_selected_alpn_protocol(PySSLSocket *self) { +/*[clinic input] +_ssl._SSLSocket.selected_alpn_protocol +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_selected_alpn_protocol_impl(PySSLSocket *self) +/*[clinic end generated code: output=ec33688b303d250f input=442de30e35bc2913]*/ +{ const unsigned char *out; unsigned int outlen; @@ -1502,7 +1550,14 @@ } #endif -static PyObject *PySSL_compression(PySSLSocket *self) { +/*[clinic input] +_ssl._SSLSocket.compression +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_compression_impl(PySSLSocket *self) +/*[clinic end generated code: output=bd16cb1bb4646ae7 input=5d059d0a2bbc32c8]*/ +{ #ifdef OPENSSL_NO_COMP Py_RETURN_NONE; #else @@ -1689,9 +1744,20 @@ return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; } -static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) +/*[clinic input] +_ssl._SSLSocket.write + b: Py_buffer + / + +Writes the bytes-like object b into the SSL object. + +Returns the number of bytes written. +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) +/*[clinic end generated code: output=aa7a6be5527358d8 input=77262d994fe5100a]*/ { - Py_buffer buf; int len; int sockstate; int err; @@ -1709,12 +1775,7 @@ Py_INCREF(sock); } - if (!PyArg_ParseTuple(args, "y*:write", &buf)) { - Py_XDECREF(sock); - return NULL; - } - - if (buf.len > INT_MAX) { + if (b->len > INT_MAX) { PyErr_Format(PyExc_OverflowError, "string longer than %d bytes", INT_MAX); goto error; @@ -1749,7 +1810,7 @@ do { PySSL_BEGIN_ALLOW_THREADS - len = SSL_write(self->ssl, buf.buf, (int)buf.len); + len = SSL_write(self->ssl, b->buf, (int)b->len); err = SSL_get_error(self->ssl, len); PySSL_END_ALLOW_THREADS @@ -1781,7 +1842,6 @@ } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); Py_XDECREF(sock); - PyBuffer_Release(&buf); if (len > 0) return PyLong_FromLong(len); else @@ -1789,17 +1849,18 @@ error: Py_XDECREF(sock); - PyBuffer_Release(&buf); return NULL; } -PyDoc_STRVAR(PySSL_SSLwrite_doc, -"write(s) -> len\n\ -\n\ -Writes the string s into the SSL object. Returns the number\n\ -of bytes written."); - -static PyObject *PySSL_SSLpending(PySSLSocket *self) +/*[clinic input] +_ssl._SSLSocket.pending + +Returns the number of already decrypted bytes available for read, pending on the connection. +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_pending_impl(PySSLSocket *self) +/*[clinic end generated code: output=983d9fecdc308a83 input=2b77487d6dfd597f]*/ { int count = 0; @@ -1812,19 +1873,25 @@ return PyLong_FromLong(count); } -PyDoc_STRVAR(PySSL_SSLpending_doc, -"pending() -> count\n\ -\n\ -Returns the number of already decrypted bytes available for read,\n\ -pending on the connection.\n"); - -static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) +/*[clinic input] +_ssl._SSLSocket.read + size as len: int + [ + buffer: Py_buffer(types={'rwbuffer'}) + ] + / + +Read up to size bytes from the SSL socket. +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, + Py_buffer *buffer) +/*[clinic end generated code: output=00097776cec2a0af input=4a0bbd2859e817b0]*/ { PyObject *dest = NULL; - Py_buffer buf; char *mem; - int len, count; - int buf_passed = 0; + int count; int sockstate; int err; int nonblocking; @@ -1841,23 +1908,17 @@ Py_INCREF(sock); } - buf.obj = NULL; - buf.buf = NULL; - if (!PyArg_ParseTuple(args, "i|w*:read", &len, &buf)) - goto error; - - if ((buf.buf == NULL) && (buf.obj == NULL)) { + if (!group_right_1) { dest = PyBytes_FromStringAndSize(NULL, len); if (dest == NULL) goto error; mem = PyBytes_AS_STRING(dest); } else { - buf_passed = 1; - mem = buf.buf; - if (len <= 0 || len > buf.len) { - len = (int) buf.len; - if (buf.len != len) { + mem = buffer->buf; + if (len <= 0 || len > buffer->len) { + len = (int) buffer->len; + if (buffer->len != len) { PyErr_SetString(PyExc_OverflowError, "maximum length can't fit in a C 'int'"); goto error; @@ -1918,30 +1979,32 @@ done: Py_XDECREF(sock); - if (!buf_passed) { + if (!group_right_1) { _PyBytes_Resize(&dest, count); return dest; } else { - PyBuffer_Release(&buf); return PyLong_FromLong(count); } error: Py_XDECREF(sock); - if (!buf_passed) + if (!group_right_1) Py_XDECREF(dest); - else - PyBuffer_Release(&buf); return NULL; } -PyDoc_STRVAR(PySSL_SSLread_doc, -"read([len]) -> string\n\ -\n\ -Read up to len bytes from the SSL socket."); - -static PyObject *PySSL_SSLshutdown(PySSLSocket *self) +/*[clinic input] +_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]*/ { int err, ssl_err, sockstate, nonblocking; int zeros = 0; @@ -2044,14 +2107,17 @@ return NULL; } -PyDoc_STRVAR(PySSL_SSLshutdown_doc, -"shutdown(s) -> socket\n\ -\n\ -Does the SSL shutdown handshake with the remote end, and returns\n\ -the underlying socket object."); +/*[clinic input] +_ssl._SSLSocket.tls_unique_cb + +Returns the 'tls-unique' channel binding data, as defined by RFC 5929. + +If the TLS handshake is not yet complete, None is returned. +[clinic start generated code]*/ static PyObject * -PySSL_tls_unique_cb(PySSLSocket *self) +_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self) +/*[clinic end generated code: output=f3a832d603f586af input=439525c7b3d8d34d]*/ { PyObject *retval = NULL; char buf[PySSL_CB_MAXLEN]; @@ -2075,13 +2141,6 @@ return retval; } -PyDoc_STRVAR(PySSL_tls_unique_cb_doc, -"tls_unique_cb() -> bytes\n\ -\n\ -Returns the 'tls-unique' channel binding data, as defined by RFC 5929.\n\ -\n\ -If the TLS handshake is not yet complete, None is returned"); - static PyGetSetDef ssl_getsetlist[] = { {"context", (getter) PySSL_get_context, (setter) PySSL_set_context, PySSL_set_context_doc}, @@ -2095,29 +2154,19 @@ }; static PyMethodDef PySSLMethods[] = { - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, - PySSL_SSLwrite_doc}, - {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, - PySSL_SSLread_doc}, - {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, - PySSL_SSLpending_doc}, - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, - {"shared_ciphers", (PyCFunction)PySSL_shared_ciphers, METH_NOARGS}, - {"version", (PyCFunction)PySSL_version, METH_NOARGS}, -#ifdef OPENSSL_NPN_NEGOTIATED - {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, -#endif -#ifdef HAVE_ALPN - {"selected_alpn_protocol", (PyCFunction)PySSL_selected_alpn_protocol, METH_NOARGS}, -#endif - {"compression", (PyCFunction)PySSL_compression, METH_NOARGS}, - {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, - PySSL_SSLshutdown_doc}, - {"tls_unique_cb", (PyCFunction)PySSL_tls_unique_cb, METH_NOARGS, - PySSL_tls_unique_cb_doc}, + _SSL__SSLSOCKET_DO_HANDSHAKE_METHODDEF + _SSL__SSLSOCKET_WRITE_METHODDEF + _SSL__SSLSOCKET_READ_METHODDEF + _SSL__SSLSOCKET_PENDING_METHODDEF + _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF + _SSL__SSLSOCKET_CIPHER_METHODDEF + _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF + _SSL__SSLSOCKET_VERSION_METHODDEF + _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF + _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF + _SSL__SSLSOCKET_COMPRESSION_METHODDEF + _SSL__SSLSOCKET_SHUTDOWN_METHODDEF + _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF {NULL, NULL} }; @@ -2160,20 +2209,21 @@ * _SSLContext objects */ +/*[clinic input] + at classmethod +_ssl._SSLContext.__new__ + protocol as proto_version: int + / +[clinic start generated code]*/ + static PyObject * -context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +_ssl__SSLContext_impl(PyTypeObject *type, int proto_version) +/*[clinic end generated code: output=2cf0d7a0741b6bd1 input=8d58a805b95fc534]*/ { - char *kwlist[] = {"protocol", NULL}; PySSLContext *self; - int proto_version = PY_SSL_VERSION_SSL23; long options; SSL_CTX *ctx = NULL; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "i:_SSLContext", kwlist, - &proto_version)) - return NULL; - PySSL_BEGIN_ALLOW_THREADS if (proto_version == PY_SSL_VERSION_TLS1) ctx = SSL_CTX_new(TLSv1_method()); @@ -2297,15 +2347,17 @@ Py_TYPE(self)->tp_free(self); } +/*[clinic input] +_ssl._SSLContext.set_ciphers + cipherlist: str + / +[clinic start generated code]*/ + static PyObject * -set_ciphers(PySSLContext *self, PyObject *args) +_ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist) +/*[clinic end generated code: output=3a3162f3557c0f3f input=a7ac931b9f3ca7fc]*/ { - int ret; - const char *cipherlist; - - if (!PyArg_ParseTuple(args, "s:set_ciphers", &cipherlist)) - return NULL; - ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist); + int ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist); if (ret == 0) { /* Clearing the error queue is necessary on some OpenSSL versions, otherwise the error will be reported again when another SSL call @@ -2374,26 +2426,24 @@ } #endif +/*[clinic input] +_ssl._SSLContext._set_npn_protocols + protos: Py_buffer + / +[clinic start generated code]*/ + static PyObject * -_set_npn_protocols(PySSLContext *self, PyObject *args) +_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, + Py_buffer *protos) +/*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { #ifdef OPENSSL_NPN_NEGOTIATED - Py_buffer protos; - - if (!PyArg_ParseTuple(args, "y*:set_npn_protocols", &protos)) - return NULL; - - if (self->npn_protocols != NULL) { - PyMem_Free(self->npn_protocols); - } - - self->npn_protocols = PyMem_Malloc(protos.len); - if (self->npn_protocols == NULL) { - PyBuffer_Release(&protos); + PyMem_Free(self->npn_protocols); + self->npn_protocols = PyMem_Malloc(protos->len); + if (self->npn_protocols == NULL) return PyErr_NoMemory(); - } - memcpy(self->npn_protocols, protos.buf, protos.len); - self->npn_protocols_len = (int) protos.len; + memcpy(self->npn_protocols, protos->buf, protos->len); + self->npn_protocols_len = (int) protos->len; /* set both server and client callbacks, because the context can * be used to create both types of sockets */ @@ -2404,7 +2454,6 @@ _selectNPN_cb, self); - PyBuffer_Release(&protos); Py_RETURN_NONE; #else PyErr_SetString(PyExc_NotImplementedError, @@ -2427,28 +2476,29 @@ } #endif +/*[clinic input] +_ssl._SSLContext._set_alpn_protocols + protos: Py_buffer + / +[clinic start generated code]*/ + static PyObject * -_set_alpn_protocols(PySSLContext *self, PyObject *args) +_ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, + Py_buffer *protos) +/*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ { #ifdef HAVE_ALPN - Py_buffer protos; - - if (!PyArg_ParseTuple(args, "y*:set_npn_protocols", &protos)) - return NULL; - PyMem_FREE(self->alpn_protocols); - self->alpn_protocols = PyMem_Malloc(protos.len); + self->alpn_protocols = PyMem_Malloc(protos->len); if (!self->alpn_protocols) return PyErr_NoMemory(); - memcpy(self->alpn_protocols, protos.buf, protos.len); - self->alpn_protocols_len = protos.len; - PyBuffer_Release(&protos); + memcpy(self->alpn_protocols, protos->buf, protos->len); + self->alpn_protocols_len = protos->len; if (SSL_CTX_set_alpn_protos(self->ctx, self->alpn_protocols, self->alpn_protocols_len)) return PyErr_NoMemory(); SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self); - PyBuffer_Release(&protos); Py_RETURN_NONE; #else PyErr_SetString(PyExc_NotImplementedError, @@ -2693,11 +2743,19 @@ return -1; } +/*[clinic input] +_ssl._SSLContext.load_cert_chain + certfile: object + keyfile: object = NULL + password: object = NULL + +[clinic start generated code]*/ + static PyObject * -load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) +_ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, + PyObject *keyfile, PyObject *password) +/*[clinic end generated code: output=9480bc1c380e2095 input=7cf9ac673cbee6fc]*/ { - char *kwlist[] = {"certfile", "keyfile", "password", NULL}; - PyObject *certfile, *keyfile = NULL, *password = NULL; PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL; pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; @@ -2706,10 +2764,6 @@ errno = 0; ERR_clear_error(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|OO:load_cert_chain", kwlist, - &certfile, &keyfile, &password)) - return NULL; if (keyfile == Py_None) keyfile = NULL; if (!PyUnicode_FSConverter(certfile, &certfile_bytes)) { @@ -2877,21 +2931,26 @@ } +/*[clinic input] +_ssl._SSLContext.load_verify_locations + cafile: object = NULL + capath: object = NULL + cadata: object = NULL + +[clinic start generated code]*/ + static PyObject * -load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds) +_ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, + PyObject *cafile, + PyObject *capath, + PyObject *cadata) +/*[clinic end generated code: output=454c7e41230ca551 input=997f1fb3a784ef88]*/ { - char *kwlist[] = {"cafile", "capath", "cadata", NULL}; - PyObject *cafile = NULL, *capath = NULL, *cadata = NULL; PyObject *cafile_bytes = NULL, *capath_bytes = NULL; const char *cafile_buf = NULL, *capath_buf = NULL; int r = 0, ok = 1; errno = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "|OOO:load_verify_locations", kwlist, - &cafile, &capath, &cadata)) - return NULL; - if (cafile == Py_None) cafile = NULL; if (capath == Py_None) @@ -2988,8 +3047,16 @@ } } +/*[clinic input] +_ssl._SSLContext.load_dh_params + path as filepath: object + / + +[clinic start generated code]*/ + static PyObject * -load_dh_params(PySSLContext *self, PyObject *filepath) +_ssl__SSLContext_load_dh_params(PySSLContext *self, PyObject *filepath) +/*[clinic end generated code: output=1c8e57a38e055af0 input=c8871f3c796ae1d6]*/ { FILE *f; DH *dh; @@ -3019,53 +3086,57 @@ Py_RETURN_NONE; } +/*[clinic input] +_ssl._SSLContext._wrap_socket + sock: object(subclass_of="PySocketModule.Sock_Type") + server_side: int + server_hostname as hostname_obj: object = None + +[clinic start generated code]*/ + static PyObject * -context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds) +_ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, + int server_side, PyObject *hostname_obj) +/*[clinic end generated code: output=6973e4b60995e933 input=83859b9156ddfc63]*/ { - char *kwlist[] = {"sock", "server_side", "server_hostname", NULL}; - PySocketSockObject *sock; - int server_side = 0; char *hostname = NULL; - PyObject *hostname_obj, *res; + PyObject *res; /* server_hostname is either None (or absent), or to be encoded using the idna encoding. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i|O!:_wrap_socket", kwlist, - PySocketModule.Sock_Type, - &sock, &server_side, - Py_TYPE(Py_None), &hostname_obj)) { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!iet:_wrap_socket", kwlist, - PySocketModule.Sock_Type, - &sock, &server_side, - "idna", &hostname)) + if (hostname_obj != Py_None) { + if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) return NULL; } - res = (PyObject *) newPySSLSocket(self, sock, server_side, hostname, + res = (PyObject *) newPySSLSocket(self, (PySocketSockObject *)sock, + server_side, hostname, NULL, NULL); if (hostname != NULL) PyMem_Free(hostname); return res; } +/*[clinic input] +_ssl._SSLContext._wrap_bio + incoming: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") + outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") + server_side: int + server_hostname as hostname_obj: object = None + +[clinic start generated code]*/ + static PyObject * -context_wrap_bio(PySSLContext *self, PyObject *args, PyObject *kwds) +_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]*/ { - char *kwlist[] = {"incoming", "outgoing", "server_side", - "server_hostname", NULL}; - int server_side; char *hostname = NULL; - PyObject *hostname_obj = Py_None, *res; - PySSLMemoryBIO *incoming, *outgoing; + PyObject *res; /* server_hostname is either None (or absent), or to be encoded using the idna encoding. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!i|O:_wrap_bio", kwlist, - &PySSLMemoryBIO_Type, &incoming, - &PySSLMemoryBIO_Type, &outgoing, - &server_side, &hostname_obj)) - return NULL; if (hostname_obj != Py_None) { if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) return NULL; @@ -3078,8 +3149,13 @@ return res; } +/*[clinic input] +_ssl._SSLContext.session_stats +[clinic start generated code]*/ + static PyObject * -session_stats(PySSLContext *self, PyObject *unused) +_ssl__SSLContext_session_stats_impl(PySSLContext *self) +/*[clinic end generated code: output=0d96411c42893bfb input=7e0a81fb11102c8b]*/ { int r; PyObject *value, *stats = PyDict_New(); @@ -3117,8 +3193,13 @@ return NULL; } +/*[clinic input] +_ssl._SSLContext.set_default_verify_paths +[clinic start generated code]*/ + static PyObject * -set_default_verify_paths(PySSLContext *self, PyObject *unused) +_ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self) +/*[clinic end generated code: output=0bee74e6e09deaaa input=35f3408021463d74]*/ { if (!SSL_CTX_set_default_verify_paths(self->ctx)) { _setSSLError(NULL, 0, __FILE__, __LINE__); @@ -3128,8 +3209,16 @@ } #ifndef OPENSSL_NO_ECDH +/*[clinic input] +_ssl._SSLContext.set_ecdh_curve + name: object + / + +[clinic start generated code]*/ + static PyObject * -set_ecdh_curve(PySSLContext *self, PyObject *name) +_ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name) +/*[clinic end generated code: output=23022c196e40d7d2 input=c2bafb6f6e34726b]*/ { PyObject *name_bytes; int nid; @@ -3263,25 +3352,23 @@ } #endif -PyDoc_STRVAR(PySSL_set_servername_callback_doc, -"set_servername_callback(method)\n\ -\n\ -This sets a callback that will be called when a server name is provided by\n\ -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.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 * -set_servername_callback(PySSLContext *self, PyObject *args) +_ssl__SSLContext_set_servername_callback(PySSLContext *self, PyObject *cb) +/*[clinic end generated code: output=3439a1b2d5d3b7ea input=a2a83620197d602b]*/ { #if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) - PyObject *cb; - - if (!PyArg_ParseTuple(args, "O", &cb)) - return NULL; - Py_CLEAR(self->set_hostname); if (cb == Py_None) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); @@ -3308,17 +3395,21 @@ #endif } -PyDoc_STRVAR(PySSL_get_stats_doc, -"cert_store_stats() -> {'crl': int, 'x509_ca': int, 'x509': int}\n\ -\n\ -Returns quantities of loaded X.509 certificates. X.509 certificates with a\n\ -CA extension and certificate revocation lists inside the context's cert\n\ -store.\n\ -NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -been used at least once."); +/*[clinic input] +_ssl._SSLContext.cert_store_stats + +Returns quantities of loaded X.509 certificates. + +X.509 certificates with a CA extension and certificate revocation lists +inside the context's cert store. + +NOTE: Certificates in a capath directory aren't loaded unless they have +been used at least once. +[clinic start generated code]*/ static PyObject * -cert_store_stats(PySSLContext *self) +_ssl__SSLContext_cert_store_stats_impl(PySSLContext *self) +/*[clinic end generated code: output=5f356f4d9cca874d input=eb40dd0f6d0e40cf]*/ { X509_STORE *store; X509_OBJECT *obj; @@ -3351,27 +3442,26 @@ "x509_ca", ca); } -PyDoc_STRVAR(PySSL_get_ca_certs_doc, -"get_ca_certs(binary_form=False) -> list of loaded certificate\n\ -\n\ -Returns a list of dicts with information of loaded CA certs. If the\n\ -optional argument is True, returns a DER-encoded copy of the CA certificate.\n\ -NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -been used at least once."); +/*[clinic input] +_ssl._SSLContext.get_ca_certs + binary_form: bool = False + +Returns a list of dicts with information of loaded CA certs. + +If the optional argument is True, returns a DER-encoded copy of the CA +certificate. + +NOTE: Certificates in a capath directory aren't loaded unless they have +been used at least once. +[clinic start generated code]*/ static PyObject * -get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds) +_ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) +/*[clinic end generated code: output=0d58f148f37e2938 input=6887b5a09b7f9076]*/ { - char *kwlist[] = {"binary_form", NULL}; X509_STORE *store; PyObject *ci = NULL, *rlist = NULL; int i; - int binary_mode = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|p:get_ca_certs", - kwlist, &binary_mode)) { - return NULL; - } if ((rlist = PyList_New(0)) == NULL) { return NULL; @@ -3392,7 +3482,7 @@ if (!X509_check_ca(cert)) { continue; } - if (binary_mode) { + if (binary_form) { ci = _certificate_to_der(cert); } else { ci = _decode_certificate(cert); @@ -3427,36 +3517,20 @@ }; static struct PyMethodDef context_methods[] = { - {"_wrap_socket", (PyCFunction) context_wrap_socket, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"_wrap_bio", (PyCFunction) context_wrap_bio, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"set_ciphers", (PyCFunction) set_ciphers, - METH_VARARGS, NULL}, - {"_set_alpn_protocols", (PyCFunction) _set_alpn_protocols, - METH_VARARGS, NULL}, - {"_set_npn_protocols", (PyCFunction) _set_npn_protocols, - METH_VARARGS, NULL}, - {"load_cert_chain", (PyCFunction) load_cert_chain, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"load_dh_params", (PyCFunction) load_dh_params, - METH_O, NULL}, - {"load_verify_locations", (PyCFunction) load_verify_locations, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"session_stats", (PyCFunction) session_stats, - METH_NOARGS, NULL}, - {"set_default_verify_paths", (PyCFunction) set_default_verify_paths, - METH_NOARGS, NULL}, -#ifndef OPENSSL_NO_ECDH - {"set_ecdh_curve", (PyCFunction) set_ecdh_curve, - METH_O, NULL}, -#endif - {"set_servername_callback", (PyCFunction) set_servername_callback, - METH_VARARGS, PySSL_set_servername_callback_doc}, - {"cert_store_stats", (PyCFunction) cert_store_stats, - METH_NOARGS, PySSL_get_stats_doc}, - {"get_ca_certs", (PyCFunction) get_ca_certs, - METH_VARARGS | METH_KEYWORDS, PySSL_get_ca_certs_doc}, + _SSL__SSLCONTEXT__WRAP_SOCKET_METHODDEF + _SSL__SSLCONTEXT__WRAP_BIO_METHODDEF + _SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF + _SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF + _SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF + _SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF + _SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF + _SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF + _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 {NULL, NULL} /* sentinel */ }; @@ -3498,7 +3572,7 @@ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ - context_new, /*tp_new*/ + _ssl__SSLContext, /*tp_new*/ }; @@ -3506,16 +3580,19 @@ * MemoryBIO objects */ +/*[clinic input] + at classmethod +_ssl.MemoryBIO.__new__ + +[clinic start generated code]*/ + static PyObject * -memory_bio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +_ssl_MemoryBIO_impl(PyTypeObject *type) +/*[clinic end generated code: output=8820a58db78330ac input=26d22e4909ecb1b5]*/ { - char *kwlist[] = {NULL}; BIO *bio; PySSLMemoryBIO *self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, ":MemoryBIO", kwlist)) - return NULL; - bio = BIO_new(BIO_s_mem()); if (bio == NULL) { PyErr_SetString(PySSLErrorObject, @@ -3566,15 +3643,26 @@ PyDoc_STRVAR(PySSL_memory_bio_eof_doc, "Whether the memory BIO is at EOF."); +/*[clinic input] +_ssl.MemoryBIO.read + size as len: int = -1 + / + +Read up to size bytes from the memory BIO. + +If size is not specified, read the entire buffer. +If the return value is an empty bytes instance, this means either +EOF or that no data is available. Use the "eof" property to +distinguish between the two. +[clinic start generated code]*/ + static PyObject * -memory_bio_read(PySSLMemoryBIO *self, PyObject *args) +_ssl_MemoryBIO_read_impl(PySSLMemoryBIO *self, int len) +/*[clinic end generated code: output=a657aa1e79cd01b3 input=574d7be06a902366]*/ { - int len = -1, avail, nbytes; + int avail, nbytes; PyObject *result; - if (!PyArg_ParseTuple(args, "|i:read", &len)) - return NULL; - avail = BIO_ctrl_pending(self->bio); if ((len < 0) || (len > avail)) len = avail; @@ -3593,59 +3681,54 @@ return result; } -PyDoc_STRVAR(PySSL_memory_bio_read_doc, -"read([len]) -> bytes\n\ -\n\ -Read up to len bytes from the memory BIO.\n\ -\n\ -If len is not specified, read the entire buffer.\n\ -If the return value is an empty bytes instance, this means either\n\ -EOF or that no data is available. Use the \"eof\" property to\n\ -distinguish between the two."); +/*[clinic input] +_ssl.MemoryBIO.write + b: Py_buffer + / + +Writes the bytes b into the memory BIO. + +Returns the number of bytes written. +[clinic start generated code]*/ static PyObject * -memory_bio_write(PySSLMemoryBIO *self, PyObject *args) +_ssl_MemoryBIO_write_impl(PySSLMemoryBIO *self, Py_buffer *b) +/*[clinic end generated code: output=156ec59110d75935 input=e45757b3e17c4808]*/ { - Py_buffer buf; int nbytes; - if (!PyArg_ParseTuple(args, "y*:write", &buf)) - return NULL; - - if (buf.len > INT_MAX) { + if (b->len > INT_MAX) { PyErr_Format(PyExc_OverflowError, "string longer than %d bytes", INT_MAX); - goto error; + return NULL; } if (self->eof_written) { PyErr_SetString(PySSLErrorObject, "cannot write() after write_eof()"); - goto error; + return NULL; } - nbytes = BIO_write(self->bio, buf.buf, buf.len); + nbytes = BIO_write(self->bio, b->buf, b->len); if (nbytes < 0) { _setSSLError(NULL, 0, __FILE__, __LINE__); - goto error; + return NULL; } - PyBuffer_Release(&buf); return PyLong_FromLong(nbytes); - -error: - PyBuffer_Release(&buf); - return NULL; } -PyDoc_STRVAR(PySSL_memory_bio_write_doc, -"write(b) -> len\n\ -\n\ -Writes the bytes b into the memory BIO. Returns the number\n\ -of bytes written."); +/*[clinic input] +_ssl.MemoryBIO.write_eof + +Write an EOF marker to the memory BIO. + +When all data has been read, the "eof" property will be True. +[clinic start generated code]*/ static PyObject * -memory_bio_write_eof(PySSLMemoryBIO *self, PyObject *args) +_ssl_MemoryBIO_write_eof_impl(PySSLMemoryBIO *self) +/*[clinic end generated code: output=d4106276ccd1ed34 input=56a945f1d29e8bd6]*/ { self->eof_written = 1; /* After an EOF is written, a zero return from read() should be a real EOF @@ -3656,12 +3739,6 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(PySSL_memory_bio_write_eof_doc, -"write_eof()\n\ -\n\ -Write an EOF marker to the memory BIO.\n\ -When all data has been read, the \"eof\" property will be True."); - static PyGetSetDef memory_bio_getsetlist[] = { {"pending", (getter) memory_bio_get_pending, NULL, PySSL_memory_bio_pending_doc}, @@ -3671,12 +3748,9 @@ }; static struct PyMethodDef memory_bio_methods[] = { - {"read", (PyCFunction) memory_bio_read, - METH_VARARGS, PySSL_memory_bio_read_doc}, - {"write", (PyCFunction) memory_bio_write, - METH_VARARGS, PySSL_memory_bio_write_doc}, - {"write_eof", (PyCFunction) memory_bio_write_eof, - METH_NOARGS, PySSL_memory_bio_write_eof_doc}, + _SSL_MEMORYBIO_READ_METHODDEF + _SSL_MEMORYBIO_WRITE_METHODDEF + _SSL_MEMORYBIO_WRITE_EOF_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -3718,40 +3792,42 @@ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ - memory_bio_new, /*tp_new*/ + _ssl_MemoryBIO, /*tp_new*/ }; /* helper routines for seeding the SSL PRNG */ +/*[clinic input] +_ssl.RAND_add + string as view: Py_buffer(types={'str', 'buffer'}) + entropy: double + / + +Mix string into the OpenSSL PRNG state. + +entropy (a float) is a lower bound on the entropy contained in +string. See RFC 1750. +[clinic start generated code]*/ + static PyObject * -PySSL_RAND_add(PyObject *self, PyObject *args) +_ssl_RAND_add_impl(PyModuleDef *module, Py_buffer *view, double entropy) +/*[clinic end generated code: output=0f8d5c8cce328958 input=c98b11d606b354bc]*/ { - Py_buffer view; const char *buf; Py_ssize_t len, written; - double entropy; - - if (!PyArg_ParseTuple(args, "s*d:RAND_add", &view, &entropy)) - return NULL; - buf = (const char *)view.buf; - len = view.len; + + buf = (const char *)view->buf; + len = view->len; do { written = Py_MIN(len, INT_MAX); RAND_add(buf, (int)written, entropy); buf += written; len -= written; } while (len); - PyBuffer_Release(&view); Py_INCREF(Py_None); return Py_None; } -PyDoc_STRVAR(PySSL_RAND_add_doc, -"RAND_add(string, entropy)\n\ -\n\ -Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\ -bound on the entropy contained in string. See RFC 1750."); - static PyObject * PySSL_RAND(int len, int pseudo) { @@ -3791,60 +3867,72 @@ return NULL; } +/*[clinic input] +_ssl.RAND_bytes + n: int + / + +Generate n cryptographically strong pseudo-random bytes. +[clinic start generated code]*/ + static PyObject * -PySSL_RAND_bytes(PyObject *self, PyObject *args) +_ssl_RAND_bytes_impl(PyModuleDef *module, int n) +/*[clinic end generated code: output=7d8741bdc1d435f3 input=678ddf2872dfebfc]*/ { - int len; - if (!PyArg_ParseTuple(args, "i:RAND_bytes", &len)) - return NULL; - return PySSL_RAND(len, 0); + return PySSL_RAND(n, 0); } -PyDoc_STRVAR(PySSL_RAND_bytes_doc, -"RAND_bytes(n) -> bytes\n\ -\n\ -Generate n cryptographically strong pseudo-random bytes."); +/*[clinic input] +_ssl.RAND_pseudo_bytes + n: int + / + +Generate n pseudo-random bytes. + +Return a pair (bytes, is_cryptographic). is_cryptographic is True +if the bytes generated are cryptographically strong. +[clinic start generated code]*/ static PyObject * -PySSL_RAND_pseudo_bytes(PyObject *self, PyObject *args) +_ssl_RAND_pseudo_bytes_impl(PyModuleDef *module, int n) +/*[clinic end generated code: output=dd673813107f3875 input=58312bd53f9bbdd0]*/ { - int len; - if (!PyArg_ParseTuple(args, "i:RAND_pseudo_bytes", &len)) - return NULL; - return PySSL_RAND(len, 1); + return PySSL_RAND(n, 1); } -PyDoc_STRVAR(PySSL_RAND_pseudo_bytes_doc, -"RAND_pseudo_bytes(n) -> (bytes, is_cryptographic)\n\ -\n\ -Generate n pseudo-random bytes. is_cryptographic is True if the bytes\ -generated are cryptographically strong."); +/*[clinic input] +_ssl.RAND_status + +Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not. + +It is necessary to seed the PRNG with RAND_add() on some platforms before +using the ssl() function. +[clinic start generated code]*/ static PyObject * -PySSL_RAND_status(PyObject *self) +_ssl_RAND_status_impl(PyModuleDef *module) +/*[clinic end generated code: output=7f7ef57bc7dd1d1c input=8a774b02d1dc81f3]*/ { return PyLong_FromLong(RAND_status()); } -PyDoc_STRVAR(PySSL_RAND_status_doc, -"RAND_status() -> 0 or 1\n\ -\n\ -Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\ -It is necessary to seed the PRNG with RAND_add() on some platforms before\n\ -using the ssl() function."); - #ifdef HAVE_RAND_EGD +/*[clinic input] +_ssl.RAND_egd + path: object(converter="PyUnicode_FSConverter") + / + +Queries the entropy gather daemon (EGD) on the socket named by 'path'. + +Returns number of bytes read. Raises SSLError if connection to EGD +fails or if it does not provide enough data to seed PRNG. +[clinic start generated code]*/ + static PyObject * -PySSL_RAND_egd(PyObject *self, PyObject *args) +_ssl_RAND_egd_impl(PyModuleDef *module, PyObject *path) +/*[clinic end generated code: output=8e728e501e28541b input=1aeb7eb948312195]*/ { - PyObject *path; - int bytes; - - if (!PyArg_ParseTuple(args, "O&:RAND_egd", - PyUnicode_FSConverter, &path)) - return NULL; - - bytes = RAND_egd(PyBytes_AsString(path)); + int bytes = RAND_egd(PyBytes_AsString(path)); Py_DECREF(path); if (bytes == -1) { PyErr_SetString(PySSLErrorObject, @@ -3854,25 +3942,21 @@ } return PyLong_FromLong(bytes); } - -PyDoc_STRVAR(PySSL_RAND_egd_doc, -"RAND_egd(path) -> bytes\n\ -\n\ -Queries the entropy gather daemon (EGD) on the socket named by 'path'.\n\ -Returns number of bytes read. Raises SSLError if connection to EGD\n\ -fails or if it does not provide enough data to seed PRNG."); #endif /* HAVE_RAND_EGD */ -PyDoc_STRVAR(PySSL_get_default_verify_paths_doc, -"get_default_verify_paths() -> tuple\n\ -\n\ -Return search paths and environment vars that are used by SSLContext's\n\ -set_default_verify_paths() to load default CAs. The values are\n\ -'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'."); + +/*[clinic input] +_ssl.get_default_verify_paths + +Return search paths and environment vars that are used by SSLContext's set_default_verify_paths() to load default CAs. + +The values are 'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'. +[clinic start generated code]*/ static PyObject * -PySSL_get_default_verify_paths(PyObject *self) +_ssl_get_default_verify_paths_impl(PyModuleDef *module) +/*[clinic end generated code: output=5a2820ce7e3304d3 input=5210c953d98c3eb5]*/ { PyObject *ofile_env = NULL; PyObject *ofile = NULL; @@ -3931,26 +4015,24 @@ } } -PyDoc_STRVAR(PySSL_txt2obj_doc, -"txt2obj(txt, name=False) -> (nid, shortname, longname, oid)\n\ -\n\ -Lookup NID, short name, long name and OID of an ASN1_OBJECT. By default\n\ -objects are looked up by OID. With name=True short and long name are also\n\ -matched."); - -static PyObject* -PySSL_txt2obj(PyObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_ssl.txt2obj + txt: str + name: bool = False + +Lookup NID, short name, long name and OID of an ASN1_OBJECT. + +By default objects are looked up by OID. With name=True short and +long name are also matched. +[clinic start generated code]*/ + +static PyObject * +_ssl_txt2obj_impl(PyModuleDef *module, const char *txt, int name) +/*[clinic end generated code: output=2ae2c30531b8809f input=1c1e7d0aa7c48602]*/ { - char *kwlist[] = {"txt", "name", NULL}; PyObject *result = NULL; - char *txt; - int name = 0; ASN1_OBJECT *obj; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|p:txt2obj", - kwlist, &txt, &name)) { - return NULL; - } obj = OBJ_txt2obj(txt, name ? 0 : 1); if (obj == NULL) { PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt); @@ -3961,21 +4043,21 @@ return result; } -PyDoc_STRVAR(PySSL_nid2obj_doc, -"nid2obj(nid) -> (nid, shortname, longname, oid)\n\ -\n\ -Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID."); - -static PyObject* -PySSL_nid2obj(PyObject *self, PyObject *args) +/*[clinic input] +_ssl.nid2obj + nid: int + / + +Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID. +[clinic start generated code]*/ + +static PyObject * +_ssl_nid2obj_impl(PyModuleDef *module, int nid) +/*[clinic end generated code: output=8db1df89e44badb8 input=51787a3bee7d8f98]*/ { PyObject *result = NULL; - int nid; ASN1_OBJECT *obj; - if (!PyArg_ParseTuple(args, "i:nid2obj", &nid)) { - return NULL; - } if (nid < NID_undef) { PyErr_SetString(PyExc_ValueError, "NID must be positive."); return NULL; @@ -4075,30 +4157,28 @@ return retval; } -PyDoc_STRVAR(PySSL_enum_certificates_doc, -"enum_certificates(store_name) -> []\n\ -\n\ -Retrieve certificates from Windows' cert store. store_name may be one of\n\ -'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -The function returns a list of (bytes, encoding_type, trust) tuples. The\n\ -encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the\n\ -boolean True."); +/*[clinic input] +_ssl.enum_certificates + store_name: str + +Retrieve certificates from Windows' cert store. + +store_name may be one of 'CA', 'ROOT' or 'MY'. The system may provide +more cert storages, too. The function returns a list of (bytes, +encoding_type, trust) tuples. The encoding_type flag can be interpreted +with X509_ASN_ENCODING or PKCS_7_ASN_ENCODING. The trust setting is either +a set of OIDs or the boolean True. +[clinic start generated code]*/ static PyObject * -PySSL_enum_certificates(PyObject *self, PyObject *args, PyObject *kwds) +_ssl_enum_certificates_impl(PyModuleDef *module, const char *store_name) +/*[clinic end generated code: output=cc4ebc10b8adacfc input=915f60d70461ea4e]*/ { - char *kwlist[] = {"store_name", NULL}; - char *store_name; HCERTSTORE hStore = NULL; PCCERT_CONTEXT pCertCtx = NULL; PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_certificates", - kwlist, &store_name)) { - return NULL; - } result = PyList_New(0); if (result == NULL) { return NULL; @@ -4164,29 +4244,27 @@ return result; } -PyDoc_STRVAR(PySSL_enum_crls_doc, -"enum_crls(store_name) -> []\n\ -\n\ -Retrieve CRLs from Windows' cert store. store_name may be one of\n\ -'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -The function returns a list of (bytes, encoding_type) tuples. The\n\ -encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -PKCS_7_ASN_ENCODING."); +/*[clinic input] +_ssl.enum_crls + store_name: str + +Retrieve CRLs from Windows' cert store. + +store_name may be one of 'CA', 'ROOT' or 'MY'. The system may provide +more cert storages, too. The function returns a list of (bytes, +encoding_type) tuples. The encoding_type flag can be interpreted with +X509_ASN_ENCODING or PKCS_7_ASN_ENCODING. +[clinic start generated code]*/ static PyObject * -PySSL_enum_crls(PyObject *self, PyObject *args, PyObject *kwds) +_ssl_enum_crls_impl(PyModuleDef *module, const char *store_name) +/*[clinic end generated code: output=763490a2aa1c50d5 input=a1f1d7629f1c5d3d]*/ { - char *kwlist[] = {"store_name", NULL}; - char *store_name; HCERTSTORE hStore = NULL; PCCRL_CONTEXT pCrlCtx = NULL; PyObject *crl = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_crls", - kwlist, &store_name)) { - return NULL; - } result = PyList_New(0); if (result == NULL) { return NULL; @@ -4244,34 +4322,18 @@ #endif /* _MSC_VER */ /* List of functions exported by this module. */ - static PyMethodDef PySSL_methods[] = { - {"_test_decode_cert", PySSL_test_decode_certificate, - METH_VARARGS}, - {"RAND_add", PySSL_RAND_add, METH_VARARGS, - PySSL_RAND_add_doc}, - {"RAND_bytes", PySSL_RAND_bytes, METH_VARARGS, - PySSL_RAND_bytes_doc}, - {"RAND_pseudo_bytes", PySSL_RAND_pseudo_bytes, METH_VARARGS, - PySSL_RAND_pseudo_bytes_doc}, -#ifdef HAVE_RAND_EGD - {"RAND_egd", PySSL_RAND_egd, METH_VARARGS, - PySSL_RAND_egd_doc}, -#endif - {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, - PySSL_RAND_status_doc}, - {"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths, - METH_NOARGS, PySSL_get_default_verify_paths_doc}, -#ifdef _MSC_VER - {"enum_certificates", (PyCFunction)PySSL_enum_certificates, - METH_VARARGS | METH_KEYWORDS, PySSL_enum_certificates_doc}, - {"enum_crls", (PyCFunction)PySSL_enum_crls, - METH_VARARGS | METH_KEYWORDS, PySSL_enum_crls_doc}, -#endif - {"txt2obj", (PyCFunction)PySSL_txt2obj, - METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc}, - {"nid2obj", (PyCFunction)PySSL_nid2obj, - METH_VARARGS, PySSL_nid2obj_doc}, + _SSL__TEST_DECODE_CERT_METHODDEF + _SSL_RAND_ADD_METHODDEF + _SSL_RAND_BYTES_METHODDEF + _SSL_RAND_PSEUDO_BYTES_METHODDEF + _SSL_RAND_EGD_METHODDEF + _SSL_RAND_STATUS_METHODDEF + _SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF + _SSL_ENUM_CERTIFICATES_METHODDEF + _SSL_ENUM_CRLS_METHODDEF + _SSL_TXT2OBJ_METHODDEF + _SSL_NID2OBJ_METHODDEF {NULL, NULL} /* Sentinel */ }; diff --git a/Modules/_ssl.c b/Modules/clinic/_ssl.c.h copy from Modules/_ssl.c copy to Modules/clinic/_ssl.c.h --- a/Modules/_ssl.c +++ b/Modules/clinic/_ssl.c.h @@ -1,4719 +1,1105 @@ -/* SSL socket module +/*[clinic input] +preserve +[clinic start generated code]*/ - SSL support based on patches by Brian E Gallew and Laszlo Kovacs. - Re-worked a bit by Bill Janssen to add server-side support and - certificate decoding. Chris Stawarz contributed some non-blocking - patches. +PyDoc_STRVAR(_ssl__SSLSocket_do_handshake__doc__, +"do_handshake($self, /)\n" +"--\n" +"\n"); - This module is imported by ssl.py. It should *not* be used - directly. - - XXX should partial writes be enabled, SSL_MODE_ENABLE_PARTIAL_WRITE? - - XXX integrate several "shutdown modes" as suggested in - http://bugs.python.org/issue8108#msg102867 ? -*/ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" - -#ifdef WITH_THREAD -#include "pythread.h" - - -#define PySSL_BEGIN_ALLOW_THREADS_S(save) \ - do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) -#define PySSL_END_ALLOW_THREADS_S(save) \ - do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } } while (0) -#define PySSL_BEGIN_ALLOW_THREADS { \ - PyThreadState *_save = NULL; \ - PySSL_BEGIN_ALLOW_THREADS_S(_save); -#define PySSL_BLOCK_THREADS PySSL_END_ALLOW_THREADS_S(_save); -#define PySSL_UNBLOCK_THREADS PySSL_BEGIN_ALLOW_THREADS_S(_save); -#define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); } - -#else /* no WITH_THREAD */ - -#define PySSL_BEGIN_ALLOW_THREADS_S(save) -#define PySSL_END_ALLOW_THREADS_S(save) -#define PySSL_BEGIN_ALLOW_THREADS -#define PySSL_BLOCK_THREADS -#define PySSL_UNBLOCK_THREADS -#define PySSL_END_ALLOW_THREADS - -#endif - -/* Include symbols from _socket module */ -#include "socketmodule.h" - -static PySocketModule_APIObject PySocketModule; - -#if defined(HAVE_POLL_H) -#include -#elif defined(HAVE_SYS_POLL_H) -#include -#endif - -/* Include OpenSSL header files */ -#include "openssl/rsa.h" -#include "openssl/crypto.h" -#include "openssl/x509.h" -#include "openssl/x509v3.h" -#include "openssl/pem.h" -#include "openssl/ssl.h" -#include "openssl/err.h" -#include "openssl/rand.h" -#include "openssl/bio.h" - -/* SSL error object */ -static PyObject *PySSLErrorObject; -static PyObject *PySSLZeroReturnErrorObject; -static PyObject *PySSLWantReadErrorObject; -static PyObject *PySSLWantWriteErrorObject; -static PyObject *PySSLSyscallErrorObject; -static PyObject *PySSLEOFErrorObject; - -/* Error mappings */ -static PyObject *err_codes_to_names; -static PyObject *err_names_to_codes; -static PyObject *lib_codes_to_names; - -struct py_ssl_error_code { - const char *mnemonic; - int library, reason; -}; -struct py_ssl_library_code { - const char *library; - int code; -}; - -/* Include generated data (error codes) */ -#include "_ssl_data.h" - -/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1 - http://www.openssl.org/news/changelog.html - */ -#if OPENSSL_VERSION_NUMBER >= 0x10001000L -# define HAVE_TLSv1_2 1 -#else -# define HAVE_TLSv1_2 0 -#endif - -/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f - * This includes the SSL_set_SSL_CTX() function. - */ -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# define HAVE_SNI 1 -#else -# define HAVE_SNI 0 -#endif - -/* ALPN added in OpenSSL 1.0.2 */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT) -# define HAVE_ALPN -#endif - -enum py_ssl_error { - /* these mirror ssl.h */ - PY_SSL_ERROR_NONE, - PY_SSL_ERROR_SSL, - PY_SSL_ERROR_WANT_READ, - PY_SSL_ERROR_WANT_WRITE, - PY_SSL_ERROR_WANT_X509_LOOKUP, - PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */ - PY_SSL_ERROR_ZERO_RETURN, - PY_SSL_ERROR_WANT_CONNECT, - /* start of non ssl.h errorcodes */ - PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ - PY_SSL_ERROR_NO_SOCKET, /* socket has been GC'd */ - PY_SSL_ERROR_INVALID_ERROR_CODE -}; - -enum py_ssl_server_or_client { - PY_SSL_CLIENT, - PY_SSL_SERVER -}; - -enum py_ssl_cert_requirements { - PY_SSL_CERT_NONE, - PY_SSL_CERT_OPTIONAL, - PY_SSL_CERT_REQUIRED -}; - -enum py_ssl_version { - PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3=1, - PY_SSL_VERSION_SSL23, -#if HAVE_TLSv1_2 - PY_SSL_VERSION_TLS1, - PY_SSL_VERSION_TLS1_1, - PY_SSL_VERSION_TLS1_2 -#else - PY_SSL_VERSION_TLS1 -#endif -}; - -#ifdef WITH_THREAD - -/* serves as a flag to see whether we've initialized the SSL thread support. */ -/* 0 means no, greater than 0 means yes */ - -static unsigned int _ssl_locks_count = 0; - -#endif /* def WITH_THREAD */ - -/* SSL socket object */ - -#define X509_NAME_MAXLEN 256 - -/* SSL_CTX_clear_options() and SSL_clear_options() were first added in - * OpenSSL 0.9.8m but do not appear in some 0.9.9-dev versions such the - * 0.9.9 from "May 2008" that NetBSD 5.0 uses. */ -#if OPENSSL_VERSION_NUMBER >= 0x009080dfL && OPENSSL_VERSION_NUMBER != 0x00909000L -# define HAVE_SSL_CTX_CLEAR_OPTIONS -#else -# undef HAVE_SSL_CTX_CLEAR_OPTIONS -#endif - -/* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for - * older SSL, but let's be safe */ -#define PySSL_CB_MAXLEN 128 - - -typedef struct { - PyObject_HEAD - SSL_CTX *ctx; -#ifdef OPENSSL_NPN_NEGOTIATED - unsigned char *npn_protocols; - int npn_protocols_len; -#endif -#ifdef HAVE_ALPN - unsigned char *alpn_protocols; - int alpn_protocols_len; -#endif -#ifndef OPENSSL_NO_TLSEXT - PyObject *set_hostname; -#endif - int check_hostname; -} PySSLContext; - -typedef struct { - PyObject_HEAD - PyObject *Socket; /* weakref to socket on which we're layered */ - SSL *ssl; - PySSLContext *ctx; /* weakref to SSL context */ - X509 *peer_cert; - char shutdown_seen_zero; - char handshake_done; - enum py_ssl_server_or_client socket_type; - PyObject *owner; /* Python level "owner" passed to servername callback */ - PyObject *server_hostname; -} PySSLSocket; - -typedef struct { - PyObject_HEAD - BIO *bio; - int eof_written; -} PySSLMemoryBIO; - -static PyTypeObject PySSLContext_Type; -static PyTypeObject PySSLSocket_Type; -static PyTypeObject PySSLMemoryBIO_Type; - -static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); -static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); -static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); -static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); -static PyObject *PySSL_cipher(PySSLSocket *self); - -#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) - -typedef enum { - SOCKET_IS_NONBLOCKING, - SOCKET_IS_BLOCKING, - SOCKET_HAS_TIMED_OUT, - SOCKET_HAS_BEEN_CLOSED, - SOCKET_TOO_LARGE_FOR_SELECT, - SOCKET_OPERATION_OK -} timeout_state; - -/* Wrap error strings with filename and line # */ -#define ERRSTR1(x,y,z) (x ":" y ": " z) -#define ERRSTR(x) ERRSTR1("_ssl.c", Py_STRINGIFY(__LINE__), x) - -/* Get the socket from a PySSLSocket, if it has one */ -#define GET_SOCKET(obj) ((obj)->Socket ? \ - (PySocketSockObject *) PyWeakref_GetObject((obj)->Socket) : NULL) - -/* If sock is NULL, use a timeout of 0 second */ -#define GET_SOCKET_TIMEOUT(sock) \ - ((sock != NULL) ? (sock)->sock_timeout : 0) - -/* - * SSL errors. - */ - -PyDoc_STRVAR(SSLError_doc, -"An error occurred in the SSL implementation."); - -PyDoc_STRVAR(SSLZeroReturnError_doc, -"SSL/TLS session closed cleanly."); - -PyDoc_STRVAR(SSLWantReadError_doc, -"Non-blocking SSL socket needs to read more data\n" -"before the requested operation can be completed."); - -PyDoc_STRVAR(SSLWantWriteError_doc, -"Non-blocking SSL socket needs to write more data\n" -"before the requested operation can be completed."); - -PyDoc_STRVAR(SSLSyscallError_doc, -"System error when attempting SSL operation."); - -PyDoc_STRVAR(SSLEOFError_doc, -"SSL/TLS connection terminated abruptly."); +#define _SSL__SSLSOCKET_DO_HANDSHAKE_METHODDEF \ + {"do_handshake", (PyCFunction)_ssl__SSLSocket_do_handshake, METH_NOARGS, _ssl__SSLSocket_do_handshake__doc__}, static PyObject * -SSLError_str(PyOSErrorObject *self) +_ssl__SSLSocket_do_handshake_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_do_handshake(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) { - if (self->strerror != NULL && PyUnicode_Check(self->strerror)) { - Py_INCREF(self->strerror); - return self->strerror; - } - else - return PyObject_Str(self->args); + return _ssl__SSLSocket_do_handshake_impl(self); } -static PyType_Slot sslerror_type_slots[] = { - {Py_tp_base, NULL}, /* Filled out in module init as it's not a constant */ - {Py_tp_doc, SSLError_doc}, - {Py_tp_str, SSLError_str}, - {0, 0}, -}; +PyDoc_STRVAR(_ssl__test_decode_cert__doc__, +"_test_decode_cert($module, path, /)\n" +"--\n" +"\n"); -static PyType_Spec sslerror_type_spec = { - "ssl.SSLError", - sizeof(PyOSErrorObject), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - sslerror_type_slots -}; +#define _SSL__TEST_DECODE_CERT_METHODDEF \ + {"_test_decode_cert", (PyCFunction)_ssl__test_decode_cert, METH_O, _ssl__test_decode_cert__doc__}, -static void -fill_and_set_sslerror(PyObject *type, int ssl_errno, const char *errstr, - int lineno, unsigned long errcode) +static PyObject * +_ssl__test_decode_cert_impl(PyModuleDef *module, PyObject *path); + +static PyObject * +_ssl__test_decode_cert(PyModuleDef *module, PyObject *arg) { - PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL; - PyObject *init_value, *msg, *key; - _Py_IDENTIFIER(reason); - _Py_IDENTIFIER(library); + PyObject *return_value = NULL; + PyObject *path; - if (errcode != 0) { - int lib, reason; + if (!PyArg_Parse(arg, "O&:_test_decode_cert", PyUnicode_FSConverter, &path)) + goto exit; + return_value = _ssl__test_decode_cert_impl(module, path); - lib = ERR_GET_LIB(errcode); - reason = ERR_GET_REASON(errcode); - key = Py_BuildValue("ii", lib, reason); - if (key == NULL) - goto fail; - reason_obj = PyDict_GetItem(err_codes_to_names, key); - Py_DECREF(key); - if (reason_obj == NULL) { - /* XXX if reason < 100, it might reflect a library number (!!) */ - PyErr_Clear(); - } - key = PyLong_FromLong(lib); - if (key == NULL) - goto fail; - lib_obj = PyDict_GetItem(lib_codes_to_names, key); - Py_DECREF(key); - if (lib_obj == NULL) { - PyErr_Clear(); - } - if (errstr == NULL) - errstr = ERR_reason_error_string(errcode); +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, +"peer_certificate($self, der=False, /)\n" +"--\n" +"\n" +"Returns the certificate for the peer.\n" +"\n" +"If no certificate was provided, returns None. If a certificate was\n" +"provided, but not validated, returns an empty dictionary. Otherwise\n" +"returns a dict containing information about the peer certificate.\n" +"\n" +"If the optional argument is True, returns a DER-encoded copy of the\n" +"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_VARARGS, _ssl__SSLSocket_peer_certificate__doc__}, + +static PyObject * +_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode); + +static PyObject * +_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject *args) +{ + PyObject *return_value = NULL; + int binary_mode = 0; + + if (!PyArg_ParseTuple(args, "|p:peer_certificate", + &binary_mode)) + goto exit; + return_value = _ssl__SSLSocket_peer_certificate_impl(self, binary_mode); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLSocket_shared_ciphers__doc__, +"shared_ciphers($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF \ + {"shared_ciphers", (PyCFunction)_ssl__SSLSocket_shared_ciphers, METH_NOARGS, _ssl__SSLSocket_shared_ciphers__doc__}, + +static PyObject * +_ssl__SSLSocket_shared_ciphers_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_shared_ciphers(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_shared_ciphers_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLSocket_cipher__doc__, +"cipher($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_CIPHER_METHODDEF \ + {"cipher", (PyCFunction)_ssl__SSLSocket_cipher, METH_NOARGS, _ssl__SSLSocket_cipher__doc__}, + +static PyObject * +_ssl__SSLSocket_cipher_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_cipher(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_cipher_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLSocket_version__doc__, +"version($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_VERSION_METHODDEF \ + {"version", (PyCFunction)_ssl__SSLSocket_version, METH_NOARGS, _ssl__SSLSocket_version__doc__}, + +static PyObject * +_ssl__SSLSocket_version_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_version_impl(self); +} + +#if defined(OPENSSL_NPN_NEGOTIATED) + +PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, +"selected_npn_protocol($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF \ + {"selected_npn_protocol", (PyCFunction)_ssl__SSLSocket_selected_npn_protocol, METH_NOARGS, _ssl__SSLSocket_selected_npn_protocol__doc__}, + +static PyObject * +_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_selected_npn_protocol_impl(self); +} + +#endif /* defined(OPENSSL_NPN_NEGOTIATED) */ + +#if defined(HAVE_ALPN) + +PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__, +"selected_alpn_protocol($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF \ + {"selected_alpn_protocol", (PyCFunction)_ssl__SSLSocket_selected_alpn_protocol, METH_NOARGS, _ssl__SSLSocket_selected_alpn_protocol__doc__}, + +static PyObject * +_ssl__SSLSocket_selected_alpn_protocol_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_selected_alpn_protocol_impl(self); +} + +#endif /* defined(HAVE_ALPN) */ + +PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, +"compression($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_COMPRESSION_METHODDEF \ + {"compression", (PyCFunction)_ssl__SSLSocket_compression, METH_NOARGS, _ssl__SSLSocket_compression__doc__}, + +static PyObject * +_ssl__SSLSocket_compression_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_compression(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_compression_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLSocket_write__doc__, +"write($self, b, /)\n" +"--\n" +"\n" +"Writes the bytes-like object b into the SSL object.\n" +"\n" +"Returns the number of bytes written."); + +#define _SSL__SSLSOCKET_WRITE_METHODDEF \ + {"write", (PyCFunction)_ssl__SSLSocket_write, METH_O, _ssl__SSLSocket_write__doc__}, + +static PyObject * +_ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b); + +static PyObject * +_ssl__SSLSocket_write(PySSLSocket *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer b = {NULL, NULL}; + + if (!PyArg_Parse(arg, "y*:write", &b)) + goto exit; + return_value = _ssl__SSLSocket_write_impl(self, &b); + +exit: + /* Cleanup for b */ + if (b.obj) + PyBuffer_Release(&b); + + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLSocket_pending__doc__, +"pending($self, /)\n" +"--\n" +"\n" +"Returns the number of already decrypted bytes available for read, pending on the connection."); + +#define _SSL__SSLSOCKET_PENDING_METHODDEF \ + {"pending", (PyCFunction)_ssl__SSLSocket_pending, METH_NOARGS, _ssl__SSLSocket_pending__doc__}, + +static PyObject * +_ssl__SSLSocket_pending_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_pending(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_pending_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLSocket_read__doc__, +"read(size, [buffer])\n" +"Read up to size bytes from the SSL socket."); + +#define _SSL__SSLSOCKET_READ_METHODDEF \ + {"read", (PyCFunction)_ssl__SSLSocket_read, METH_VARARGS, _ssl__SSLSocket_read__doc__}, + +static PyObject * +_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, + Py_buffer *buffer); + +static PyObject * +_ssl__SSLSocket_read(PySSLSocket *self, PyObject *args) +{ + PyObject *return_value = NULL; + int len; + int group_right_1 = 0; + Py_buffer buffer = {NULL, NULL}; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "i:read", &len)) + goto exit; + break; + case 2: + if (!PyArg_ParseTuple(args, "iw*:read", &len, &buffer)) + goto exit; + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_ssl._SSLSocket.read requires 1 to 2 arguments"); + goto exit; } - if (errstr == NULL) - errstr = "unknown error"; + return_value = _ssl__SSLSocket_read_impl(self, len, group_right_1, &buffer); - if (reason_obj && lib_obj) - msg = PyUnicode_FromFormat("[%S: %S] %s (_ssl.c:%d)", - lib_obj, reason_obj, errstr, lineno); - else if (lib_obj) - msg = PyUnicode_FromFormat("[%S] %s (_ssl.c:%d)", - lib_obj, errstr, lineno); - else - msg = PyUnicode_FromFormat("%s (_ssl.c:%d)", errstr, lineno); - if (msg == NULL) - goto fail; +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); - init_value = Py_BuildValue("iN", ssl_errno, msg); - if (init_value == NULL) - goto fail; + return return_value; +} - err_value = PyObject_CallObject(type, init_value); - Py_DECREF(init_value); - if (err_value == NULL) - goto fail; +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."); - if (reason_obj == NULL) - reason_obj = Py_None; - if (_PyObject_SetAttrId(err_value, &PyId_reason, reason_obj)) - goto fail; - if (lib_obj == NULL) - lib_obj = Py_None; - if (_PyObject_SetAttrId(err_value, &PyId_library, lib_obj)) - goto fail; - PyErr_SetObject(type, err_value); -fail: - Py_XDECREF(err_value); +#define _SSL__SSLSOCKET_SHUTDOWN_METHODDEF \ + {"shutdown", (PyCFunction)_ssl__SSLSocket_shutdown, METH_NOARGS, _ssl__SSLSocket_shutdown__doc__}, + +static PyObject * +_ssl__SSLSocket_shutdown_impl(PySSLSocket *self); + +static PyObject * +_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" +"--\n" +"\n" +"Returns the \'tls-unique\' channel binding data, as defined by RFC 5929.\n" +"\n" +"If the TLS handshake is not yet complete, None is returned."); + +#define _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF \ + {"tls_unique_cb", (PyCFunction)_ssl__SSLSocket_tls_unique_cb, METH_NOARGS, _ssl__SSLSocket_tls_unique_cb__doc__}, + +static PyObject * +_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_tls_unique_cb(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_tls_unique_cb_impl(self); } static PyObject * -PySSL_SetError(PySSLSocket *obj, int ret, char *filename, int lineno) +_ssl__SSLContext_impl(PyTypeObject *type, int proto_version); + +static PyObject * +_ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs) { - PyObject *type = PySSLErrorObject; - char *errstr = NULL; - int err; - enum py_ssl_error p = PY_SSL_ERROR_NONE; - unsigned long e = 0; + PyObject *return_value = NULL; + int proto_version; - assert(ret <= 0); - e = ERR_peek_last_error(); + if ((type == &PySSLContext_Type) && + !_PyArg_NoKeywords("_SSLContext", kwargs)) + goto exit; + if (!PyArg_ParseTuple(args, "i:_SSLContext", + &proto_version)) + goto exit; + return_value = _ssl__SSLContext_impl(type, proto_version); - if (obj->ssl != NULL) { - err = SSL_get_error(obj->ssl, ret); +exit: + return return_value; +} - switch (err) { - case SSL_ERROR_ZERO_RETURN: - errstr = "TLS/SSL connection has been closed (EOF)"; - type = PySSLZeroReturnErrorObject; - p = PY_SSL_ERROR_ZERO_RETURN; - break; - case SSL_ERROR_WANT_READ: - errstr = "The operation did not complete (read)"; - type = PySSLWantReadErrorObject; - p = PY_SSL_ERROR_WANT_READ; - break; - case SSL_ERROR_WANT_WRITE: - p = PY_SSL_ERROR_WANT_WRITE; - type = PySSLWantWriteErrorObject; - errstr = "The operation did not complete (write)"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: - p = PY_SSL_ERROR_WANT_X509_LOOKUP; - errstr = "The operation did not complete (X509 lookup)"; - break; - case SSL_ERROR_WANT_CONNECT: - p = PY_SSL_ERROR_WANT_CONNECT; - errstr = "The operation did not complete (connect)"; - break; - case SSL_ERROR_SYSCALL: - { - if (e == 0) { - PySocketSockObject *s = GET_SOCKET(obj); - if (ret == 0 || (((PyObject *)s) == Py_None)) { - p = PY_SSL_ERROR_EOF; - type = PySSLEOFErrorObject; - errstr = "EOF occurred in violation of protocol"; - } else if (s && ret == -1) { - /* underlying BIO reported an I/O error */ - Py_INCREF(s); - ERR_clear_error(); - s->errorhandler(); - Py_DECREF(s); - return NULL; - } else { /* possible? */ - p = PY_SSL_ERROR_SYSCALL; - type = PySSLSyscallErrorObject; - errstr = "Some I/O error occurred"; - } - } else { - p = PY_SSL_ERROR_SYSCALL; - } - break; - } - case SSL_ERROR_SSL: - { - p = PY_SSL_ERROR_SSL; - if (e == 0) - /* possible? */ - errstr = "A failure in the SSL library occurred"; - break; - } - default: - p = PY_SSL_ERROR_INVALID_ERROR_CODE; - errstr = "Invalid error code"; - } - } - fill_and_set_sslerror(type, p, errstr, lineno, e); - ERR_clear_error(); - return NULL; +PyDoc_STRVAR(_ssl__SSLContext_set_ciphers__doc__, +"set_ciphers($self, cipherlist, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF \ + {"set_ciphers", (PyCFunction)_ssl__SSLContext_set_ciphers, METH_O, _ssl__SSLContext_set_ciphers__doc__}, + +static PyObject * +_ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist); + +static PyObject * +_ssl__SSLContext_set_ciphers(PySSLContext *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *cipherlist; + + if (!PyArg_Parse(arg, "s:set_ciphers", &cipherlist)) + goto exit; + return_value = _ssl__SSLContext_set_ciphers_impl(self, cipherlist); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext__set_npn_protocols__doc__, +"_set_npn_protocols($self, protos, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF \ + {"_set_npn_protocols", (PyCFunction)_ssl__SSLContext__set_npn_protocols, METH_O, _ssl__SSLContext__set_npn_protocols__doc__}, + +static PyObject * +_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, + Py_buffer *protos); + +static PyObject * +_ssl__SSLContext__set_npn_protocols(PySSLContext *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer protos = {NULL, NULL}; + + if (!PyArg_Parse(arg, "y*:_set_npn_protocols", &protos)) + goto exit; + return_value = _ssl__SSLContext__set_npn_protocols_impl(self, &protos); + +exit: + /* Cleanup for protos */ + if (protos.obj) + PyBuffer_Release(&protos); + + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext__set_alpn_protocols__doc__, +"_set_alpn_protocols($self, protos, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF \ + {"_set_alpn_protocols", (PyCFunction)_ssl__SSLContext__set_alpn_protocols, METH_O, _ssl__SSLContext__set_alpn_protocols__doc__}, + +static PyObject * +_ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, + Py_buffer *protos); + +static PyObject * +_ssl__SSLContext__set_alpn_protocols(PySSLContext *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer protos = {NULL, NULL}; + + if (!PyArg_Parse(arg, "y*:_set_alpn_protocols", &protos)) + goto exit; + return_value = _ssl__SSLContext__set_alpn_protocols_impl(self, &protos); + +exit: + /* Cleanup for protos */ + if (protos.obj) + PyBuffer_Release(&protos); + + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext_load_cert_chain__doc__, +"load_cert_chain($self, /, certfile, keyfile=None, password=None)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF \ + {"load_cert_chain", (PyCFunction)_ssl__SSLContext_load_cert_chain, METH_VARARGS|METH_KEYWORDS, _ssl__SSLContext_load_cert_chain__doc__}, + +static PyObject * +_ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, + PyObject *keyfile, PyObject *password); + +static PyObject * +_ssl__SSLContext_load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"certfile", "keyfile", "password", NULL}; + PyObject *certfile; + PyObject *keyfile = NULL; + PyObject *password = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:load_cert_chain", _keywords, + &certfile, &keyfile, &password)) + goto exit; + return_value = _ssl__SSLContext_load_cert_chain_impl(self, certfile, keyfile, password); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext_load_verify_locations__doc__, +"load_verify_locations($self, /, cafile=None, capath=None, cadata=None)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF \ + {"load_verify_locations", (PyCFunction)_ssl__SSLContext_load_verify_locations, METH_VARARGS|METH_KEYWORDS, _ssl__SSLContext_load_verify_locations__doc__}, + +static PyObject * +_ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, + PyObject *cafile, + PyObject *capath, + PyObject *cadata); + +static PyObject * +_ssl__SSLContext_load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"cafile", "capath", "cadata", NULL}; + PyObject *cafile = NULL; + PyObject *capath = NULL; + PyObject *cadata = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:load_verify_locations", _keywords, + &cafile, &capath, &cadata)) + goto exit; + return_value = _ssl__SSLContext_load_verify_locations_impl(self, cafile, capath, cadata); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext_load_dh_params__doc__, +"load_dh_params($self, path, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF \ + {"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" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT__WRAP_SOCKET_METHODDEF \ + {"_wrap_socket", (PyCFunction)_ssl__SSLContext__wrap_socket, METH_VARARGS|METH_KEYWORDS, _ssl__SSLContext__wrap_socket__doc__}, + +static PyObject * +_ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, + int server_side, PyObject *hostname_obj); + +static PyObject * +_ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"sock", "server_side", "server_hostname", NULL}; + PyObject *sock; + int server_side; + PyObject *hostname_obj = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|O:_wrap_socket", _keywords, + PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj)) + goto exit; + return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, +"_wrap_bio($self, /, incoming, outgoing, server_side,\n" +" server_hostname=None)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT__WRAP_BIO_METHODDEF \ + {"_wrap_bio", (PyCFunction)_ssl__SSLContext__wrap_bio, METH_VARARGS|METH_KEYWORDS, _ssl__SSLContext__wrap_bio__doc__}, + +static PyObject * +_ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, + PySSLMemoryBIO *outgoing, int server_side, + PyObject *hostname_obj); + +static PyObject * +_ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL}; + PySSLMemoryBIO *incoming; + PySSLMemoryBIO *outgoing; + int server_side; + PyObject *hostname_obj = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!i|O:_wrap_bio", _keywords, + &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj)) + goto exit; + return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl__SSLContext_session_stats__doc__, +"session_stats($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SESSION_STATS_METHODDEF \ + {"session_stats", (PyCFunction)_ssl__SSLContext_session_stats, METH_NOARGS, _ssl__SSLContext_session_stats__doc__}, + +static PyObject * +_ssl__SSLContext_session_stats_impl(PySSLContext *self); + +static PyObject * +_ssl__SSLContext_session_stats(PySSLContext *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLContext_session_stats_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLContext_set_default_verify_paths__doc__, +"set_default_verify_paths($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SET_DEFAULT_VERIFY_PATHS_METHODDEF \ + {"set_default_verify_paths", (PyCFunction)_ssl__SSLContext_set_default_verify_paths, METH_NOARGS, _ssl__SSLContext_set_default_verify_paths__doc__}, + +static PyObject * +_ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self); + +static PyObject * +_ssl__SSLContext_set_default_verify_paths(PySSLContext *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLContext_set_default_verify_paths_impl(self); +} + +#if !defined(OPENSSL_NO_ECDH) + +PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, +"set_ecdh_curve($self, name, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF \ + {"set_ecdh_curve", (PyCFunction)_ssl__SSLContext_set_ecdh_curve, METH_O, _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" +"\n" +"Returns quantities of loaded X.509 certificates.\n" +"\n" +"X.509 certificates with a CA extension and certificate revocation lists\n" +"inside the context\'s cert store.\n" +"\n" +"NOTE: Certificates in a capath directory aren\'t loaded unless they have\n" +"been used at least once."); + +#define _SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF \ + {"cert_store_stats", (PyCFunction)_ssl__SSLContext_cert_store_stats, METH_NOARGS, _ssl__SSLContext_cert_store_stats__doc__}, + +static PyObject * +_ssl__SSLContext_cert_store_stats_impl(PySSLContext *self); + +static PyObject * +_ssl__SSLContext_cert_store_stats(PySSLContext *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLContext_cert_store_stats_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLContext_get_ca_certs__doc__, +"get_ca_certs($self, /, binary_form=False)\n" +"--\n" +"\n" +"Returns a list of dicts with information of loaded CA certs.\n" +"\n" +"If the optional argument is True, returns a DER-encoded copy of the CA\n" +"certificate.\n" +"\n" +"NOTE: Certificates in a capath directory aren\'t loaded unless they have\n" +"been used at least once."); + +#define _SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF \ + {"get_ca_certs", (PyCFunction)_ssl__SSLContext_get_ca_certs, METH_VARARGS|METH_KEYWORDS, _ssl__SSLContext_get_ca_certs__doc__}, + +static PyObject * +_ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form); + +static PyObject * +_ssl__SSLContext_get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"binary_form", NULL}; + int binary_form = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:get_ca_certs", _keywords, + &binary_form)) + goto exit; + return_value = _ssl__SSLContext_get_ca_certs_impl(self, binary_form); + +exit: + return return_value; } static PyObject * -_setSSLError (char *errstr, int errcode, char *filename, int lineno) { +_ssl_MemoryBIO_impl(PyTypeObject *type); - if (errstr == NULL) - errcode = ERR_peek_last_error(); - else - errcode = 0; - fill_and_set_sslerror(PySSLErrorObject, errcode, errstr, lineno, errcode); - ERR_clear_error(); - return NULL; +static PyObject * +_ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + + if ((type == &PySSLMemoryBIO_Type) && + !_PyArg_NoPositional("MemoryBIO", args)) + goto exit; + if ((type == &PySSLMemoryBIO_Type) && + !_PyArg_NoKeywords("MemoryBIO", kwargs)) + goto exit; + return_value = _ssl_MemoryBIO_impl(type); + +exit: + return return_value; } -/* - * SSL objects - */ +PyDoc_STRVAR(_ssl_MemoryBIO_read__doc__, +"read($self, size=-1, /)\n" +"--\n" +"\n" +"Read up to size bytes from the memory BIO.\n" +"\n" +"If size is not specified, read the entire buffer.\n" +"If the return value is an empty bytes instance, this means either\n" +"EOF or that no data is available. Use the \"eof\" property to\n" +"distinguish between the two."); -static PySSLSocket * -newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, - enum py_ssl_server_or_client socket_type, - char *server_hostname, - PySSLMemoryBIO *inbio, PySSLMemoryBIO *outbio) +#define _SSL_MEMORYBIO_READ_METHODDEF \ + {"read", (PyCFunction)_ssl_MemoryBIO_read, METH_VARARGS, _ssl_MemoryBIO_read__doc__}, + +static PyObject * +_ssl_MemoryBIO_read_impl(PySSLMemoryBIO *self, int len); + +static PyObject * +_ssl_MemoryBIO_read(PySSLMemoryBIO *self, PyObject *args) { - PySSLSocket *self; - SSL_CTX *ctx = sslctx->ctx; - PyObject *hostname; - long mode; + PyObject *return_value = NULL; + int len = -1; - self = PyObject_New(PySSLSocket, &PySSLSocket_Type); - if (self == NULL) - return NULL; + if (!PyArg_ParseTuple(args, "|i:read", + &len)) + goto exit; + return_value = _ssl_MemoryBIO_read_impl(self, len); - self->peer_cert = NULL; - self->ssl = NULL; - self->Socket = NULL; - self->ctx = sslctx; - self->shutdown_seen_zero = 0; - self->handshake_done = 0; - self->owner = NULL; - if (server_hostname != NULL) { - hostname = PyUnicode_Decode(server_hostname, strlen(server_hostname), - "idna", "strict"); - if (hostname == NULL) { - Py_DECREF(self); - return NULL; - } - self->server_hostname = hostname; - } else - self->server_hostname = NULL; - - Py_INCREF(sslctx); - - /* Make sure the SSL error state is initialized */ - (void) ERR_get_state(); - ERR_clear_error(); - - PySSL_BEGIN_ALLOW_THREADS - self->ssl = SSL_new(ctx); - PySSL_END_ALLOW_THREADS - SSL_set_app_data(self->ssl, self); - if (sock) { - SSL_set_fd(self->ssl, Py_SAFE_DOWNCAST(sock->sock_fd, SOCKET_T, int)); - } else { - /* BIOs are reference counted and SSL_set_bio borrows our reference. - * To prevent a double free in memory_bio_dealloc() we need to take an - * extra reference here. */ - CRYPTO_add(&inbio->bio->references, 1, CRYPTO_LOCK_BIO); - CRYPTO_add(&outbio->bio->references, 1, CRYPTO_LOCK_BIO); - SSL_set_bio(self->ssl, inbio->bio, outbio->bio); - } - mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; -#ifdef SSL_MODE_AUTO_RETRY - mode |= SSL_MODE_AUTO_RETRY; -#endif - SSL_set_mode(self->ssl, mode); - -#if HAVE_SNI - if (server_hostname != NULL) - SSL_set_tlsext_host_name(self->ssl, server_hostname); -#endif - - /* If the socket is in non-blocking mode or timeout mode, set the BIO - * to non-blocking mode (blocking is the default) - */ - if (sock && sock->sock_timeout >= 0) { - BIO_set_nbio(SSL_get_rbio(self->ssl), 1); - BIO_set_nbio(SSL_get_wbio(self->ssl), 1); - } - - PySSL_BEGIN_ALLOW_THREADS - if (socket_type == PY_SSL_CLIENT) - SSL_set_connect_state(self->ssl); - else - SSL_set_accept_state(self->ssl); - PySSL_END_ALLOW_THREADS - - self->socket_type = socket_type; - if (sock != NULL) { - self->Socket = PyWeakref_NewRef((PyObject *) sock, NULL); - if (self->Socket == NULL) { - Py_DECREF(self); - Py_XDECREF(self->server_hostname); - return NULL; - } - } - return self; +exit: + return return_value; } -/* SSL object methods */ +PyDoc_STRVAR(_ssl_MemoryBIO_write__doc__, +"write($self, b, /)\n" +"--\n" +"\n" +"Writes the bytes b into the memory BIO.\n" +"\n" +"Returns the number of bytes written."); -static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) +#define _SSL_MEMORYBIO_WRITE_METHODDEF \ + {"write", (PyCFunction)_ssl_MemoryBIO_write, METH_O, _ssl_MemoryBIO_write__doc__}, + +static PyObject * +_ssl_MemoryBIO_write_impl(PySSLMemoryBIO *self, Py_buffer *b); + +static PyObject * +_ssl_MemoryBIO_write(PySSLMemoryBIO *self, PyObject *arg) { - int ret; - int err; - int sockstate, nonblocking; - PySocketSockObject *sock = GET_SOCKET(self); - _PyTime_t timeout, deadline = 0; - int has_timeout; + PyObject *return_value = NULL; + Py_buffer b = {NULL, NULL}; - if (sock) { - if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", - PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } - Py_INCREF(sock); + if (!PyArg_Parse(arg, "y*:write", &b)) + goto exit; + return_value = _ssl_MemoryBIO_write_impl(self, &b); - /* just in case the blocking state of the socket has been changed */ - nonblocking = (sock->sock_timeout >= 0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - } +exit: + /* Cleanup for b */ + if (b.obj) + PyBuffer_Release(&b); - timeout = GET_SOCKET_TIMEOUT(sock); - has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; - - /* Actually negotiate SSL connection */ - /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ - do { - PySSL_BEGIN_ALLOW_THREADS - ret = SSL_do_handshake(self->ssl); - err = SSL_get_error(self->ssl, ret); - PySSL_END_ALLOW_THREADS - - if (PyErr_CheckSignals()) - goto error; - - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); - - if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0, timeout); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1, timeout); - } else { - sockstate = SOCKET_OPERATION_OK; - } - - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, - ERRSTR("The handshake operation timed out")); - goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket has been closed.")); - goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket too large for select().")); - goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - Py_XDECREF(sock); - if (ret < 1) - return PySSL_SetError(self, ret, __FILE__, __LINE__); - - if (self->peer_cert) - X509_free (self->peer_cert); - PySSL_BEGIN_ALLOW_THREADS - self->peer_cert = SSL_get_peer_certificate(self->ssl); - PySSL_END_ALLOW_THREADS - self->handshake_done = 1; - - Py_INCREF(Py_None); - return Py_None; - -error: - Py_XDECREF(sock); - return NULL; + return return_value; } +PyDoc_STRVAR(_ssl_MemoryBIO_write_eof__doc__, +"write_eof($self, /)\n" +"--\n" +"\n" +"Write an EOF marker to the memory BIO.\n" +"\n" +"When all data has been read, the \"eof\" property will be True."); + +#define _SSL_MEMORYBIO_WRITE_EOF_METHODDEF \ + {"write_eof", (PyCFunction)_ssl_MemoryBIO_write_eof, METH_NOARGS, _ssl_MemoryBIO_write_eof__doc__}, + static PyObject * -_create_tuple_for_attribute (ASN1_OBJECT *name, ASN1_STRING *value) { +_ssl_MemoryBIO_write_eof_impl(PySSLMemoryBIO *self); - char namebuf[X509_NAME_MAXLEN]; - int buflen; - PyObject *name_obj; - PyObject *value_obj; - PyObject *attr; - unsigned char *valuebuf = NULL; - - buflen = OBJ_obj2txt(namebuf, sizeof(namebuf), name, 0); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail; - } - name_obj = PyUnicode_FromStringAndSize(namebuf, buflen); - if (name_obj == NULL) - goto fail; - - buflen = ASN1_STRING_to_UTF8(&valuebuf, value); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - Py_DECREF(name_obj); - goto fail; - } - value_obj = PyUnicode_DecodeUTF8((char *) valuebuf, - buflen, "strict"); - OPENSSL_free(valuebuf); - if (value_obj == NULL) { - Py_DECREF(name_obj); - goto fail; - } - attr = PyTuple_New(2); - if (attr == NULL) { - Py_DECREF(name_obj); - Py_DECREF(value_obj); - goto fail; - } - PyTuple_SET_ITEM(attr, 0, name_obj); - PyTuple_SET_ITEM(attr, 1, value_obj); - return attr; - - fail: - return NULL; +static PyObject * +_ssl_MemoryBIO_write_eof(PySSLMemoryBIO *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl_MemoryBIO_write_eof_impl(self); } +PyDoc_STRVAR(_ssl_RAND_add__doc__, +"RAND_add($module, string, entropy, /)\n" +"--\n" +"\n" +"Mix string into the OpenSSL PRNG state.\n" +"\n" +"entropy (a float) is a lower bound on the entropy contained in\n" +"string. See RFC 1750."); + +#define _SSL_RAND_ADD_METHODDEF \ + {"RAND_add", (PyCFunction)_ssl_RAND_add, METH_VARARGS, _ssl_RAND_add__doc__}, + static PyObject * -_create_tuple_for_X509_NAME (X509_NAME *xname) +_ssl_RAND_add_impl(PyModuleDef *module, Py_buffer *view, double entropy); + +static PyObject * +_ssl_RAND_add(PyModuleDef *module, PyObject *args) { - PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ - PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ - PyObject *rdnt; - PyObject *attr = NULL; /* tuple to hold an attribute */ - int entry_count = X509_NAME_entry_count(xname); - X509_NAME_ENTRY *entry; - ASN1_OBJECT *name; - ASN1_STRING *value; - int index_counter; - int rdn_level = -1; - int retcode; + PyObject *return_value = NULL; + Py_buffer view = {NULL, NULL}; + double entropy; - dn = PyList_New(0); - if (dn == NULL) - return NULL; - /* now create another tuple to hold the top-level RDN */ - rdn = PyList_New(0); - if (rdn == NULL) - goto fail0; + if (!PyArg_ParseTuple(args, "s*d:RAND_add", + &view, &entropy)) + goto exit; + return_value = _ssl_RAND_add_impl(module, &view, entropy); - for (index_counter = 0; - index_counter < entry_count; - index_counter++) - { - entry = X509_NAME_get_entry(xname, index_counter); +exit: + /* Cleanup for view */ + if (view.obj) + PyBuffer_Release(&view); - /* check to see if we've gotten to a new RDN */ - if (rdn_level >= 0) { - if (rdn_level != entry->set) { - /* yes, new RDN */ - /* add old RDN to DN */ - rdnt = PyList_AsTuple(rdn); - Py_DECREF(rdn); - if (rdnt == NULL) - goto fail0; - retcode = PyList_Append(dn, rdnt); - Py_DECREF(rdnt); - if (retcode < 0) - goto fail0; - /* create new RDN */ - rdn = PyList_New(0); - if (rdn == NULL) - goto fail0; - } - } - rdn_level = entry->set; - - /* now add this attribute to the current RDN */ - name = X509_NAME_ENTRY_get_object(entry); - value = X509_NAME_ENTRY_get_data(entry); - attr = _create_tuple_for_attribute(name, value); - /* - fprintf(stderr, "RDN level %d, attribute %s: %s\n", - entry->set, - PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 0)), - PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 1))); - */ - if (attr == NULL) - goto fail1; - retcode = PyList_Append(rdn, attr); - Py_DECREF(attr); - if (retcode < 0) - goto fail1; - } - /* now, there's typically a dangling RDN */ - if (rdn != NULL) { - if (PyList_GET_SIZE(rdn) > 0) { - rdnt = PyList_AsTuple(rdn); - Py_DECREF(rdn); - if (rdnt == NULL) - goto fail0; - retcode = PyList_Append(dn, rdnt); - Py_DECREF(rdnt); - if (retcode < 0) - goto fail0; - } - else { - Py_DECREF(rdn); - } - } - - /* convert list to tuple */ - rdnt = PyList_AsTuple(dn); - Py_DECREF(dn); - if (rdnt == NULL) - return NULL; - return rdnt; - - fail1: - Py_XDECREF(rdn); - - fail0: - Py_XDECREF(dn); - return NULL; + return return_value; } +PyDoc_STRVAR(_ssl_RAND_bytes__doc__, +"RAND_bytes($module, n, /)\n" +"--\n" +"\n" +"Generate n cryptographically strong pseudo-random bytes."); + +#define _SSL_RAND_BYTES_METHODDEF \ + {"RAND_bytes", (PyCFunction)_ssl_RAND_bytes, METH_O, _ssl_RAND_bytes__doc__}, + static PyObject * -_get_peer_alt_names (X509 *certificate) { +_ssl_RAND_bytes_impl(PyModuleDef *module, int n); - /* this code follows the procedure outlined in - OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() - function to extract the STACK_OF(GENERAL_NAME), - then iterates through the stack to add the - names. */ +static PyObject * +_ssl_RAND_bytes(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int n; - int i, j; - PyObject *peer_alt_names = Py_None; - PyObject *v = NULL, *t; - X509_EXTENSION *ext = NULL; - GENERAL_NAMES *names = NULL; - GENERAL_NAME *name; - const X509V3_EXT_METHOD *method; - BIO *biobuf = NULL; - char buf[2048]; - char *vptr; - int len; - const unsigned char *p; + if (!PyArg_Parse(arg, "i:RAND_bytes", &n)) + goto exit; + return_value = _ssl_RAND_bytes_impl(module, n); - if (certificate == NULL) - return peer_alt_names; - - /* get a memory buffer */ - biobuf = BIO_new(BIO_s_mem()); - - i = -1; - while ((i = X509_get_ext_by_NID( - certificate, NID_subject_alt_name, i)) >= 0) { - - if (peer_alt_names == Py_None) { - peer_alt_names = PyList_New(0); - if (peer_alt_names == NULL) - goto fail; - } - - /* now decode the altName */ - ext = X509_get_ext(certificate, i); - if(!(method = X509V3_EXT_get(ext))) { - PyErr_SetString - (PySSLErrorObject, - ERRSTR("No method for internalizing subjectAltName!")); - goto fail; - } - - p = ext->value->data; - if (method->it) - names = (GENERAL_NAMES*) - (ASN1_item_d2i(NULL, - &p, - ext->value->length, - ASN1_ITEM_ptr(method->it))); - else - names = (GENERAL_NAMES*) - (method->d2i(NULL, - &p, - ext->value->length)); - - for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { - /* get a rendering of each name in the set of names */ - int gntype; - ASN1_STRING *as = NULL; - - name = sk_GENERAL_NAME_value(names, j); - gntype = name->type; - switch (gntype) { - case GEN_DIRNAME: - /* we special-case DirName as a tuple of - tuples of attributes */ - - t = PyTuple_New(2); - if (t == NULL) { - goto fail; - } - - v = PyUnicode_FromString("DirName"); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 0, v); - - v = _create_tuple_for_X509_NAME (name->d.dirn); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 1, v); - break; - - case GEN_EMAIL: - case GEN_DNS: - case GEN_URI: - /* GENERAL_NAME_print() doesn't handle NULL bytes in ASN1_string - correctly, CVE-2013-4238 */ - t = PyTuple_New(2); - if (t == NULL) - goto fail; - switch (gntype) { - case GEN_EMAIL: - v = PyUnicode_FromString("email"); - as = name->d.rfc822Name; - break; - case GEN_DNS: - v = PyUnicode_FromString("DNS"); - as = name->d.dNSName; - break; - case GEN_URI: - v = PyUnicode_FromString("URI"); - as = name->d.uniformResourceIdentifier; - break; - } - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 0, v); - v = PyUnicode_FromStringAndSize((char *)ASN1_STRING_data(as), - ASN1_STRING_length(as)); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 1, v); - break; - - default: - /* for everything else, we use the OpenSSL print form */ - switch (gntype) { - /* check for new general name type */ - case GEN_OTHERNAME: - case GEN_X400: - case GEN_EDIPARTY: - case GEN_IPADD: - case GEN_RID: - break; - default: - if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, - "Unknown general name type %d", - gntype) == -1) { - goto fail; - } - break; - } - (void) BIO_reset(biobuf); - GENERAL_NAME_print(biobuf, name); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail; - } - vptr = strchr(buf, ':'); - if (vptr == NULL) - goto fail; - t = PyTuple_New(2); - if (t == NULL) - goto fail; - v = PyUnicode_FromStringAndSize(buf, (vptr - buf)); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 0, v); - v = PyUnicode_FromStringAndSize((vptr + 1), - (len - (vptr - buf + 1))); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 1, v); - break; - } - - /* and add that rendering to the list */ - - if (PyList_Append(peer_alt_names, t) < 0) { - Py_DECREF(t); - goto fail; - } - Py_DECREF(t); - } - sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); - } - BIO_free(biobuf); - if (peer_alt_names != Py_None) { - v = PyList_AsTuple(peer_alt_names); - Py_DECREF(peer_alt_names); - return v; - } else { - return peer_alt_names; - } - - - fail: - if (biobuf != NULL) - BIO_free(biobuf); - - if (peer_alt_names != Py_None) { - Py_XDECREF(peer_alt_names); - } - - return NULL; +exit: + return return_value; } +PyDoc_STRVAR(_ssl_RAND_pseudo_bytes__doc__, +"RAND_pseudo_bytes($module, n, /)\n" +"--\n" +"\n" +"Generate n pseudo-random bytes.\n" +"\n" +"Return a pair (bytes, is_cryptographic). is_cryptographic is True\n" +"if the bytes generated are cryptographically strong."); + +#define _SSL_RAND_PSEUDO_BYTES_METHODDEF \ + {"RAND_pseudo_bytes", (PyCFunction)_ssl_RAND_pseudo_bytes, METH_O, _ssl_RAND_pseudo_bytes__doc__}, + static PyObject * -_get_aia_uri(X509 *certificate, int nid) { - PyObject *lst = NULL, *ostr = NULL; - int i, result; - AUTHORITY_INFO_ACCESS *info; +_ssl_RAND_pseudo_bytes_impl(PyModuleDef *module, int n); - info = X509_get_ext_d2i(certificate, NID_info_access, NULL, NULL); - if ((info == NULL) || (sk_ACCESS_DESCRIPTION_num(info) == 0)) { - return Py_None; - } +static PyObject * +_ssl_RAND_pseudo_bytes(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int n; - if ((lst = PyList_New(0)) == NULL) { - goto fail; - } + if (!PyArg_Parse(arg, "i:RAND_pseudo_bytes", &n)) + goto exit; + return_value = _ssl_RAND_pseudo_bytes_impl(module, n); - for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { - ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); - ASN1_IA5STRING *uri; - - if ((OBJ_obj2nid(ad->method) != nid) || - (ad->location->type != GEN_URI)) { - continue; - } - uri = ad->location->d.uniformResourceIdentifier; - ostr = PyUnicode_FromStringAndSize((char *)uri->data, - uri->length); - if (ostr == NULL) { - goto fail; - } - result = PyList_Append(lst, ostr); - Py_DECREF(ostr); - if (result < 0) { - goto fail; - } - } - AUTHORITY_INFO_ACCESS_free(info); - - /* convert to tuple or None */ - if (PyList_Size(lst) == 0) { - Py_DECREF(lst); - return Py_None; - } else { - PyObject *tup; - tup = PyList_AsTuple(lst); - Py_DECREF(lst); - return tup; - } - - fail: - AUTHORITY_INFO_ACCESS_free(info); - Py_XDECREF(lst); - return NULL; +exit: + return return_value; } +PyDoc_STRVAR(_ssl_RAND_status__doc__, +"RAND_status($module, /)\n" +"--\n" +"\n" +"Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n" +"\n" +"It is necessary to seed the PRNG with RAND_add() on some platforms before\n" +"using the ssl() function."); + +#define _SSL_RAND_STATUS_METHODDEF \ + {"RAND_status", (PyCFunction)_ssl_RAND_status, METH_NOARGS, _ssl_RAND_status__doc__}, + static PyObject * -_get_crl_dp(X509 *certificate) { - STACK_OF(DIST_POINT) *dps; - int i, j, result; - PyObject *lst; +_ssl_RAND_status_impl(PyModuleDef *module); -#if OPENSSL_VERSION_NUMBER < 0x10001000L - dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, - NULL, NULL); -#else - /* Calls x509v3_cache_extensions and sets up crldp */ - X509_check_ca(certificate); - dps = certificate->crldp; -#endif - - if (dps == NULL) { - return Py_None; - } - - if ((lst = PyList_New(0)) == NULL) { - return NULL; - } - - for (i=0; i < sk_DIST_POINT_num(dps); i++) { - DIST_POINT *dp; - STACK_OF(GENERAL_NAME) *gns; - - dp = sk_DIST_POINT_value(dps, i); - gns = dp->distpoint->name.fullname; - - for (j=0; j < sk_GENERAL_NAME_num(gns); j++) { - GENERAL_NAME *gn; - ASN1_IA5STRING *uri; - PyObject *ouri; - - gn = sk_GENERAL_NAME_value(gns, j); - if (gn->type != GEN_URI) { - continue; - } - uri = gn->d.uniformResourceIdentifier; - ouri = PyUnicode_FromStringAndSize((char *)uri->data, - uri->length); - if (ouri == NULL) { - Py_DECREF(lst); - return NULL; - } - result = PyList_Append(lst, ouri); - Py_DECREF(ouri); - if (result < 0) { - Py_DECREF(lst); - return NULL; - } - } - } - /* convert to tuple or None */ - if (PyList_Size(lst) == 0) { - Py_DECREF(lst); - return Py_None; - } else { - PyObject *tup; - tup = PyList_AsTuple(lst); - Py_DECREF(lst); - return tup; - } +static PyObject * +_ssl_RAND_status(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return _ssl_RAND_status_impl(module); } +#if defined(HAVE_RAND_EGD) + +PyDoc_STRVAR(_ssl_RAND_egd__doc__, +"RAND_egd($module, path, /)\n" +"--\n" +"\n" +"Queries the entropy gather daemon (EGD) on the socket named by \'path\'.\n" +"\n" +"Returns number of bytes read. Raises SSLError if connection to EGD\n" +"fails or if it does not provide enough data to seed PRNG."); + +#define _SSL_RAND_EGD_METHODDEF \ + {"RAND_egd", (PyCFunction)_ssl_RAND_egd, METH_O, _ssl_RAND_egd__doc__}, + static PyObject * -_decode_certificate(X509 *certificate) { +_ssl_RAND_egd_impl(PyModuleDef *module, PyObject *path); - PyObject *retval = NULL; - BIO *biobuf = NULL; - PyObject *peer; - PyObject *peer_alt_names = NULL; - PyObject *issuer; - PyObject *version; - PyObject *sn_obj; - PyObject *obj; - ASN1_INTEGER *serialNumber; - char buf[2048]; - int len, result; - ASN1_TIME *notBefore, *notAfter; - PyObject *pnotBefore, *pnotAfter; +static PyObject * +_ssl_RAND_egd(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *path; - retval = PyDict_New(); - if (retval == NULL) - return NULL; + if (!PyArg_Parse(arg, "O&:RAND_egd", PyUnicode_FSConverter, &path)) + goto exit; + return_value = _ssl_RAND_egd_impl(module, path); - peer = _create_tuple_for_X509_NAME( - X509_get_subject_name(certificate)); - if (peer == NULL) - goto fail0; - if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { - Py_DECREF(peer); - goto fail0; - } - Py_DECREF(peer); - - issuer = _create_tuple_for_X509_NAME( - X509_get_issuer_name(certificate)); - if (issuer == NULL) - goto fail0; - if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { - Py_DECREF(issuer); - goto fail0; - } - Py_DECREF(issuer); - - version = PyLong_FromLong(X509_get_version(certificate) + 1); - if (version == NULL) - goto fail0; - if (PyDict_SetItemString(retval, "version", version) < 0) { - Py_DECREF(version); - goto fail0; - } - Py_DECREF(version); - - /* get a memory buffer */ - biobuf = BIO_new(BIO_s_mem()); - - (void) BIO_reset(biobuf); - serialNumber = X509_get_serialNumber(certificate); - /* should not exceed 20 octets, 160 bits, so buf is big enough */ - i2a_ASN1_INTEGER(biobuf, serialNumber); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - sn_obj = PyUnicode_FromStringAndSize(buf, len); - if (sn_obj == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { - Py_DECREF(sn_obj); - goto fail1; - } - Py_DECREF(sn_obj); - - (void) BIO_reset(biobuf); - notBefore = X509_get_notBefore(certificate); - ASN1_TIME_print(biobuf, notBefore); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - pnotBefore = PyUnicode_FromStringAndSize(buf, len); - if (pnotBefore == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { - Py_DECREF(pnotBefore); - goto fail1; - } - Py_DECREF(pnotBefore); - - (void) BIO_reset(biobuf); - notAfter = X509_get_notAfter(certificate); - ASN1_TIME_print(biobuf, notAfter); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - pnotAfter = PyUnicode_FromStringAndSize(buf, len); - if (pnotAfter == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) { - Py_DECREF(pnotAfter); - goto fail1; - } - Py_DECREF(pnotAfter); - - /* Now look for subjectAltName */ - - peer_alt_names = _get_peer_alt_names(certificate); - if (peer_alt_names == NULL) - goto fail1; - else if (peer_alt_names != Py_None) { - if (PyDict_SetItemString(retval, "subjectAltName", - peer_alt_names) < 0) { - Py_DECREF(peer_alt_names); - goto fail1; - } - Py_DECREF(peer_alt_names); - } - - /* Authority Information Access: OCSP URIs */ - obj = _get_aia_uri(certificate, NID_ad_OCSP); - if (obj == NULL) { - goto fail1; - } else if (obj != Py_None) { - result = PyDict_SetItemString(retval, "OCSP", obj); - Py_DECREF(obj); - if (result < 0) { - goto fail1; - } - } - - obj = _get_aia_uri(certificate, NID_ad_ca_issuers); - if (obj == NULL) { - goto fail1; - } else if (obj != Py_None) { - result = PyDict_SetItemString(retval, "caIssuers", obj); - Py_DECREF(obj); - if (result < 0) { - goto fail1; - } - } - - /* CDP (CRL distribution points) */ - obj = _get_crl_dp(certificate); - if (obj == NULL) { - goto fail1; - } else if (obj != Py_None) { - result = PyDict_SetItemString(retval, "crlDistributionPoints", obj); - Py_DECREF(obj); - if (result < 0) { - goto fail1; - } - } - - BIO_free(biobuf); - return retval; - - fail1: - if (biobuf != NULL) - BIO_free(biobuf); - fail0: - Py_XDECREF(retval); - return NULL; +exit: + return return_value; } +#endif /* defined(HAVE_RAND_EGD) */ + +PyDoc_STRVAR(_ssl_get_default_verify_paths__doc__, +"get_default_verify_paths($module, /)\n" +"--\n" +"\n" +"Return search paths and environment vars that are used by SSLContext\'s set_default_verify_paths() to load default CAs.\n" +"\n" +"The values are \'cert_file_env\', \'cert_file\', \'cert_dir_env\', \'cert_dir\'."); + +#define _SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF \ + {"get_default_verify_paths", (PyCFunction)_ssl_get_default_verify_paths, METH_NOARGS, _ssl_get_default_verify_paths__doc__}, + static PyObject * -_certificate_to_der(X509 *certificate) +_ssl_get_default_verify_paths_impl(PyModuleDef *module); + +static PyObject * +_ssl_get_default_verify_paths(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - unsigned char *bytes_buf = NULL; - int len; - PyObject *retval; - - bytes_buf = NULL; - len = i2d_X509(certificate, &bytes_buf); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return NULL; - } - /* this is actually an immutable bytes sequence */ - retval = PyBytes_FromStringAndSize((const char *) bytes_buf, len); - OPENSSL_free(bytes_buf); - return retval; + return _ssl_get_default_verify_paths_impl(module); } +PyDoc_STRVAR(_ssl_txt2obj__doc__, +"txt2obj($module, /, txt, name=False)\n" +"--\n" +"\n" +"Lookup NID, short name, long name and OID of an ASN1_OBJECT.\n" +"\n" +"By default objects are looked up by OID. With name=True short and\n" +"long name are also matched."); + +#define _SSL_TXT2OBJ_METHODDEF \ + {"txt2obj", (PyCFunction)_ssl_txt2obj, METH_VARARGS|METH_KEYWORDS, _ssl_txt2obj__doc__}, + static PyObject * -PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { +_ssl_txt2obj_impl(PyModuleDef *module, const char *txt, int name); - PyObject *retval = NULL; - PyObject *filename; - X509 *x=NULL; - BIO *cert; +static PyObject * +_ssl_txt2obj(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"txt", "name", NULL}; + const char *txt; + int name = 0; - if (!PyArg_ParseTuple(args, "O&:test_decode_certificate", - PyUnicode_FSConverter, &filename)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|p:txt2obj", _keywords, + &txt, &name)) + goto exit; + return_value = _ssl_txt2obj_impl(module, txt, name); - if ((cert=BIO_new(BIO_s_file())) == NULL) { - PyErr_SetString(PySSLErrorObject, - "Can't malloc memory to read file"); - goto fail0; - } - - if (BIO_read_filename(cert, PyBytes_AsString(filename)) <= 0) { - PyErr_SetString(PySSLErrorObject, - "Can't open file"); - goto fail0; - } - - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); - if (x == NULL) { - PyErr_SetString(PySSLErrorObject, - "Error decoding PEM-encoded file"); - goto fail0; - } - - retval = _decode_certificate(x); - X509_free(x); - - fail0: - Py_DECREF(filename); - if (cert != NULL) BIO_free(cert); - return retval; +exit: + return return_value; } +PyDoc_STRVAR(_ssl_nid2obj__doc__, +"nid2obj($module, nid, /)\n" +"--\n" +"\n" +"Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID."); + +#define _SSL_NID2OBJ_METHODDEF \ + {"nid2obj", (PyCFunction)_ssl_nid2obj, METH_O, _ssl_nid2obj__doc__}, static PyObject * -PySSL_peercert(PySSLSocket *self, PyObject *args) +_ssl_nid2obj_impl(PyModuleDef *module, int nid); + +static PyObject * +_ssl_nid2obj(PyModuleDef *module, PyObject *arg) { - int verification; - int binary_mode = 0; + PyObject *return_value = NULL; + int nid; - if (!PyArg_ParseTuple(args, "|p:peer_certificate", &binary_mode)) - return NULL; + if (!PyArg_Parse(arg, "i:nid2obj", &nid)) + goto exit; + return_value = _ssl_nid2obj_impl(module, nid); - if (!self->handshake_done) { - PyErr_SetString(PyExc_ValueError, - "handshake not done yet"); - return NULL; - } - if (!self->peer_cert) - Py_RETURN_NONE; - - if (binary_mode) { - /* return cert in DER-encoded format */ - return _certificate_to_der(self->peer_cert); - } else { - verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl)); - if ((verification & SSL_VERIFY_PEER) == 0) - return PyDict_New(); - else - return _decode_certificate(self->peer_cert); - } +exit: + return return_value; } -PyDoc_STRVAR(PySSL_peercert_doc, -"peer_certificate([der=False]) -> certificate\n\ -\n\ -Returns the certificate for the peer. If no certificate was provided,\n\ -returns None. If a certificate was provided, but not validated, returns\n\ -an empty dictionary. Otherwise returns a dict containing information\n\ -about the peer certificate.\n\ -\n\ -If the optional argument is True, returns a DER-encoded copy of the\n\ -peer certificate, or None if no certificate was provided. This will\n\ -return the certificate even if it wasn't validated."); +#if defined(_MSC_VER) + +PyDoc_STRVAR(_ssl_enum_certificates__doc__, +"enum_certificates($module, /, store_name)\n" +"--\n" +"\n" +"Retrieve certificates from Windows\' cert store.\n" +"\n" +"store_name may be one of \'CA\', \'ROOT\' or \'MY\'. The system may provide\n" +"more cert storages, too. The function returns a list of (bytes,\n" +"encoding_type, trust) tuples. The encoding_type flag can be interpreted\n" +"with X509_ASN_ENCODING or PKCS_7_ASN_ENCODING. The trust setting is either\n" +"a set of OIDs or the boolean True."); + +#define _SSL_ENUM_CERTIFICATES_METHODDEF \ + {"enum_certificates", (PyCFunction)_ssl_enum_certificates, METH_VARARGS|METH_KEYWORDS, _ssl_enum_certificates__doc__}, static PyObject * -cipher_to_tuple(const SSL_CIPHER *cipher) +_ssl_enum_certificates_impl(PyModuleDef *module, const char *store_name); + +static PyObject * +_ssl_enum_certificates(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - const char *cipher_name, *cipher_protocol; - PyObject *v, *retval = PyTuple_New(3); - if (retval == NULL) - return NULL; + PyObject *return_value = NULL; + static char *_keywords[] = {"store_name", NULL}; + const char *store_name; - cipher_name = SSL_CIPHER_get_name(cipher); - if (cipher_name == NULL) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(retval, 0, Py_None); - } else { - v = PyUnicode_FromString(cipher_name); - if (v == NULL) - goto fail; - PyTuple_SET_ITEM(retval, 0, v); - } + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:enum_certificates", _keywords, + &store_name)) + goto exit; + return_value = _ssl_enum_certificates_impl(module, store_name); - cipher_protocol = SSL_CIPHER_get_version(cipher); - if (cipher_protocol == NULL) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(retval, 1, Py_None); - } else { - v = PyUnicode_FromString(cipher_protocol); - if (v == NULL) - goto fail; - PyTuple_SET_ITEM(retval, 1, v); - } - - v = PyLong_FromLong(SSL_CIPHER_get_bits(cipher, NULL)); - if (v == NULL) - goto fail; - PyTuple_SET_ITEM(retval, 2, v); - - return retval; - - fail: - Py_DECREF(retval); - return NULL; +exit: + return return_value; } -static PyObject *PySSL_shared_ciphers(PySSLSocket *self) +#endif /* defined(_MSC_VER) */ + +#if defined(_MSC_VER) + +PyDoc_STRVAR(_ssl_enum_crls__doc__, +"enum_crls($module, /, store_name)\n" +"--\n" +"\n" +"Retrieve CRLs from Windows\' cert store.\n" +"\n" +"store_name may be one of \'CA\', \'ROOT\' or \'MY\'. The system may provide\n" +"more cert storages, too. The function returns a list of (bytes,\n" +"encoding_type) tuples. The encoding_type flag can be interpreted with\n" +"X509_ASN_ENCODING or PKCS_7_ASN_ENCODING."); + +#define _SSL_ENUM_CRLS_METHODDEF \ + {"enum_crls", (PyCFunction)_ssl_enum_crls, METH_VARARGS|METH_KEYWORDS, _ssl_enum_crls__doc__}, + +static PyObject * +_ssl_enum_crls_impl(PyModuleDef *module, const char *store_name); + +static PyObject * +_ssl_enum_crls(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - SSL_SESSION *sess = SSL_get_session(self->ssl); - STACK_OF(SSL_CIPHER) *ciphers; - int i; - PyObject *res; + PyObject *return_value = NULL; + static char *_keywords[] = {"store_name", NULL}; + const char *store_name; - if (!sess || !sess->ciphers) - Py_RETURN_NONE; - ciphers = sess->ciphers; - res = PyList_New(sk_SSL_CIPHER_num(ciphers)); - if (!res) - return NULL; - for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { - PyObject *tup = cipher_to_tuple(sk_SSL_CIPHER_value(ciphers, i)); - if (!tup) { - Py_DECREF(res); - return NULL; - } - PyList_SET_ITEM(res, i, tup); - } - return res; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:enum_crls", _keywords, + &store_name)) + goto exit; + return_value = _ssl_enum_crls_impl(module, store_name); + +exit: + return return_value; } -static PyObject *PySSL_cipher (PySSLSocket *self) -{ - const SSL_CIPHER *current; +#endif /* defined(_MSC_VER) */ - if (self->ssl == NULL) - Py_RETURN_NONE; - current = SSL_get_current_cipher(self->ssl); - if (current == NULL) - Py_RETURN_NONE; - return cipher_to_tuple(current); -} +#ifndef _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF + #define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF +#endif /* !defined(_SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF) */ -static PyObject *PySSL_version(PySSLSocket *self) -{ - const char *version; +#ifndef _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF + #define _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF +#endif /* !defined(_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF) */ - if (self->ssl == NULL) - Py_RETURN_NONE; - version = SSL_get_version(self->ssl); - if (!strcmp(version, "unknown")) - Py_RETURN_NONE; - return PyUnicode_FromString(version); -} +#ifndef _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF + #define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF +#endif /* !defined(_SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF) */ -#ifdef OPENSSL_NPN_NEGOTIATED -static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { - const unsigned char *out; - unsigned int outlen; +#ifndef _SSL_RAND_EGD_METHODDEF + #define _SSL_RAND_EGD_METHODDEF +#endif /* !defined(_SSL_RAND_EGD_METHODDEF) */ - SSL_get0_next_proto_negotiated(self->ssl, - &out, &outlen); +#ifndef _SSL_ENUM_CERTIFICATES_METHODDEF + #define _SSL_ENUM_CERTIFICATES_METHODDEF +#endif /* !defined(_SSL_ENUM_CERTIFICATES_METHODDEF) */ - if (out == NULL) - Py_RETURN_NONE; - return PyUnicode_FromStringAndSize((char *)out, outlen); -} -#endif - -#ifdef HAVE_ALPN -static PyObject *PySSL_selected_alpn_protocol(PySSLSocket *self) { - const unsigned char *out; - unsigned int outlen; - - SSL_get0_alpn_selected(self->ssl, &out, &outlen); - - if (out == NULL) - Py_RETURN_NONE; - return PyUnicode_FromStringAndSize((char *)out, outlen); -} -#endif - -static PyObject *PySSL_compression(PySSLSocket *self) { -#ifdef OPENSSL_NO_COMP - Py_RETURN_NONE; -#else - const COMP_METHOD *comp_method; - const char *short_name; - - if (self->ssl == NULL) - Py_RETURN_NONE; - comp_method = SSL_get_current_compression(self->ssl); - if (comp_method == NULL || comp_method->type == NID_undef) - Py_RETURN_NONE; - short_name = OBJ_nid2sn(comp_method->type); - if (short_name == NULL) - Py_RETURN_NONE; - return PyUnicode_DecodeFSDefault(short_name); -#endif -} - -static PySSLContext *PySSL_get_context(PySSLSocket *self, void *closure) { - Py_INCREF(self->ctx); - return self->ctx; -} - -static int PySSL_set_context(PySSLSocket *self, PyObject *value, - void *closure) { - - if (PyObject_TypeCheck(value, &PySSLContext_Type)) { -#if !HAVE_SNI - PyErr_SetString(PyExc_NotImplementedError, "setting a socket's " - "context is not supported by your OpenSSL library"); - return -1; -#else - Py_INCREF(value); - Py_DECREF(self->ctx); - self->ctx = (PySSLContext *) value; - SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); -#endif - } else { - PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); - return -1; - } - - return 0; -} - -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\ -on the SSLContext to change the certificate information associated with the\n\ -SSLSocket before the cryptographic exchange handshake messages\n"); - - -static PyObject * -PySSL_get_server_side(PySSLSocket *self, void *c) -{ - return PyBool_FromLong(self->socket_type == PY_SSL_SERVER); -} - -PyDoc_STRVAR(PySSL_get_server_side_doc, -"Whether this is a server-side socket."); - -static PyObject * -PySSL_get_server_hostname(PySSLSocket *self, void *c) -{ - if (self->server_hostname == NULL) - Py_RETURN_NONE; - Py_INCREF(self->server_hostname); - return self->server_hostname; -} - -PyDoc_STRVAR(PySSL_get_server_hostname_doc, -"The currently set server hostname (for SNI)."); - -static PyObject * -PySSL_get_owner(PySSLSocket *self, void *c) -{ - PyObject *owner; - - if (self->owner == NULL) - Py_RETURN_NONE; - - owner = PyWeakref_GetObject(self->owner); - Py_INCREF(owner); - return owner; -} - -static int -PySSL_set_owner(PySSLSocket *self, PyObject *value, void *c) -{ - Py_XDECREF(self->owner); - self->owner = PyWeakref_NewRef(value, NULL); - if (self->owner == NULL) - return -1; - return 0; -} - -PyDoc_STRVAR(PySSL_get_owner_doc, -"The Python-level owner of this object.\ -Passed as \"self\" in servername callback."); - - -static void PySSL_dealloc(PySSLSocket *self) -{ - if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); - if (self->ssl) - SSL_free(self->ssl); - Py_XDECREF(self->Socket); - Py_XDECREF(self->ctx); - Py_XDECREF(self->server_hostname); - Py_XDECREF(self->owner); - PyObject_Del(self); -} - -/* If the socket has a timeout, do a select()/poll() on the socket. - The argument writing indicates the direction. - Returns one of the possibilities in the timeout_state enum (above). - */ - -static int -PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout) -{ - int rc; -#ifdef HAVE_POLL - struct pollfd pollfd; - _PyTime_t ms; -#else - int nfds; - fd_set fds; - struct timeval tv; -#endif - - /* Nothing to do unless we're in timeout mode (not non-blocking) */ - if ((s == NULL) || (timeout == 0)) - return SOCKET_IS_NONBLOCKING; - else if (timeout < 0) { - if (s->sock_timeout > 0) - return SOCKET_HAS_TIMED_OUT; - else - return SOCKET_IS_BLOCKING; - } - - /* Guard against closed socket */ - if (s->sock_fd < 0) - return SOCKET_HAS_BEEN_CLOSED; - - /* Prefer poll, if available, since you can poll() any fd - * which can't be done with select(). */ -#ifdef HAVE_POLL - pollfd.fd = s->sock_fd; - pollfd.events = writing ? POLLOUT : POLLIN; - - /* timeout is in seconds, poll() uses milliseconds */ - ms = (int)_PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); - assert(ms <= INT_MAX); - - PySSL_BEGIN_ALLOW_THREADS - rc = poll(&pollfd, 1, (int)ms); - PySSL_END_ALLOW_THREADS -#else - /* Guard against socket too large for select*/ - if (!_PyIsSelectable_fd(s->sock_fd)) - return SOCKET_TOO_LARGE_FOR_SELECT; - - _PyTime_AsTimeval_noraise(timeout, &tv, _PyTime_ROUND_CEILING); - - FD_ZERO(&fds); - FD_SET(s->sock_fd, &fds); - - /* Wait until the socket becomes ready */ - PySSL_BEGIN_ALLOW_THREADS - nfds = Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int); - if (writing) - rc = select(nfds, NULL, &fds, NULL, &tv); - else - rc = select(nfds, &fds, NULL, NULL, &tv); - PySSL_END_ALLOW_THREADS -#endif - - /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise - (when we are able to write or when there's something to read) */ - return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; -} - -static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) -{ - Py_buffer buf; - int len; - int sockstate; - int err; - int nonblocking; - PySocketSockObject *sock = GET_SOCKET(self); - _PyTime_t timeout, deadline = 0; - int has_timeout; - - if (sock != NULL) { - if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", - PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } - Py_INCREF(sock); - } - - if (!PyArg_ParseTuple(args, "y*:write", &buf)) { - Py_XDECREF(sock); - return NULL; - } - - if (buf.len > INT_MAX) { - PyErr_Format(PyExc_OverflowError, - "string longer than %d bytes", INT_MAX); - goto error; - } - - if (sock != NULL) { - /* just in case the blocking state of the socket has been changed */ - nonblocking = (sock->sock_timeout >= 0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - } - - timeout = GET_SOCKET_TIMEOUT(sock); - has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; - - sockstate = PySSL_select(sock, 1, timeout); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, - "The write operation timed out"); - goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket has been closed."); - goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); - goto error; - } - - do { - PySSL_BEGIN_ALLOW_THREADS - len = SSL_write(self->ssl, buf.buf, (int)buf.len); - err = SSL_get_error(self->ssl, len); - PySSL_END_ALLOW_THREADS - - if (PyErr_CheckSignals()) - goto error; - - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); - - if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0, timeout); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1, timeout); - } else { - sockstate = SOCKET_OPERATION_OK; - } - - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, - "The write operation timed out"); - goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket has been closed."); - goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - - Py_XDECREF(sock); - PyBuffer_Release(&buf); - if (len > 0) - return PyLong_FromLong(len); - else - return PySSL_SetError(self, len, __FILE__, __LINE__); - -error: - Py_XDECREF(sock); - PyBuffer_Release(&buf); - return NULL; -} - -PyDoc_STRVAR(PySSL_SSLwrite_doc, -"write(s) -> len\n\ -\n\ -Writes the string s into the SSL object. Returns the number\n\ -of bytes written."); - -static PyObject *PySSL_SSLpending(PySSLSocket *self) -{ - int count = 0; - - PySSL_BEGIN_ALLOW_THREADS - count = SSL_pending(self->ssl); - PySSL_END_ALLOW_THREADS - if (count < 0) - return PySSL_SetError(self, count, __FILE__, __LINE__); - else - return PyLong_FromLong(count); -} - -PyDoc_STRVAR(PySSL_SSLpending_doc, -"pending() -> count\n\ -\n\ -Returns the number of already decrypted bytes available for read,\n\ -pending on the connection.\n"); - -static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) -{ - PyObject *dest = NULL; - Py_buffer buf; - char *mem; - int len, count; - int buf_passed = 0; - int sockstate; - int err; - int nonblocking; - PySocketSockObject *sock = GET_SOCKET(self); - _PyTime_t timeout, deadline = 0; - int has_timeout; - - if (sock != NULL) { - if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", - PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } - Py_INCREF(sock); - } - - buf.obj = NULL; - buf.buf = NULL; - if (!PyArg_ParseTuple(args, "i|w*:read", &len, &buf)) - goto error; - - if ((buf.buf == NULL) && (buf.obj == NULL)) { - dest = PyBytes_FromStringAndSize(NULL, len); - if (dest == NULL) - goto error; - mem = PyBytes_AS_STRING(dest); - } - else { - buf_passed = 1; - mem = buf.buf; - if (len <= 0 || len > buf.len) { - len = (int) buf.len; - if (buf.len != len) { - PyErr_SetString(PyExc_OverflowError, - "maximum length can't fit in a C 'int'"); - goto error; - } - } - } - - if (sock != NULL) { - /* just in case the blocking state of the socket has been changed */ - nonblocking = (sock->sock_timeout >= 0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - } - - timeout = GET_SOCKET_TIMEOUT(sock); - has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; - - do { - PySSL_BEGIN_ALLOW_THREADS - count = SSL_read(self->ssl, mem, len); - err = SSL_get_error(self->ssl, count); - PySSL_END_ALLOW_THREADS - - if (PyErr_CheckSignals()) - goto error; - - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); - - if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0, timeout); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1, timeout); - } else if (err == SSL_ERROR_ZERO_RETURN && - SSL_get_shutdown(self->ssl) == SSL_RECEIVED_SHUTDOWN) - { - count = 0; - goto done; - } - else - sockstate = SOCKET_OPERATION_OK; - - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, - "The read operation timed out"); - goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - - if (count <= 0) { - PySSL_SetError(self, count, __FILE__, __LINE__); - goto error; - } - -done: - Py_XDECREF(sock); - if (!buf_passed) { - _PyBytes_Resize(&dest, count); - return dest; - } - else { - PyBuffer_Release(&buf); - return PyLong_FromLong(count); - } - -error: - Py_XDECREF(sock); - if (!buf_passed) - Py_XDECREF(dest); - else - PyBuffer_Release(&buf); - return NULL; -} - -PyDoc_STRVAR(PySSL_SSLread_doc, -"read([len]) -> string\n\ -\n\ -Read up to len bytes from the SSL socket."); - -static PyObject *PySSL_SSLshutdown(PySSLSocket *self) -{ - int err, ssl_err, sockstate, nonblocking; - int zeros = 0; - PySocketSockObject *sock = GET_SOCKET(self); - _PyTime_t timeout, deadline = 0; - int has_timeout; - - if (sock != NULL) { - /* Guard against closed socket */ - if ((((PyObject*)sock) == Py_None) || (sock->sock_fd < 0)) { - _setSSLError("Underlying socket connection gone", - PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } - Py_INCREF(sock); - - /* Just in case the blocking state of the socket has been changed */ - nonblocking = (sock->sock_timeout >= 0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - } - - timeout = GET_SOCKET_TIMEOUT(sock); - has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; - - while (1) { - PySSL_BEGIN_ALLOW_THREADS - /* Disable read-ahead so that unwrap can work correctly. - * Otherwise OpenSSL might read in too much data, - * eating clear text data that happens to be - * transmitted after the SSL shutdown. - * Should be safe to call repeatedly every time this - * function is used and the shutdown_seen_zero != 0 - * condition is met. - */ - if (self->shutdown_seen_zero) - SSL_set_read_ahead(self->ssl, 0); - err = SSL_shutdown(self->ssl); - PySSL_END_ALLOW_THREADS - - /* If err == 1, a secure shutdown with SSL_shutdown() is complete */ - if (err > 0) - break; - if (err == 0) { - /* Don't loop endlessly; instead preserve legacy - behaviour of trying SSL_shutdown() only twice. - This looks necessary for OpenSSL < 0.9.8m */ - if (++zeros > 1) - break; - /* Shutdown was sent, now try receiving */ - self->shutdown_seen_zero = 1; - continue; - } - - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); - - /* Possibly retry shutdown until timeout or failure */ - ssl_err = SSL_get_error(self->ssl, err); - if (ssl_err == SSL_ERROR_WANT_READ) - sockstate = PySSL_select(sock, 0, timeout); - else if (ssl_err == SSL_ERROR_WANT_WRITE) - sockstate = PySSL_select(sock, 1, timeout); - else - break; - - if (sockstate == SOCKET_HAS_TIMED_OUT) { - if (ssl_err == SSL_ERROR_WANT_READ) - PyErr_SetString(PySocketModule.timeout_error, - "The read operation timed out"); - else - PyErr_SetString(PySocketModule.timeout_error, - "The write operation timed out"); - goto error; - } - else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); - goto error; - } - else if (sockstate != SOCKET_OPERATION_OK) - /* Retain the SSL error code */ - break; - } - - if (err < 0) { - Py_XDECREF(sock); - return PySSL_SetError(self, err, __FILE__, __LINE__); - } - if (sock) - /* It's already INCREF'ed */ - return (PyObject *) sock; - else - Py_RETURN_NONE; - -error: - Py_XDECREF(sock); - return NULL; -} - -PyDoc_STRVAR(PySSL_SSLshutdown_doc, -"shutdown(s) -> socket\n\ -\n\ -Does the SSL shutdown handshake with the remote end, and returns\n\ -the underlying socket object."); - -static PyObject * -PySSL_tls_unique_cb(PySSLSocket *self) -{ - 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); - } - else { - /* if a new session XOR we are the server */ - len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); - } - - /* 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; -} - -PyDoc_STRVAR(PySSL_tls_unique_cb_doc, -"tls_unique_cb() -> bytes\n\ -\n\ -Returns the 'tls-unique' channel binding data, as defined by RFC 5929.\n\ -\n\ -If the TLS handshake is not yet complete, None is returned"); - -static PyGetSetDef ssl_getsetlist[] = { - {"context", (getter) PySSL_get_context, - (setter) PySSL_set_context, PySSL_set_context_doc}, - {"server_side", (getter) PySSL_get_server_side, NULL, - PySSL_get_server_side_doc}, - {"server_hostname", (getter) PySSL_get_server_hostname, NULL, - PySSL_get_server_hostname_doc}, - {"owner", (getter) PySSL_get_owner, (setter) PySSL_set_owner, - PySSL_get_owner_doc}, - {NULL}, /* sentinel */ -}; - -static PyMethodDef PySSLMethods[] = { - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, - PySSL_SSLwrite_doc}, - {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, - PySSL_SSLread_doc}, - {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, - PySSL_SSLpending_doc}, - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, - {"shared_ciphers", (PyCFunction)PySSL_shared_ciphers, METH_NOARGS}, - {"version", (PyCFunction)PySSL_version, METH_NOARGS}, -#ifdef OPENSSL_NPN_NEGOTIATED - {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, -#endif -#ifdef HAVE_ALPN - {"selected_alpn_protocol", (PyCFunction)PySSL_selected_alpn_protocol, METH_NOARGS}, -#endif - {"compression", (PyCFunction)PySSL_compression, METH_NOARGS}, - {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, - PySSL_SSLshutdown_doc}, - {"tls_unique_cb", (PyCFunction)PySSL_tls_unique_cb, METH_NOARGS, - PySSL_tls_unique_cb_doc}, - {NULL, NULL} -}; - -static PyTypeObject PySSLSocket_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl._SSLSocket", /*tp_name*/ - sizeof(PySSLSocket), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PySSL_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*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PySSLMethods, /*tp_methods*/ - 0, /*tp_members*/ - ssl_getsetlist, /*tp_getset*/ -}; - - -/* - * _SSLContext objects - */ - -static PyObject * -context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"protocol", NULL}; - PySSLContext *self; - int proto_version = PY_SSL_VERSION_SSL23; - long options; - SSL_CTX *ctx = NULL; - - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "i:_SSLContext", kwlist, - &proto_version)) - return NULL; - - PySSL_BEGIN_ALLOW_THREADS - if (proto_version == PY_SSL_VERSION_TLS1) - ctx = SSL_CTX_new(TLSv1_method()); -#if HAVE_TLSv1_2 - else if (proto_version == PY_SSL_VERSION_TLS1_1) - ctx = SSL_CTX_new(TLSv1_1_method()); - else if (proto_version == PY_SSL_VERSION_TLS1_2) - ctx = SSL_CTX_new(TLSv1_2_method()); -#endif -#ifndef OPENSSL_NO_SSL3 - else if (proto_version == PY_SSL_VERSION_SSL3) - ctx = SSL_CTX_new(SSLv3_method()); -#endif -#ifndef OPENSSL_NO_SSL2 - else if (proto_version == PY_SSL_VERSION_SSL2) - ctx = SSL_CTX_new(SSLv2_method()); -#endif - else if (proto_version == PY_SSL_VERSION_SSL23) - ctx = SSL_CTX_new(SSLv23_method()); - else - proto_version = -1; - PySSL_END_ALLOW_THREADS - - if (proto_version == -1) { - PyErr_SetString(PyExc_ValueError, - "invalid protocol version"); - return NULL; - } - if (ctx == NULL) { - PyErr_SetString(PySSLErrorObject, - "failed to allocate SSL context"); - return NULL; - } - - assert(type != NULL && type->tp_alloc != NULL); - self = (PySSLContext *) type->tp_alloc(type, 0); - if (self == NULL) { - SSL_CTX_free(ctx); - return NULL; - } - self->ctx = ctx; -#ifdef OPENSSL_NPN_NEGOTIATED - self->npn_protocols = NULL; -#endif -#ifdef HAVE_ALPN - self->alpn_protocols = NULL; -#endif -#ifndef OPENSSL_NO_TLSEXT - self->set_hostname = NULL; -#endif - /* Don't check host name by default */ - self->check_hostname = 0; - /* Defaults */ - SSL_CTX_set_verify(self->ctx, SSL_VERIFY_NONE, NULL); - options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; - if (proto_version != PY_SSL_VERSION_SSL2) - options |= SSL_OP_NO_SSLv2; - SSL_CTX_set_options(self->ctx, options); - -#ifndef OPENSSL_NO_ECDH - /* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use - prime256v1 by default. This is Apache mod_ssl's initialization - policy, so we should be safe. */ -#if defined(SSL_CTX_set_ecdh_auto) - SSL_CTX_set_ecdh_auto(self->ctx, 1); -#else - { - EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - SSL_CTX_set_tmp_ecdh(self->ctx, key); - EC_KEY_free(key); - } -#endif -#endif - -#define SID_CTX "Python" - SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX, - sizeof(SID_CTX)); -#undef SID_CTX - -#ifdef X509_V_FLAG_TRUSTED_FIRST - { - /* Improve trust chain building when cross-signed intermediate - certificates are present. See https://bugs.python.org/issue23476. */ - X509_STORE *store = SSL_CTX_get_cert_store(self->ctx); - X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); - } -#endif - - return (PyObject *)self; -} - -static int -context_traverse(PySSLContext *self, visitproc visit, void *arg) -{ -#ifndef OPENSSL_NO_TLSEXT - Py_VISIT(self->set_hostname); -#endif - return 0; -} - -static int -context_clear(PySSLContext *self) -{ -#ifndef OPENSSL_NO_TLSEXT - Py_CLEAR(self->set_hostname); -#endif - return 0; -} - -static void -context_dealloc(PySSLContext *self) -{ - context_clear(self); - SSL_CTX_free(self->ctx); -#ifdef OPENSSL_NPN_NEGOTIATED - PyMem_FREE(self->npn_protocols); -#endif -#ifdef HAVE_ALPN - PyMem_FREE(self->alpn_protocols); -#endif - Py_TYPE(self)->tp_free(self); -} - -static PyObject * -set_ciphers(PySSLContext *self, PyObject *args) -{ - int ret; - const char *cipherlist; - - if (!PyArg_ParseTuple(args, "s:set_ciphers", &cipherlist)) - return NULL; - ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist); - if (ret == 0) { - /* Clearing the error queue is necessary on some OpenSSL versions, - otherwise the error will be reported again when another SSL call - is done. */ - ERR_clear_error(); - PyErr_SetString(PySSLErrorObject, - "No cipher can be selected."); - return NULL; - } - Py_RETURN_NONE; -} - -#ifdef OPENSSL_NPN_NEGOTIATED -static int -do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, - const unsigned char *server_protocols, unsigned int server_protocols_len, - const unsigned char *client_protocols, unsigned int client_protocols_len) -{ - int ret; - if (client_protocols == NULL) { - client_protocols = (unsigned char *)""; - client_protocols_len = 0; - } - if (server_protocols == NULL) { - server_protocols = (unsigned char *)""; - server_protocols_len = 0; - } - - ret = SSL_select_next_proto(out, outlen, - server_protocols, server_protocols_len, - client_protocols, client_protocols_len); - if (alpn && ret != OPENSSL_NPN_NEGOTIATED) - return SSL_TLSEXT_ERR_NOACK; - - return SSL_TLSEXT_ERR_OK; -} - -/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ -static int -_advertiseNPN_cb(SSL *s, - const unsigned char **data, unsigned int *len, - void *args) -{ - PySSLContext *ssl_ctx = (PySSLContext *) args; - - if (ssl_ctx->npn_protocols == NULL) { - *data = (unsigned char *)""; - *len = 0; - } else { - *data = ssl_ctx->npn_protocols; - *len = ssl_ctx->npn_protocols_len; - } - - return SSL_TLSEXT_ERR_OK; -} -/* this callback gets passed to SSL_CTX_set_next_proto_select_cb */ -static int -_selectNPN_cb(SSL *s, - unsigned char **out, unsigned char *outlen, - const unsigned char *server, unsigned int server_len, - void *args) -{ - PySSLContext *ctx = (PySSLContext *)args; - return do_protocol_selection(0, out, outlen, server, server_len, - ctx->npn_protocols, ctx->npn_protocols_len); -} -#endif - -static PyObject * -_set_npn_protocols(PySSLContext *self, PyObject *args) -{ -#ifdef OPENSSL_NPN_NEGOTIATED - Py_buffer protos; - - if (!PyArg_ParseTuple(args, "y*:set_npn_protocols", &protos)) - return NULL; - - if (self->npn_protocols != NULL) { - PyMem_Free(self->npn_protocols); - } - - self->npn_protocols = PyMem_Malloc(protos.len); - if (self->npn_protocols == NULL) { - PyBuffer_Release(&protos); - return PyErr_NoMemory(); - } - memcpy(self->npn_protocols, protos.buf, protos.len); - self->npn_protocols_len = (int) protos.len; - - /* set both server and client callbacks, because the context can - * be used to create both types of sockets */ - SSL_CTX_set_next_protos_advertised_cb(self->ctx, - _advertiseNPN_cb, - self); - SSL_CTX_set_next_proto_select_cb(self->ctx, - _selectNPN_cb, - self); - - PyBuffer_Release(&protos); - Py_RETURN_NONE; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The NPN extension requires OpenSSL 1.0.1 or later."); - return NULL; -#endif -} - -#ifdef HAVE_ALPN -static int -_selectALPN_cb(SSL *s, - const unsigned char **out, unsigned char *outlen, - const unsigned char *client_protocols, unsigned int client_protocols_len, - void *args) -{ - PySSLContext *ctx = (PySSLContext *)args; - return do_protocol_selection(1, (unsigned char **)out, outlen, - ctx->alpn_protocols, ctx->alpn_protocols_len, - client_protocols, client_protocols_len); -} -#endif - -static PyObject * -_set_alpn_protocols(PySSLContext *self, PyObject *args) -{ -#ifdef HAVE_ALPN - Py_buffer protos; - - if (!PyArg_ParseTuple(args, "y*:set_npn_protocols", &protos)) - return NULL; - - PyMem_FREE(self->alpn_protocols); - self->alpn_protocols = PyMem_Malloc(protos.len); - if (!self->alpn_protocols) - return PyErr_NoMemory(); - memcpy(self->alpn_protocols, protos.buf, protos.len); - self->alpn_protocols_len = protos.len; - PyBuffer_Release(&protos); - - if (SSL_CTX_set_alpn_protos(self->ctx, self->alpn_protocols, self->alpn_protocols_len)) - return PyErr_NoMemory(); - SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self); - - PyBuffer_Release(&protos); - Py_RETURN_NONE; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The ALPN extension requires OpenSSL 1.0.2 or later."); - return NULL; -#endif -} - -static PyObject * -get_verify_mode(PySSLContext *self, void *c) -{ - switch (SSL_CTX_get_verify_mode(self->ctx)) { - case SSL_VERIFY_NONE: - return PyLong_FromLong(PY_SSL_CERT_NONE); - case SSL_VERIFY_PEER: - return PyLong_FromLong(PY_SSL_CERT_OPTIONAL); - case SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT: - return PyLong_FromLong(PY_SSL_CERT_REQUIRED); - } - PyErr_SetString(PySSLErrorObject, - "invalid return value from SSL_CTX_get_verify_mode"); - return NULL; -} - -static int -set_verify_mode(PySSLContext *self, PyObject *arg, void *c) -{ - int n, mode; - if (!PyArg_Parse(arg, "i", &n)) - return -1; - if (n == PY_SSL_CERT_NONE) - mode = SSL_VERIFY_NONE; - else if (n == PY_SSL_CERT_OPTIONAL) - mode = SSL_VERIFY_PEER; - else if (n == PY_SSL_CERT_REQUIRED) - mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - else { - PyErr_SetString(PyExc_ValueError, - "invalid value for verify_mode"); - return -1; - } - if (mode == SSL_VERIFY_NONE && self->check_hostname) { - PyErr_SetString(PyExc_ValueError, - "Cannot set verify_mode to CERT_NONE when " - "check_hostname is enabled."); - return -1; - } - SSL_CTX_set_verify(self->ctx, mode, NULL); - return 0; -} - -static PyObject * -get_verify_flags(PySSLContext *self, void *c) -{ - X509_STORE *store; - unsigned long flags; - - store = SSL_CTX_get_cert_store(self->ctx); - flags = X509_VERIFY_PARAM_get_flags(store->param); - return PyLong_FromUnsignedLong(flags); -} - -static int -set_verify_flags(PySSLContext *self, PyObject *arg, void *c) -{ - X509_STORE *store; - unsigned long new_flags, flags, set, clear; - - if (!PyArg_Parse(arg, "k", &new_flags)) - return -1; - store = SSL_CTX_get_cert_store(self->ctx); - flags = X509_VERIFY_PARAM_get_flags(store->param); - clear = flags & ~new_flags; - set = ~flags & new_flags; - if (clear) { - if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return -1; - } - } - if (set) { - if (!X509_VERIFY_PARAM_set_flags(store->param, set)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return -1; - } - } - return 0; -} - -static PyObject * -get_options(PySSLContext *self, void *c) -{ - return PyLong_FromLong(SSL_CTX_get_options(self->ctx)); -} - -static int -set_options(PySSLContext *self, PyObject *arg, void *c) -{ - long new_opts, opts, set, clear; - if (!PyArg_Parse(arg, "l", &new_opts)) - return -1; - opts = SSL_CTX_get_options(self->ctx); - clear = opts & ~new_opts; - set = ~opts & new_opts; - if (clear) { -#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS - SSL_CTX_clear_options(self->ctx, clear); -#else - PyErr_SetString(PyExc_ValueError, - "can't clear options before OpenSSL 0.9.8m"); - return -1; -#endif - } - if (set) - SSL_CTX_set_options(self->ctx, set); - return 0; -} - -static PyObject * -get_check_hostname(PySSLContext *self, void *c) -{ - return PyBool_FromLong(self->check_hostname); -} - -static int -set_check_hostname(PySSLContext *self, PyObject *arg, void *c) -{ - int check_hostname; - if (!PyArg_Parse(arg, "p", &check_hostname)) - return -1; - if (check_hostname && - SSL_CTX_get_verify_mode(self->ctx) == SSL_VERIFY_NONE) { - PyErr_SetString(PyExc_ValueError, - "check_hostname needs a SSL context with either " - "CERT_OPTIONAL or CERT_REQUIRED"); - return -1; - } - self->check_hostname = check_hostname; - return 0; -} - - -typedef struct { - PyThreadState *thread_state; - PyObject *callable; - char *password; - int size; - int error; -} _PySSLPasswordInfo; - -static int -_pwinfo_set(_PySSLPasswordInfo *pw_info, PyObject* password, - const char *bad_type_error) -{ - /* Set the password and size fields of a _PySSLPasswordInfo struct - from a unicode, bytes, or byte array object. - The password field will be dynamically allocated and must be freed - by the caller */ - PyObject *password_bytes = NULL; - const char *data = NULL; - Py_ssize_t size; - - if (PyUnicode_Check(password)) { - password_bytes = PyUnicode_AsEncodedString(password, NULL, NULL); - if (!password_bytes) { - goto error; - } - data = PyBytes_AS_STRING(password_bytes); - size = PyBytes_GET_SIZE(password_bytes); - } else if (PyBytes_Check(password)) { - data = PyBytes_AS_STRING(password); - size = PyBytes_GET_SIZE(password); - } else if (PyByteArray_Check(password)) { - data = PyByteArray_AS_STRING(password); - size = PyByteArray_GET_SIZE(password); - } else { - PyErr_SetString(PyExc_TypeError, bad_type_error); - goto error; - } - - if (size > (Py_ssize_t)INT_MAX) { - PyErr_Format(PyExc_ValueError, - "password cannot be longer than %d bytes", INT_MAX); - goto error; - } - - PyMem_Free(pw_info->password); - pw_info->password = PyMem_Malloc(size); - if (!pw_info->password) { - PyErr_SetString(PyExc_MemoryError, - "unable to allocate password buffer"); - goto error; - } - memcpy(pw_info->password, data, size); - pw_info->size = (int)size; - - Py_XDECREF(password_bytes); - return 1; - -error: - Py_XDECREF(password_bytes); - return 0; -} - -static int -_password_callback(char *buf, int size, int rwflag, void *userdata) -{ - _PySSLPasswordInfo *pw_info = (_PySSLPasswordInfo*) userdata; - PyObject *fn_ret = NULL; - - PySSL_END_ALLOW_THREADS_S(pw_info->thread_state); - - if (pw_info->callable) { - fn_ret = PyObject_CallFunctionObjArgs(pw_info->callable, NULL); - if (!fn_ret) { - /* TODO: It would be nice to move _ctypes_add_traceback() into the - core python API, so we could use it to add a frame here */ - goto error; - } - - if (!_pwinfo_set(pw_info, fn_ret, - "password callback must return a string")) { - goto error; - } - Py_CLEAR(fn_ret); - } - - if (pw_info->size > size) { - PyErr_Format(PyExc_ValueError, - "password cannot be longer than %d bytes", size); - goto error; - } - - PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); - memcpy(buf, pw_info->password, pw_info->size); - return pw_info->size; - -error: - Py_XDECREF(fn_ret); - PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); - pw_info->error = 1; - return -1; -} - -static PyObject * -load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"certfile", "keyfile", "password", NULL}; - PyObject *certfile, *keyfile = NULL, *password = NULL; - PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL; - pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; - void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; - _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 }; - int r; - - errno = 0; - ERR_clear_error(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|OO:load_cert_chain", kwlist, - &certfile, &keyfile, &password)) - return NULL; - if (keyfile == Py_None) - keyfile = NULL; - if (!PyUnicode_FSConverter(certfile, &certfile_bytes)) { - PyErr_SetString(PyExc_TypeError, - "certfile should be a valid filesystem path"); - return NULL; - } - if (keyfile && !PyUnicode_FSConverter(keyfile, &keyfile_bytes)) { - PyErr_SetString(PyExc_TypeError, - "keyfile should be a valid filesystem path"); - goto error; - } - if (password && password != Py_None) { - if (PyCallable_Check(password)) { - pw_info.callable = password; - } else if (!_pwinfo_set(&pw_info, password, - "password should be a string or callable")) { - goto error; - } - SSL_CTX_set_default_passwd_cb(self->ctx, _password_callback); - SSL_CTX_set_default_passwd_cb_userdata(self->ctx, &pw_info); - } - PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); - r = SSL_CTX_use_certificate_chain_file(self->ctx, - PyBytes_AS_STRING(certfile_bytes)); - PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); - if (r != 1) { - if (pw_info.error) { - ERR_clear_error(); - /* the password callback has already set the error information */ - } - else if (errno != 0) { - ERR_clear_error(); - PyErr_SetFromErrno(PyExc_IOError); - } - else { - _setSSLError(NULL, 0, __FILE__, __LINE__); - } - goto error; - } - PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); - r = SSL_CTX_use_PrivateKey_file(self->ctx, - PyBytes_AS_STRING(keyfile ? keyfile_bytes : certfile_bytes), - SSL_FILETYPE_PEM); - PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); - Py_CLEAR(keyfile_bytes); - Py_CLEAR(certfile_bytes); - if (r != 1) { - if (pw_info.error) { - ERR_clear_error(); - /* the password callback has already set the error information */ - } - else if (errno != 0) { - ERR_clear_error(); - PyErr_SetFromErrno(PyExc_IOError); - } - else { - _setSSLError(NULL, 0, __FILE__, __LINE__); - } - goto error; - } - PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); - r = SSL_CTX_check_private_key(self->ctx); - PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); - if (r != 1) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto error; - } - SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); - PyMem_Free(pw_info.password); - Py_RETURN_NONE; - -error: - SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); - PyMem_Free(pw_info.password); - Py_XDECREF(keyfile_bytes); - Py_XDECREF(certfile_bytes); - return NULL; -} - -/* internal helper function, returns -1 on error - */ -static int -_add_ca_certs(PySSLContext *self, void *data, Py_ssize_t len, - int filetype) -{ - BIO *biobuf = NULL; - X509_STORE *store; - int retval = 0, err, loaded = 0; - - assert(filetype == SSL_FILETYPE_ASN1 || filetype == SSL_FILETYPE_PEM); - - if (len <= 0) { - PyErr_SetString(PyExc_ValueError, - "Empty certificate data"); - return -1; - } else if (len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "Certificate data is too long."); - return -1; - } - - biobuf = BIO_new_mem_buf(data, (int)len); - if (biobuf == NULL) { - _setSSLError("Can't allocate buffer", 0, __FILE__, __LINE__); - return -1; - } - - store = SSL_CTX_get_cert_store(self->ctx); - assert(store != NULL); - - while (1) { - X509 *cert = NULL; - int r; - - if (filetype == SSL_FILETYPE_ASN1) { - cert = d2i_X509_bio(biobuf, NULL); - } else { - cert = PEM_read_bio_X509(biobuf, NULL, - self->ctx->default_passwd_callback, - self->ctx->default_passwd_callback_userdata); - } - if (cert == NULL) { - break; - } - r = X509_STORE_add_cert(store, cert); - X509_free(cert); - if (!r) { - err = ERR_peek_last_error(); - if ((ERR_GET_LIB(err) == ERR_LIB_X509) && - (ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) { - /* cert already in hash table, not an error */ - ERR_clear_error(); - } else { - break; - } - } - loaded++; - } - - err = ERR_peek_last_error(); - if ((filetype == SSL_FILETYPE_ASN1) && - (loaded > 0) && - (ERR_GET_LIB(err) == ERR_LIB_ASN1) && - (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) { - /* EOF ASN1 file, not an error */ - ERR_clear_error(); - retval = 0; - } else if ((filetype == SSL_FILETYPE_PEM) && - (loaded > 0) && - (ERR_GET_LIB(err) == ERR_LIB_PEM) && - (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { - /* EOF PEM file, not an error */ - ERR_clear_error(); - retval = 0; - } else { - _setSSLError(NULL, 0, __FILE__, __LINE__); - retval = -1; - } - - BIO_free(biobuf); - return retval; -} - - -static PyObject * -load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"cafile", "capath", "cadata", NULL}; - PyObject *cafile = NULL, *capath = NULL, *cadata = NULL; - PyObject *cafile_bytes = NULL, *capath_bytes = NULL; - const char *cafile_buf = NULL, *capath_buf = NULL; - int r = 0, ok = 1; - - errno = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "|OOO:load_verify_locations", kwlist, - &cafile, &capath, &cadata)) - return NULL; - - if (cafile == Py_None) - cafile = NULL; - if (capath == Py_None) - capath = NULL; - if (cadata == Py_None) - cadata = NULL; - - if (cafile == NULL && capath == NULL && cadata == NULL) { - PyErr_SetString(PyExc_TypeError, - "cafile, capath and cadata cannot be all omitted"); - goto error; - } - if (cafile && !PyUnicode_FSConverter(cafile, &cafile_bytes)) { - PyErr_SetString(PyExc_TypeError, - "cafile should be a valid filesystem path"); - goto error; - } - if (capath && !PyUnicode_FSConverter(capath, &capath_bytes)) { - PyErr_SetString(PyExc_TypeError, - "capath should be a valid filesystem path"); - goto error; - } - - /* validata cadata type and load cadata */ - if (cadata) { - Py_buffer buf; - PyObject *cadata_ascii = NULL; - - if (PyObject_GetBuffer(cadata, &buf, PyBUF_SIMPLE) == 0) { - if (!PyBuffer_IsContiguous(&buf, 'C') || buf.ndim > 1) { - PyBuffer_Release(&buf); - PyErr_SetString(PyExc_TypeError, - "cadata should be a contiguous buffer with " - "a single dimension"); - goto error; - } - r = _add_ca_certs(self, buf.buf, buf.len, SSL_FILETYPE_ASN1); - PyBuffer_Release(&buf); - if (r == -1) { - goto error; - } - } else { - PyErr_Clear(); - cadata_ascii = PyUnicode_AsASCIIString(cadata); - if (cadata_ascii == NULL) { - PyErr_SetString(PyExc_TypeError, - "cadata should be a ASCII string or a " - "bytes-like object"); - goto error; - } - r = _add_ca_certs(self, - PyBytes_AS_STRING(cadata_ascii), - PyBytes_GET_SIZE(cadata_ascii), - SSL_FILETYPE_PEM); - Py_DECREF(cadata_ascii); - if (r == -1) { - goto error; - } - } - } - - /* load cafile or capath */ - if (cafile || capath) { - if (cafile) - cafile_buf = PyBytes_AS_STRING(cafile_bytes); - if (capath) - capath_buf = PyBytes_AS_STRING(capath_bytes); - PySSL_BEGIN_ALLOW_THREADS - r = SSL_CTX_load_verify_locations(self->ctx, cafile_buf, capath_buf); - PySSL_END_ALLOW_THREADS - if (r != 1) { - ok = 0; - if (errno != 0) { - ERR_clear_error(); - PyErr_SetFromErrno(PyExc_IOError); - } - else { - _setSSLError(NULL, 0, __FILE__, __LINE__); - } - goto error; - } - } - goto end; - - error: - ok = 0; - end: - Py_XDECREF(cafile_bytes); - Py_XDECREF(capath_bytes); - if (ok) { - Py_RETURN_NONE; - } else { - return NULL; - } -} - -static PyObject * -load_dh_params(PySSLContext *self, PyObject *filepath) -{ - FILE *f; - DH *dh; - - f = _Py_fopen_obj(filepath, "rb"); - if (f == NULL) - return NULL; - - errno = 0; - PySSL_BEGIN_ALLOW_THREADS - dh = PEM_read_DHparams(f, NULL, NULL, NULL); - fclose(f); - PySSL_END_ALLOW_THREADS - if (dh == NULL) { - if (errno != 0) { - ERR_clear_error(); - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath); - } - else { - _setSSLError(NULL, 0, __FILE__, __LINE__); - } - return NULL; - } - if (SSL_CTX_set_tmp_dh(self->ctx, dh) == 0) - _setSSLError(NULL, 0, __FILE__, __LINE__); - DH_free(dh); - Py_RETURN_NONE; -} - -static PyObject * -context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"sock", "server_side", "server_hostname", NULL}; - PySocketSockObject *sock; - int server_side = 0; - char *hostname = NULL; - PyObject *hostname_obj, *res; - - /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i|O!:_wrap_socket", kwlist, - PySocketModule.Sock_Type, - &sock, &server_side, - Py_TYPE(Py_None), &hostname_obj)) { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!iet:_wrap_socket", kwlist, - PySocketModule.Sock_Type, - &sock, &server_side, - "idna", &hostname)) - return NULL; - } - - res = (PyObject *) newPySSLSocket(self, sock, server_side, hostname, - NULL, NULL); - if (hostname != NULL) - PyMem_Free(hostname); - return res; -} - -static PyObject * -context_wrap_bio(PySSLContext *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"incoming", "outgoing", "server_side", - "server_hostname", NULL}; - int server_side; - char *hostname = NULL; - PyObject *hostname_obj = Py_None, *res; - PySSLMemoryBIO *incoming, *outgoing; - - /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!i|O:_wrap_bio", kwlist, - &PySSLMemoryBIO_Type, &incoming, - &PySSLMemoryBIO_Type, &outgoing, - &server_side, &hostname_obj)) - return NULL; - if (hostname_obj != Py_None) { - if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) - return NULL; - } - - res = (PyObject *) newPySSLSocket(self, NULL, server_side, hostname, - incoming, outgoing); - - PyMem_Free(hostname); - return res; -} - -static PyObject * -session_stats(PySSLContext *self, PyObject *unused) -{ - int r; - PyObject *value, *stats = PyDict_New(); - if (!stats) - return NULL; - -#define ADD_STATS(SSL_NAME, KEY_NAME) \ - value = PyLong_FromLong(SSL_CTX_sess_ ## SSL_NAME (self->ctx)); \ - if (value == NULL) \ - goto error; \ - r = PyDict_SetItemString(stats, KEY_NAME, value); \ - Py_DECREF(value); \ - if (r < 0) \ - goto error; - - ADD_STATS(number, "number"); - ADD_STATS(connect, "connect"); - ADD_STATS(connect_good, "connect_good"); - ADD_STATS(connect_renegotiate, "connect_renegotiate"); - ADD_STATS(accept, "accept"); - ADD_STATS(accept_good, "accept_good"); - ADD_STATS(accept_renegotiate, "accept_renegotiate"); - ADD_STATS(accept, "accept"); - ADD_STATS(hits, "hits"); - ADD_STATS(misses, "misses"); - ADD_STATS(timeouts, "timeouts"); - ADD_STATS(cache_full, "cache_full"); - -#undef ADD_STATS - - return stats; - -error: - Py_DECREF(stats); - return NULL; -} - -static PyObject * -set_default_verify_paths(PySSLContext *self, PyObject *unused) -{ - if (!SSL_CTX_set_default_verify_paths(self->ctx)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return NULL; - } - Py_RETURN_NONE; -} - -#ifndef OPENSSL_NO_ECDH -static PyObject * -set_ecdh_curve(PySSLContext *self, PyObject *name) -{ - PyObject *name_bytes; - int nid; - EC_KEY *key; - - if (!PyUnicode_FSConverter(name, &name_bytes)) - return NULL; - assert(PyBytes_Check(name_bytes)); - nid = OBJ_sn2nid(PyBytes_AS_STRING(name_bytes)); - Py_DECREF(name_bytes); - if (nid == 0) { - PyErr_Format(PyExc_ValueError, - "unknown elliptic curve name %R", name); - return NULL; - } - key = EC_KEY_new_by_curve_name(nid); - if (key == NULL) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return NULL; - } - SSL_CTX_set_tmp_ecdh(self->ctx, key); - EC_KEY_free(key); - Py_RETURN_NONE; -} -#endif - -#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) -static int -_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); -#ifdef WITH_THREAD - PyGILState_STATE gstate = PyGILState_Ensure(); -#endif - - if (ssl_ctx->set_hostname == NULL) { - /* remove race condition in this the call back while if removing the - * callback is in progress */ -#ifdef WITH_THREAD - PyGILState_Release(gstate); -#endif - return SSL_TLSEXT_ERR_OK; - } - - ssl = SSL_get_app_data(s); - assert(PySSLSocket_Check(ssl)); - - /* The servername callback expects a argument that represents the current - * SSL connection and that has a .context attribute that can be changed to - * identify the requested hostname. Since the official API is the Python - * level API we want to pass the callback a Python level object rather than - * a _ssl.SSLSocket instance. If there's an "owner" (typically an - * SSLObject) that will be passed. Otherwise if there's a socket then that - * will be passed. If both do not exist only then the C-level object is - * passed. */ - if (ssl->owner) - ssl_socket = PyWeakref_GetObject(ssl->owner); - else if (ssl->Socket) - ssl_socket = PyWeakref_GetObject(ssl->Socket); - else - ssl_socket = (PyObject *) ssl; - - Py_INCREF(ssl_socket); - if (ssl_socket == Py_None) - goto error; - - if (servername == NULL) { - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, - Py_None, ssl_ctx, NULL); - } - else { - servername_o = PyBytes_FromString(servername); - if (servername_o == 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); - goto error; - } - Py_DECREF(servername_o); - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, - servername_idna, ssl_ctx, NULL); - Py_DECREF(servername_idna); - } - Py_DECREF(ssl_socket); - - if (result == NULL) { - PyErr_WriteUnraisable(ssl_ctx->set_hostname); - *al = SSL_AD_HANDSHAKE_FAILURE; - ret = SSL_TLSEXT_ERR_ALERT_FATAL; - } - else { - if (result != Py_None) { - *al = (int) PyLong_AsLong(result); - if (PyErr_Occurred()) { - PyErr_WriteUnraisable(result); - *al = SSL_AD_INTERNAL_ERROR; - } - ret = SSL_TLSEXT_ERR_ALERT_FATAL; - } - else { - ret = SSL_TLSEXT_ERR_OK; - } - Py_DECREF(result); - } - -#ifdef WITH_THREAD - PyGILState_Release(gstate); -#endif - return ret; - -error: - Py_DECREF(ssl_socket); - *al = SSL_AD_INTERNAL_ERROR; - ret = SSL_TLSEXT_ERR_ALERT_FATAL; -#ifdef WITH_THREAD - PyGILState_Release(gstate); -#endif - return ret; -} -#endif - -PyDoc_STRVAR(PySSL_set_servername_callback_doc, -"set_servername_callback(method)\n\ -\n\ -This sets a callback that will be called when a server name is provided by\n\ -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."); - -static PyObject * -set_servername_callback(PySSLContext *self, PyObject *args) -{ -#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) - PyObject *cb; - - if (!PyArg_ParseTuple(args, "O", &cb)) - return NULL; - - Py_CLEAR(self->set_hostname); - if (cb == Py_None) { - SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); - } - else { - if (!PyCallable_Check(cb)) { - SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); - PyErr_SetString(PyExc_TypeError, - "not a callable object"); - return NULL; - } - Py_INCREF(cb); - self->set_hostname = cb; - SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); - SSL_CTX_set_tlsext_servername_arg(self->ctx, self); - } - Py_RETURN_NONE; -#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; -#endif -} - -PyDoc_STRVAR(PySSL_get_stats_doc, -"cert_store_stats() -> {'crl': int, 'x509_ca': int, 'x509': int}\n\ -\n\ -Returns quantities of loaded X.509 certificates. X.509 certificates with a\n\ -CA extension and certificate revocation lists inside the context's cert\n\ -store.\n\ -NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -been used at least once."); - -static PyObject * -cert_store_stats(PySSLContext *self) -{ - X509_STORE *store; - X509_OBJECT *obj; - int x509 = 0, crl = 0, pkey = 0, ca = 0, i; - - store = SSL_CTX_get_cert_store(self->ctx); - for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { - obj = sk_X509_OBJECT_value(store->objs, i); - switch (obj->type) { - case X509_LU_X509: - x509++; - if (X509_check_ca(obj->data.x509)) { - ca++; - } - break; - case X509_LU_CRL: - crl++; - break; - case X509_LU_PKEY: - pkey++; - break; - default: - /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY. - * As far as I can tell they are internal states and never - * stored in a cert store */ - break; - } - } - return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl, - "x509_ca", ca); -} - -PyDoc_STRVAR(PySSL_get_ca_certs_doc, -"get_ca_certs(binary_form=False) -> list of loaded certificate\n\ -\n\ -Returns a list of dicts with information of loaded CA certs. If the\n\ -optional argument is True, returns a DER-encoded copy of the CA certificate.\n\ -NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -been used at least once."); - -static PyObject * -get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"binary_form", NULL}; - X509_STORE *store; - PyObject *ci = NULL, *rlist = NULL; - int i; - int binary_mode = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|p:get_ca_certs", - kwlist, &binary_mode)) { - return NULL; - } - - if ((rlist = PyList_New(0)) == NULL) { - return NULL; - } - - store = SSL_CTX_get_cert_store(self->ctx); - for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { - X509_OBJECT *obj; - X509 *cert; - - obj = sk_X509_OBJECT_value(store->objs, i); - if (obj->type != X509_LU_X509) { - /* not a x509 cert */ - continue; - } - /* CA for any purpose */ - cert = obj->data.x509; - if (!X509_check_ca(cert)) { - continue; - } - if (binary_mode) { - ci = _certificate_to_der(cert); - } else { - ci = _decode_certificate(cert); - } - if (ci == NULL) { - goto error; - } - if (PyList_Append(rlist, ci) == -1) { - goto error; - } - Py_CLEAR(ci); - } - return rlist; - - error: - Py_XDECREF(ci); - Py_XDECREF(rlist); - return NULL; -} - - -static PyGetSetDef context_getsetlist[] = { - {"check_hostname", (getter) get_check_hostname, - (setter) set_check_hostname, NULL}, - {"options", (getter) get_options, - (setter) set_options, NULL}, - {"verify_flags", (getter) get_verify_flags, - (setter) set_verify_flags, NULL}, - {"verify_mode", (getter) get_verify_mode, - (setter) set_verify_mode, NULL}, - {NULL}, /* sentinel */ -}; - -static struct PyMethodDef context_methods[] = { - {"_wrap_socket", (PyCFunction) context_wrap_socket, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"_wrap_bio", (PyCFunction) context_wrap_bio, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"set_ciphers", (PyCFunction) set_ciphers, - METH_VARARGS, NULL}, - {"_set_alpn_protocols", (PyCFunction) _set_alpn_protocols, - METH_VARARGS, NULL}, - {"_set_npn_protocols", (PyCFunction) _set_npn_protocols, - METH_VARARGS, NULL}, - {"load_cert_chain", (PyCFunction) load_cert_chain, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"load_dh_params", (PyCFunction) load_dh_params, - METH_O, NULL}, - {"load_verify_locations", (PyCFunction) load_verify_locations, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"session_stats", (PyCFunction) session_stats, - METH_NOARGS, NULL}, - {"set_default_verify_paths", (PyCFunction) set_default_verify_paths, - METH_NOARGS, NULL}, -#ifndef OPENSSL_NO_ECDH - {"set_ecdh_curve", (PyCFunction) set_ecdh_curve, - METH_O, NULL}, -#endif - {"set_servername_callback", (PyCFunction) set_servername_callback, - METH_VARARGS, PySSL_set_servername_callback_doc}, - {"cert_store_stats", (PyCFunction) cert_store_stats, - METH_NOARGS, PySSL_get_stats_doc}, - {"get_ca_certs", (PyCFunction) get_ca_certs, - METH_VARARGS | METH_KEYWORDS, PySSL_get_ca_certs_doc}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject PySSLContext_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl._SSLContext", /*tp_name*/ - sizeof(PySSLContext), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)context_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*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc) context_traverse, /*tp_traverse*/ - (inquiry) context_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - context_methods, /*tp_methods*/ - 0, /*tp_members*/ - context_getsetlist, /*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*/ - context_new, /*tp_new*/ -}; - - -/* - * MemoryBIO objects - */ - -static PyObject * -memory_bio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {NULL}; - BIO *bio; - PySSLMemoryBIO *self; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, ":MemoryBIO", kwlist)) - return NULL; - - bio = BIO_new(BIO_s_mem()); - if (bio == NULL) { - PyErr_SetString(PySSLErrorObject, - "failed to allocate BIO"); - return NULL; - } - /* Since our BIO is non-blocking an empty read() does not indicate EOF, - * just that no data is currently available. The SSL routines should retry - * the read, which we can achieve by calling BIO_set_retry_read(). */ - BIO_set_retry_read(bio); - BIO_set_mem_eof_return(bio, -1); - - assert(type != NULL && type->tp_alloc != NULL); - self = (PySSLMemoryBIO *) type->tp_alloc(type, 0); - if (self == NULL) { - BIO_free(bio); - return NULL; - } - self->bio = bio; - self->eof_written = 0; - - return (PyObject *) self; -} - -static void -memory_bio_dealloc(PySSLMemoryBIO *self) -{ - BIO_free(self->bio); - Py_TYPE(self)->tp_free(self); -} - -static PyObject * -memory_bio_get_pending(PySSLMemoryBIO *self, void *c) -{ - return PyLong_FromLong(BIO_ctrl_pending(self->bio)); -} - -PyDoc_STRVAR(PySSL_memory_bio_pending_doc, -"The number of bytes pending in the memory BIO."); - -static PyObject * -memory_bio_get_eof(PySSLMemoryBIO *self, void *c) -{ - return PyBool_FromLong((BIO_ctrl_pending(self->bio) == 0) - && self->eof_written); -} - -PyDoc_STRVAR(PySSL_memory_bio_eof_doc, -"Whether the memory BIO is at EOF."); - -static PyObject * -memory_bio_read(PySSLMemoryBIO *self, PyObject *args) -{ - int len = -1, avail, nbytes; - PyObject *result; - - if (!PyArg_ParseTuple(args, "|i:read", &len)) - return NULL; - - avail = BIO_ctrl_pending(self->bio); - if ((len < 0) || (len > avail)) - len = avail; - - result = PyBytes_FromStringAndSize(NULL, len); - if ((result == NULL) || (len == 0)) - return result; - - nbytes = BIO_read(self->bio, PyBytes_AS_STRING(result), len); - /* There should never be any short reads but check anyway. */ - if ((nbytes < len) && (_PyBytes_Resize(&result, len) < 0)) { - Py_DECREF(result); - return NULL; - } - - return result; -} - -PyDoc_STRVAR(PySSL_memory_bio_read_doc, -"read([len]) -> bytes\n\ -\n\ -Read up to len bytes from the memory BIO.\n\ -\n\ -If len is not specified, read the entire buffer.\n\ -If the return value is an empty bytes instance, this means either\n\ -EOF or that no data is available. Use the \"eof\" property to\n\ -distinguish between the two."); - -static PyObject * -memory_bio_write(PySSLMemoryBIO *self, PyObject *args) -{ - Py_buffer buf; - int nbytes; - - if (!PyArg_ParseTuple(args, "y*:write", &buf)) - return NULL; - - if (buf.len > INT_MAX) { - PyErr_Format(PyExc_OverflowError, - "string longer than %d bytes", INT_MAX); - goto error; - } - - if (self->eof_written) { - PyErr_SetString(PySSLErrorObject, - "cannot write() after write_eof()"); - goto error; - } - - nbytes = BIO_write(self->bio, buf.buf, buf.len); - if (nbytes < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto error; - } - - PyBuffer_Release(&buf); - return PyLong_FromLong(nbytes); - -error: - PyBuffer_Release(&buf); - return NULL; -} - -PyDoc_STRVAR(PySSL_memory_bio_write_doc, -"write(b) -> len\n\ -\n\ -Writes the bytes b into the memory BIO. Returns the number\n\ -of bytes written."); - -static PyObject * -memory_bio_write_eof(PySSLMemoryBIO *self, PyObject *args) -{ - self->eof_written = 1; - /* After an EOF is written, a zero return from read() should be a real EOF - * i.e. it should not be retried. Clear the SHOULD_RETRY flag. */ - BIO_clear_retry_flags(self->bio); - BIO_set_mem_eof_return(self->bio, 0); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(PySSL_memory_bio_write_eof_doc, -"write_eof()\n\ -\n\ -Write an EOF marker to the memory BIO.\n\ -When all data has been read, the \"eof\" property will be True."); - -static PyGetSetDef memory_bio_getsetlist[] = { - {"pending", (getter) memory_bio_get_pending, NULL, - PySSL_memory_bio_pending_doc}, - {"eof", (getter) memory_bio_get_eof, NULL, - PySSL_memory_bio_eof_doc}, - {NULL}, /* sentinel */ -}; - -static struct PyMethodDef memory_bio_methods[] = { - {"read", (PyCFunction) memory_bio_read, - METH_VARARGS, PySSL_memory_bio_read_doc}, - {"write", (PyCFunction) memory_bio_write, - METH_VARARGS, PySSL_memory_bio_write_doc}, - {"write_eof", (PyCFunction) memory_bio_write_eof, - METH_NOARGS, PySSL_memory_bio_write_eof_doc}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject PySSLMemoryBIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl.MemoryBIO", /*tp_name*/ - sizeof(PySSLMemoryBIO), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)memory_bio_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*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - memory_bio_methods, /*tp_methods*/ - 0, /*tp_members*/ - memory_bio_getsetlist, /*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*/ - memory_bio_new, /*tp_new*/ -}; - - -/* helper routines for seeding the SSL PRNG */ -static PyObject * -PySSL_RAND_add(PyObject *self, PyObject *args) -{ - Py_buffer view; - const char *buf; - Py_ssize_t len, written; - double entropy; - - if (!PyArg_ParseTuple(args, "s*d:RAND_add", &view, &entropy)) - return NULL; - buf = (const char *)view.buf; - len = view.len; - do { - written = Py_MIN(len, INT_MAX); - RAND_add(buf, (int)written, entropy); - buf += written; - len -= written; - } while (len); - PyBuffer_Release(&view); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(PySSL_RAND_add_doc, -"RAND_add(string, entropy)\n\ -\n\ -Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\ -bound on the entropy contained in string. See RFC 1750."); - -static PyObject * -PySSL_RAND(int len, int pseudo) -{ - int ok; - PyObject *bytes; - unsigned long err; - const char *errstr; - PyObject *v; - - if (len < 0) { - PyErr_SetString(PyExc_ValueError, "num must be positive"); - return NULL; - } - - bytes = PyBytes_FromStringAndSize(NULL, len); - if (bytes == NULL) - return NULL; - if (pseudo) { - ok = RAND_pseudo_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len); - if (ok == 0 || ok == 1) - return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False); - } - else { - ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len); - if (ok == 1) - return bytes; - } - Py_DECREF(bytes); - - err = ERR_get_error(); - errstr = ERR_reason_error_string(err); - v = Py_BuildValue("(ks)", err, errstr); - if (v != NULL) { - PyErr_SetObject(PySSLErrorObject, v); - Py_DECREF(v); - } - return NULL; -} - -static PyObject * -PySSL_RAND_bytes(PyObject *self, PyObject *args) -{ - int len; - if (!PyArg_ParseTuple(args, "i:RAND_bytes", &len)) - return NULL; - return PySSL_RAND(len, 0); -} - -PyDoc_STRVAR(PySSL_RAND_bytes_doc, -"RAND_bytes(n) -> bytes\n\ -\n\ -Generate n cryptographically strong pseudo-random bytes."); - -static PyObject * -PySSL_RAND_pseudo_bytes(PyObject *self, PyObject *args) -{ - int len; - if (!PyArg_ParseTuple(args, "i:RAND_pseudo_bytes", &len)) - return NULL; - return PySSL_RAND(len, 1); -} - -PyDoc_STRVAR(PySSL_RAND_pseudo_bytes_doc, -"RAND_pseudo_bytes(n) -> (bytes, is_cryptographic)\n\ -\n\ -Generate n pseudo-random bytes. is_cryptographic is True if the bytes\ -generated are cryptographically strong."); - -static PyObject * -PySSL_RAND_status(PyObject *self) -{ - return PyLong_FromLong(RAND_status()); -} - -PyDoc_STRVAR(PySSL_RAND_status_doc, -"RAND_status() -> 0 or 1\n\ -\n\ -Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\ -It is necessary to seed the PRNG with RAND_add() on some platforms before\n\ -using the ssl() function."); - -#ifdef HAVE_RAND_EGD -static PyObject * -PySSL_RAND_egd(PyObject *self, PyObject *args) -{ - PyObject *path; - int bytes; - - if (!PyArg_ParseTuple(args, "O&:RAND_egd", - PyUnicode_FSConverter, &path)) - return NULL; - - bytes = RAND_egd(PyBytes_AsString(path)); - Py_DECREF(path); - if (bytes == -1) { - PyErr_SetString(PySSLErrorObject, - "EGD connection failed or EGD did not return " - "enough data to seed the PRNG"); - return NULL; - } - return PyLong_FromLong(bytes); -} - -PyDoc_STRVAR(PySSL_RAND_egd_doc, -"RAND_egd(path) -> bytes\n\ -\n\ -Queries the entropy gather daemon (EGD) on the socket named by 'path'.\n\ -Returns number of bytes read. Raises SSLError if connection to EGD\n\ -fails or if it does not provide enough data to seed PRNG."); -#endif /* HAVE_RAND_EGD */ - - -PyDoc_STRVAR(PySSL_get_default_verify_paths_doc, -"get_default_verify_paths() -> tuple\n\ -\n\ -Return search paths and environment vars that are used by SSLContext's\n\ -set_default_verify_paths() to load default CAs. The values are\n\ -'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'."); - -static PyObject * -PySSL_get_default_verify_paths(PyObject *self) -{ - PyObject *ofile_env = NULL; - PyObject *ofile = NULL; - PyObject *odir_env = NULL; - PyObject *odir = NULL; - -#define convert(info, target) { \ - const char *tmp = (info); \ - target = NULL; \ - if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ - else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \ - target = PyBytes_FromString(tmp); } \ - if (!target) goto error; \ - } while(0) - - convert(X509_get_default_cert_file_env(), ofile_env); - convert(X509_get_default_cert_file(), ofile); - convert(X509_get_default_cert_dir_env(), odir_env); - convert(X509_get_default_cert_dir(), odir); -#undef convert - - return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); - - error: - Py_XDECREF(ofile_env); - Py_XDECREF(ofile); - Py_XDECREF(odir_env); - Py_XDECREF(odir); - return NULL; -} - -static PyObject* -asn1obj2py(ASN1_OBJECT *obj) -{ - int nid; - const char *ln, *sn; - char buf[100]; - Py_ssize_t buflen; - - nid = OBJ_obj2nid(obj); - if (nid == NID_undef) { - PyErr_Format(PyExc_ValueError, "Unknown object"); - return NULL; - } - sn = OBJ_nid2sn(nid); - ln = OBJ_nid2ln(nid); - buflen = OBJ_obj2txt(buf, sizeof(buf), obj, 1); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - return NULL; - } - if (buflen) { - return Py_BuildValue("isss#", nid, sn, ln, buf, buflen); - } else { - return Py_BuildValue("issO", nid, sn, ln, Py_None); - } -} - -PyDoc_STRVAR(PySSL_txt2obj_doc, -"txt2obj(txt, name=False) -> (nid, shortname, longname, oid)\n\ -\n\ -Lookup NID, short name, long name and OID of an ASN1_OBJECT. By default\n\ -objects are looked up by OID. With name=True short and long name are also\n\ -matched."); - -static PyObject* -PySSL_txt2obj(PyObject *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"txt", "name", NULL}; - PyObject *result = NULL; - char *txt; - int name = 0; - ASN1_OBJECT *obj; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|p:txt2obj", - kwlist, &txt, &name)) { - return NULL; - } - obj = OBJ_txt2obj(txt, name ? 0 : 1); - if (obj == NULL) { - PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt); - return NULL; - } - result = asn1obj2py(obj); - ASN1_OBJECT_free(obj); - return result; -} - -PyDoc_STRVAR(PySSL_nid2obj_doc, -"nid2obj(nid) -> (nid, shortname, longname, oid)\n\ -\n\ -Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID."); - -static PyObject* -PySSL_nid2obj(PyObject *self, PyObject *args) -{ - PyObject *result = NULL; - int nid; - ASN1_OBJECT *obj; - - if (!PyArg_ParseTuple(args, "i:nid2obj", &nid)) { - return NULL; - } - if (nid < NID_undef) { - PyErr_SetString(PyExc_ValueError, "NID must be positive."); - return NULL; - } - obj = OBJ_nid2obj(nid); - if (obj == NULL) { - PyErr_Format(PyExc_ValueError, "unknown NID %i", nid); - return NULL; - } - result = asn1obj2py(obj); - ASN1_OBJECT_free(obj); - return result; -} - -#ifdef _MSC_VER - -static PyObject* -certEncodingType(DWORD encodingType) -{ - static PyObject *x509_asn = NULL; - static PyObject *pkcs_7_asn = NULL; - - if (x509_asn == NULL) { - x509_asn = PyUnicode_InternFromString("x509_asn"); - if (x509_asn == NULL) - return NULL; - } - if (pkcs_7_asn == NULL) { - pkcs_7_asn = PyUnicode_InternFromString("pkcs_7_asn"); - if (pkcs_7_asn == NULL) - return NULL; - } - switch(encodingType) { - case X509_ASN_ENCODING: - Py_INCREF(x509_asn); - return x509_asn; - case PKCS_7_ASN_ENCODING: - Py_INCREF(pkcs_7_asn); - return pkcs_7_asn; - default: - return PyLong_FromLong(encodingType); - } -} - -static PyObject* -parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags) -{ - CERT_ENHKEY_USAGE *usage; - DWORD size, error, i; - PyObject *retval; - - if (!CertGetEnhancedKeyUsage(pCertCtx, flags, NULL, &size)) { - error = GetLastError(); - if (error == CRYPT_E_NOT_FOUND) { - Py_RETURN_TRUE; - } - return PyErr_SetFromWindowsErr(error); - } - - usage = (CERT_ENHKEY_USAGE*)PyMem_Malloc(size); - if (usage == NULL) { - return PyErr_NoMemory(); - } - - /* Now get the actual enhanced usage property */ - if (!CertGetEnhancedKeyUsage(pCertCtx, flags, usage, &size)) { - PyMem_Free(usage); - error = GetLastError(); - if (error == CRYPT_E_NOT_FOUND) { - Py_RETURN_TRUE; - } - return PyErr_SetFromWindowsErr(error); - } - retval = PySet_New(NULL); - if (retval == NULL) { - goto error; - } - for (i = 0; i < usage->cUsageIdentifier; ++i) { - if (usage->rgpszUsageIdentifier[i]) { - PyObject *oid; - int err; - oid = PyUnicode_FromString(usage->rgpszUsageIdentifier[i]); - if (oid == NULL) { - Py_CLEAR(retval); - goto error; - } - err = PySet_Add(retval, oid); - Py_DECREF(oid); - if (err == -1) { - Py_CLEAR(retval); - goto error; - } - } - } - error: - PyMem_Free(usage); - return retval; -} - -PyDoc_STRVAR(PySSL_enum_certificates_doc, -"enum_certificates(store_name) -> []\n\ -\n\ -Retrieve certificates from Windows' cert store. store_name may be one of\n\ -'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -The function returns a list of (bytes, encoding_type, trust) tuples. The\n\ -encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the\n\ -boolean True."); - -static PyObject * -PySSL_enum_certificates(PyObject *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"store_name", NULL}; - char *store_name; - HCERTSTORE hStore = NULL; - PCCERT_CONTEXT pCertCtx = NULL; - PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; - PyObject *result = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_certificates", - kwlist, &store_name)) { - return NULL; - } - result = PyList_New(0); - if (result == NULL) { - return NULL; - } - hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); - if (hStore == NULL) { - Py_DECREF(result); - return PyErr_SetFromWindowsErr(GetLastError()); - } - - while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) { - cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded, - pCertCtx->cbCertEncoded); - if (!cert) { - Py_CLEAR(result); - break; - } - if ((enc = certEncodingType(pCertCtx->dwCertEncodingType)) == NULL) { - Py_CLEAR(result); - break; - } - keyusage = parseKeyUsage(pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); - if (keyusage == Py_True) { - Py_DECREF(keyusage); - keyusage = parseKeyUsage(pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); - } - if (keyusage == NULL) { - Py_CLEAR(result); - break; - } - if ((tup = PyTuple_New(3)) == NULL) { - Py_CLEAR(result); - break; - } - PyTuple_SET_ITEM(tup, 0, cert); - cert = NULL; - PyTuple_SET_ITEM(tup, 1, enc); - enc = NULL; - PyTuple_SET_ITEM(tup, 2, keyusage); - keyusage = NULL; - if (PyList_Append(result, tup) < 0) { - Py_CLEAR(result); - break; - } - Py_CLEAR(tup); - } - if (pCertCtx) { - /* loop ended with an error, need to clean up context manually */ - CertFreeCertificateContext(pCertCtx); - } - - /* In error cases cert, enc and tup may not be NULL */ - Py_XDECREF(cert); - Py_XDECREF(enc); - Py_XDECREF(keyusage); - Py_XDECREF(tup); - - if (!CertCloseStore(hStore, 0)) { - /* This error case might shadow another exception.*/ - Py_XDECREF(result); - return PyErr_SetFromWindowsErr(GetLastError()); - } - return result; -} - -PyDoc_STRVAR(PySSL_enum_crls_doc, -"enum_crls(store_name) -> []\n\ -\n\ -Retrieve CRLs from Windows' cert store. store_name may be one of\n\ -'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -The function returns a list of (bytes, encoding_type) tuples. The\n\ -encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -PKCS_7_ASN_ENCODING."); - -static PyObject * -PySSL_enum_crls(PyObject *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"store_name", NULL}; - char *store_name; - HCERTSTORE hStore = NULL; - PCCRL_CONTEXT pCrlCtx = NULL; - PyObject *crl = NULL, *enc = NULL, *tup = NULL; - PyObject *result = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_crls", - kwlist, &store_name)) { - return NULL; - } - result = PyList_New(0); - if (result == NULL) { - return NULL; - } - hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); - if (hStore == NULL) { - Py_DECREF(result); - return PyErr_SetFromWindowsErr(GetLastError()); - } - - while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) { - crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded, - pCrlCtx->cbCrlEncoded); - if (!crl) { - Py_CLEAR(result); - break; - } - if ((enc = certEncodingType(pCrlCtx->dwCertEncodingType)) == NULL) { - Py_CLEAR(result); - break; - } - if ((tup = PyTuple_New(2)) == NULL) { - Py_CLEAR(result); - break; - } - PyTuple_SET_ITEM(tup, 0, crl); - crl = NULL; - PyTuple_SET_ITEM(tup, 1, enc); - enc = NULL; - - if (PyList_Append(result, tup) < 0) { - Py_CLEAR(result); - break; - } - Py_CLEAR(tup); - } - if (pCrlCtx) { - /* loop ended with an error, need to clean up context manually */ - CertFreeCRLContext(pCrlCtx); - } - - /* In error cases cert, enc and tup may not be NULL */ - Py_XDECREF(crl); - Py_XDECREF(enc); - Py_XDECREF(tup); - - if (!CertCloseStore(hStore, 0)) { - /* This error case might shadow another exception.*/ - Py_XDECREF(result); - return PyErr_SetFromWindowsErr(GetLastError()); - } - return result; -} - -#endif /* _MSC_VER */ - -/* List of functions exported by this module. */ - -static PyMethodDef PySSL_methods[] = { - {"_test_decode_cert", PySSL_test_decode_certificate, - METH_VARARGS}, - {"RAND_add", PySSL_RAND_add, METH_VARARGS, - PySSL_RAND_add_doc}, - {"RAND_bytes", PySSL_RAND_bytes, METH_VARARGS, - PySSL_RAND_bytes_doc}, - {"RAND_pseudo_bytes", PySSL_RAND_pseudo_bytes, METH_VARARGS, - PySSL_RAND_pseudo_bytes_doc}, -#ifdef HAVE_RAND_EGD - {"RAND_egd", PySSL_RAND_egd, METH_VARARGS, - PySSL_RAND_egd_doc}, -#endif - {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, - PySSL_RAND_status_doc}, - {"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths, - METH_NOARGS, PySSL_get_default_verify_paths_doc}, -#ifdef _MSC_VER - {"enum_certificates", (PyCFunction)PySSL_enum_certificates, - METH_VARARGS | METH_KEYWORDS, PySSL_enum_certificates_doc}, - {"enum_crls", (PyCFunction)PySSL_enum_crls, - METH_VARARGS | METH_KEYWORDS, PySSL_enum_crls_doc}, -#endif - {"txt2obj", (PyCFunction)PySSL_txt2obj, - METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc}, - {"nid2obj", (PyCFunction)PySSL_nid2obj, - METH_VARARGS, PySSL_nid2obj_doc}, - {NULL, NULL} /* Sentinel */ -}; - - -#ifdef WITH_THREAD - -/* an implementation of OpenSSL threading operations in terms - of the Python C thread library */ - -static PyThread_type_lock *_ssl_locks = NULL; - -#if OPENSSL_VERSION_NUMBER >= 0x10000000 -/* use new CRYPTO_THREADID API. */ -static void -_ssl_threadid_callback(CRYPTO_THREADID *id) -{ - CRYPTO_THREADID_set_numeric(id, - (unsigned long)PyThread_get_thread_ident()); -} -#else -/* deprecated CRYPTO_set_id_callback() API. */ -static unsigned long -_ssl_thread_id_function (void) { - return PyThread_get_thread_ident(); -} -#endif - -static void _ssl_thread_locking_function - (int mode, int n, const char *file, int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data - structures that will be implicitly shared whenever multiple - threads use OpenSSL.) Multi-threaded applications will - crash at random if it is not set. - - locking_function() must be able to handle up to - CRYPTO_num_locks() different mutex locks. It sets the n-th - lock if mode & CRYPTO_LOCK, and releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. - */ - - if ((_ssl_locks == NULL) || - (n < 0) || ((unsigned)n >= _ssl_locks_count)) - return; - - if (mode & CRYPTO_LOCK) { - PyThread_acquire_lock(_ssl_locks[n], 1); - } else { - PyThread_release_lock(_ssl_locks[n]); - } -} - -static int _setup_ssl_threads(void) { - - unsigned int i; - - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = PyMem_New(PyThread_type_lock, _ssl_locks_count); - if (_ssl_locks == NULL) { - PyErr_NoMemory(); - return 0; - } - memset(_ssl_locks, 0, - sizeof(PyThread_type_lock) * _ssl_locks_count); - for (i = 0; i < _ssl_locks_count; i++) { - _ssl_locks[i] = PyThread_allocate_lock(); - if (_ssl_locks[i] == NULL) { - unsigned int j; - for (j = 0; j < i; j++) { - PyThread_free_lock(_ssl_locks[j]); - } - PyMem_Free(_ssl_locks); - return 0; - } - } - CRYPTO_set_locking_callback(_ssl_thread_locking_function); -#if OPENSSL_VERSION_NUMBER >= 0x10000000 - CRYPTO_THREADID_set_callback(_ssl_threadid_callback); -#else - CRYPTO_set_id_callback(_ssl_thread_id_function); -#endif - } - return 1; -} - -#endif /* def HAVE_THREAD */ - -PyDoc_STRVAR(module_doc, -"Implementation module for SSL socket operations. See the socket module\n\ -for documentation."); - - -static struct PyModuleDef _sslmodule = { - PyModuleDef_HEAD_INIT, - "_ssl", - module_doc, - -1, - PySSL_methods, - NULL, - NULL, - NULL, - NULL -}; - - -static void -parse_openssl_version(unsigned long libver, - unsigned int *major, unsigned int *minor, - unsigned int *fix, unsigned int *patch, - unsigned int *status) -{ - *status = libver & 0xF; - libver >>= 4; - *patch = libver & 0xFF; - libver >>= 8; - *fix = libver & 0xFF; - libver >>= 8; - *minor = libver & 0xFF; - libver >>= 8; - *major = libver & 0xFF; -} - -PyMODINIT_FUNC -PyInit__ssl(void) -{ - PyObject *m, *d, *r; - unsigned long libver; - unsigned int major, minor, fix, patch, status; - PySocketModule_APIObject *socket_api; - struct py_ssl_error_code *errcode; - struct py_ssl_library_code *libcode; - - if (PyType_Ready(&PySSLContext_Type) < 0) - return NULL; - if (PyType_Ready(&PySSLSocket_Type) < 0) - return NULL; - if (PyType_Ready(&PySSLMemoryBIO_Type) < 0) - return NULL; - - m = PyModule_Create(&_sslmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - - /* Load _socket module and its C API */ - socket_api = PySocketModule_ImportModuleAndAPI(); - if (!socket_api) - return NULL; - PySocketModule = *socket_api; - - /* Init OpenSSL */ - SSL_load_error_strings(); - SSL_library_init(); -#ifdef WITH_THREAD - /* note that this will start threading if not already started */ - if (!_setup_ssl_threads()) { - return NULL; - } -#endif - OpenSSL_add_all_algorithms(); - - /* Add symbols to module dict */ - sslerror_type_slots[0].pfunc = PyExc_OSError; - PySSLErrorObject = PyType_FromSpec(&sslerror_type_spec); - if (PySSLErrorObject == NULL) - return NULL; - - PySSLZeroReturnErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLZeroReturnError", SSLZeroReturnError_doc, - PySSLErrorObject, NULL); - PySSLWantReadErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLWantReadError", SSLWantReadError_doc, - PySSLErrorObject, NULL); - PySSLWantWriteErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLWantWriteError", SSLWantWriteError_doc, - PySSLErrorObject, NULL); - PySSLSyscallErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLSyscallError", SSLSyscallError_doc, - PySSLErrorObject, NULL); - PySSLEOFErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLEOFError", SSLEOFError_doc, - PySSLErrorObject, NULL); - if (PySSLZeroReturnErrorObject == NULL - || PySSLWantReadErrorObject == NULL - || PySSLWantWriteErrorObject == NULL - || PySSLSyscallErrorObject == NULL - || PySSLEOFErrorObject == NULL) - return NULL; - if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0 - || PyDict_SetItemString(d, "SSLZeroReturnError", PySSLZeroReturnErrorObject) != 0 - || PyDict_SetItemString(d, "SSLWantReadError", PySSLWantReadErrorObject) != 0 - || PyDict_SetItemString(d, "SSLWantWriteError", PySSLWantWriteErrorObject) != 0 - || PyDict_SetItemString(d, "SSLSyscallError", PySSLSyscallErrorObject) != 0 - || PyDict_SetItemString(d, "SSLEOFError", PySSLEOFErrorObject) != 0) - return NULL; - if (PyDict_SetItemString(d, "_SSLContext", - (PyObject *)&PySSLContext_Type) != 0) - return NULL; - if (PyDict_SetItemString(d, "_SSLSocket", - (PyObject *)&PySSLSocket_Type) != 0) - return NULL; - if (PyDict_SetItemString(d, "MemoryBIO", - (PyObject *)&PySSLMemoryBIO_Type) != 0) - return NULL; - PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - PY_SSL_ERROR_ZERO_RETURN); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", - PY_SSL_ERROR_WANT_READ); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", - PY_SSL_ERROR_WANT_WRITE); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", - PY_SSL_ERROR_WANT_X509_LOOKUP); - PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", - PY_SSL_ERROR_SYSCALL); - PyModule_AddIntConstant(m, "SSL_ERROR_SSL", - PY_SSL_ERROR_SSL); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", - PY_SSL_ERROR_WANT_CONNECT); - /* non ssl.h errorcodes */ - PyModule_AddIntConstant(m, "SSL_ERROR_EOF", - PY_SSL_ERROR_EOF); - PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", - PY_SSL_ERROR_INVALID_ERROR_CODE); - /* cert requirements */ - PyModule_AddIntConstant(m, "CERT_NONE", - PY_SSL_CERT_NONE); - PyModule_AddIntConstant(m, "CERT_OPTIONAL", - PY_SSL_CERT_OPTIONAL); - PyModule_AddIntConstant(m, "CERT_REQUIRED", - PY_SSL_CERT_REQUIRED); - /* CRL verification for verification_flags */ - PyModule_AddIntConstant(m, "VERIFY_DEFAULT", - 0); - PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_LEAF", - X509_V_FLAG_CRL_CHECK); - PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_CHAIN", - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - PyModule_AddIntConstant(m, "VERIFY_X509_STRICT", - X509_V_FLAG_X509_STRICT); -#ifdef X509_V_FLAG_TRUSTED_FIRST - PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST", - X509_V_FLAG_TRUSTED_FIRST); -#endif - - /* Alert Descriptions from ssl.h */ - /* note RESERVED constants no longer intended for use have been removed */ - /* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */ - -#define ADD_AD_CONSTANT(s) \ - PyModule_AddIntConstant(m, "ALERT_DESCRIPTION_"#s, \ - SSL_AD_##s) - - ADD_AD_CONSTANT(CLOSE_NOTIFY); - ADD_AD_CONSTANT(UNEXPECTED_MESSAGE); - ADD_AD_CONSTANT(BAD_RECORD_MAC); - ADD_AD_CONSTANT(RECORD_OVERFLOW); - ADD_AD_CONSTANT(DECOMPRESSION_FAILURE); - ADD_AD_CONSTANT(HANDSHAKE_FAILURE); - ADD_AD_CONSTANT(BAD_CERTIFICATE); - ADD_AD_CONSTANT(UNSUPPORTED_CERTIFICATE); - ADD_AD_CONSTANT(CERTIFICATE_REVOKED); - ADD_AD_CONSTANT(CERTIFICATE_EXPIRED); - ADD_AD_CONSTANT(CERTIFICATE_UNKNOWN); - ADD_AD_CONSTANT(ILLEGAL_PARAMETER); - ADD_AD_CONSTANT(UNKNOWN_CA); - ADD_AD_CONSTANT(ACCESS_DENIED); - ADD_AD_CONSTANT(DECODE_ERROR); - ADD_AD_CONSTANT(DECRYPT_ERROR); - ADD_AD_CONSTANT(PROTOCOL_VERSION); - ADD_AD_CONSTANT(INSUFFICIENT_SECURITY); - ADD_AD_CONSTANT(INTERNAL_ERROR); - ADD_AD_CONSTANT(USER_CANCELLED); - ADD_AD_CONSTANT(NO_RENEGOTIATION); - /* Not all constants are in old OpenSSL versions */ -#ifdef SSL_AD_UNSUPPORTED_EXTENSION - ADD_AD_CONSTANT(UNSUPPORTED_EXTENSION); -#endif -#ifdef SSL_AD_CERTIFICATE_UNOBTAINABLE - ADD_AD_CONSTANT(CERTIFICATE_UNOBTAINABLE); -#endif -#ifdef SSL_AD_UNRECOGNIZED_NAME - ADD_AD_CONSTANT(UNRECOGNIZED_NAME); -#endif -#ifdef SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE - ADD_AD_CONSTANT(BAD_CERTIFICATE_STATUS_RESPONSE); -#endif -#ifdef SSL_AD_BAD_CERTIFICATE_HASH_VALUE - ADD_AD_CONSTANT(BAD_CERTIFICATE_HASH_VALUE); -#endif -#ifdef SSL_AD_UNKNOWN_PSK_IDENTITY - ADD_AD_CONSTANT(UNKNOWN_PSK_IDENTITY); -#endif - -#undef ADD_AD_CONSTANT - - /* protocol versions */ -#ifndef OPENSSL_NO_SSL2 - PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", - PY_SSL_VERSION_SSL2); -#endif -#ifndef OPENSSL_NO_SSL3 - PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", - PY_SSL_VERSION_SSL3); -#endif - PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", - PY_SSL_VERSION_SSL23); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", - PY_SSL_VERSION_TLS1); -#if HAVE_TLSv1_2 - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_1", - PY_SSL_VERSION_TLS1_1); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2", - PY_SSL_VERSION_TLS1_2); -#endif - - /* protocol options */ - PyModule_AddIntConstant(m, "OP_ALL", - SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); - PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2); - PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); - PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); -#if HAVE_TLSv1_2 - PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1); - PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2); -#endif - PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE", - SSL_OP_CIPHER_SERVER_PREFERENCE); - PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE); -#ifdef SSL_OP_SINGLE_ECDH_USE - PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE); -#endif -#ifdef SSL_OP_NO_COMPRESSION - PyModule_AddIntConstant(m, "OP_NO_COMPRESSION", - SSL_OP_NO_COMPRESSION); -#endif - -#if HAVE_SNI - r = Py_True; -#else - r = Py_False; -#endif - 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 - r = Py_True; -#endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ECDH", r); - -#ifdef OPENSSL_NPN_NEGOTIATED - r = Py_True; -#else - r = Py_False; -#endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_NPN", r); - -#ifdef HAVE_ALPN - r = Py_True; -#else - r = Py_False; -#endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ALPN", r); - - /* Mappings for error codes */ - err_codes_to_names = PyDict_New(); - err_names_to_codes = PyDict_New(); - if (err_codes_to_names == NULL || err_names_to_codes == NULL) - return NULL; - errcode = error_codes; - while (errcode->mnemonic != NULL) { - PyObject *mnemo, *key; - mnemo = PyUnicode_FromString(errcode->mnemonic); - key = Py_BuildValue("ii", errcode->library, errcode->reason); - if (mnemo == NULL || key == NULL) - return NULL; - if (PyDict_SetItem(err_codes_to_names, key, mnemo)) - return NULL; - if (PyDict_SetItem(err_names_to_codes, mnemo, key)) - return NULL; - Py_DECREF(key); - Py_DECREF(mnemo); - errcode++; - } - if (PyModule_AddObject(m, "err_codes_to_names", err_codes_to_names)) - return NULL; - if (PyModule_AddObject(m, "err_names_to_codes", err_names_to_codes)) - return NULL; - - lib_codes_to_names = PyDict_New(); - if (lib_codes_to_names == NULL) - return NULL; - libcode = library_codes; - while (libcode->library != NULL) { - PyObject *mnemo, *key; - key = PyLong_FromLong(libcode->code); - mnemo = PyUnicode_FromString(libcode->library); - if (key == NULL || mnemo == NULL) - return NULL; - if (PyDict_SetItem(lib_codes_to_names, key, mnemo)) - return NULL; - Py_DECREF(key); - Py_DECREF(mnemo); - libcode++; - } - if (PyModule_AddObject(m, "lib_codes_to_names", lib_codes_to_names)) - return NULL; - - /* OpenSSL version */ - /* SSLeay() gives us the version of the library linked against, - which could be different from the headers version. - */ - libver = SSLeay(); - r = PyLong_FromUnsignedLong(libver); - if (r == NULL) - return NULL; - if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) - return NULL; - parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); - r = Py_BuildValue("IIIII", major, minor, fix, patch, status); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) - return NULL; - r = PyUnicode_FromString(SSLeay_version(SSLEAY_VERSION)); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) - return NULL; - - libver = OPENSSL_VERSION_NUMBER; - parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); - r = Py_BuildValue("IIIII", major, minor, fix, patch, status); - if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r)) - return NULL; - - return m; -} +#ifndef _SSL_ENUM_CRLS_METHODDEF + #define _SSL_ENUM_CRLS_METHODDEF +#endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ +/*[clinic end generated code: output=a14999cb565a69a2 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 17:30:07 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 15:30:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3_=28=2324096=29?= Message-ID: <20150503153007.84506.89404@psf.io> https://hg.python.org/cpython/rev/47f4c3a5d86a changeset: 95871:47f4c3a5d86a branch: 3.4 parent: 95865:0079465a9425 parent: 95870:ffc1f9d1c8b3 user: Benjamin Peterson date: Sun May 03 11:28:46 2015 -0400 summary: merge 3.3 (#24096) files: Lib/test/test_warnings.py | 12 ++++++++ Misc/NEWS | 3 ++ Python/_warnings.c | 37 +++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -247,6 +247,18 @@ self.assertEqual(str(w[-1].message), text) self.assertTrue(w[-1].category is UserWarning) + def test_mutate_filter_list(self): + class X: + def match(self, a): + L[:] = [] + + L = [("default",X(),UserWarning,X(),0) for i in range(2)] + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + self.module.filters = L + self.module.warn_explicit(UserWarning("b"), None, "f.py", 42) + self.assertEqual(str(w[-1].message), "b") + class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24096: Make warnings.warn_explicit more robust against mutation of the + warnings.filters list. + - Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel. diff --git a/Python/_warnings.c b/Python/_warnings.c --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -101,7 +101,7 @@ } -/* The item is a borrowed reference. */ +/* The item is a new reference. */ static PyObject* get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, PyObject *module, PyObject **item) @@ -132,14 +132,15 @@ Py_ssize_t ln; int is_subclass, good_msg, good_mod; - tmp_item = *item = PyList_GET_ITEM(_filters, i); - if (PyTuple_Size(tmp_item) != 5) { + tmp_item = PyList_GET_ITEM(_filters, i); + if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) { PyErr_Format(PyExc_ValueError, MODULE_NAME ".filters item %zd isn't a 5-tuple", i); return NULL; } /* Python code: action, msg, cat, mod, ln = item */ + Py_INCREF(tmp_item); action = PyTuple_GET_ITEM(tmp_item, 0); msg = PyTuple_GET_ITEM(tmp_item, 1); cat = PyTuple_GET_ITEM(tmp_item, 2); @@ -147,28 +148,43 @@ ln_obj = PyTuple_GET_ITEM(tmp_item, 4); good_msg = check_matched(msg, text); - if (good_msg == -1) + if (good_msg == -1) { + Py_DECREF(tmp_item); return NULL; + } good_mod = check_matched(mod, module); - if (good_mod == -1) + if (good_mod == -1) { + Py_DECREF(tmp_item); return NULL; + } is_subclass = PyObject_IsSubclass(category, cat); - if (is_subclass == -1) + if (is_subclass == -1) { + Py_DECREF(tmp_item); return NULL; + } ln = PyLong_AsSsize_t(ln_obj); - if (ln == -1 && PyErr_Occurred()) + if (ln == -1 && PyErr_Occurred()) { + Py_DECREF(tmp_item); return NULL; + } - if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) + if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) { + *item = tmp_item; return action; + } + + Py_DECREF(tmp_item); } action = get_default_action(); - if (action != NULL) + if (action != NULL) { + Py_INCREF(Py_None); + *item = Py_None; return action; + } PyErr_SetString(PyExc_ValueError, MODULE_NAME ".defaultaction not found"); @@ -349,7 +365,7 @@ PyObject *module, PyObject *registry, PyObject *sourceline) { PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; - PyObject *item = Py_None; + PyObject *item = NULL; PyObject *action; int rc; @@ -488,6 +504,7 @@ Py_INCREF(result); cleanup: + Py_XDECREF(item); Py_XDECREF(key); Py_XDECREF(text); Py_XDECREF(lineno_obj); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 17:30:07 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 15:30:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_be_more_robust?= =?utf-8?q?_against_the_filters_list_changing_under_us_=28closes_=2324096?= =?utf-8?q?=29?= Message-ID: <20150503153007.98689.54953@psf.io> https://hg.python.org/cpython/rev/ffc1f9d1c8b3 changeset: 95870:ffc1f9d1c8b3 branch: 3.3 parent: 95858:0e8c9cf1fede user: Benjamin Peterson date: Sun May 03 11:23:37 2015 -0400 summary: be more robust against the filters list changing under us (closes #24096) files: Lib/test/test_warnings.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Python/_warnings.c | 22 ++++++++++++++++------ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -185,6 +185,18 @@ self.assertEqual(str(w[-1].message), text) self.assertTrue(w[-1].category is UserWarning) + def test_mutate_filter_list(self): + class X: + def match(self, a): + L[:] = [] + + L = [("default",X(),UserWarning,X(),0) for i in range(2)] + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + self.module.filters = L + self.module.warn_explicit(UserWarning("b"), None, "f.py", 42) + self.assertEqual(str(w[-1].message), "b") + class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24096: Make warnings.warn_explicit more robust against mutation of the + warnings.filters list. + - Issue #24044: Fix possible null pointer dereference in list.sort in out of memory conditions. diff --git a/Python/_warnings.c b/Python/_warnings.c --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -98,7 +98,7 @@ } -/* The item is a borrowed reference. */ +/* The item is a new reference. */ static const char * get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, PyObject *module, PyObject **item) @@ -129,14 +129,15 @@ Py_ssize_t ln; int is_subclass, good_msg, good_mod; - tmp_item = *item = PyList_GET_ITEM(_filters, i); - if (PyTuple_Size(tmp_item) != 5) { + tmp_item = PyList_GET_ITEM(_filters, i); + if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) { PyErr_Format(PyExc_ValueError, MODULE_NAME ".filters item %zd isn't a 5-tuple", i); return NULL; } /* Python code: action, msg, cat, mod, ln = item */ + Py_INCREF(tmp_item); action = PyTuple_GET_ITEM(tmp_item, 0); msg = PyTuple_GET_ITEM(tmp_item, 1); cat = PyTuple_GET_ITEM(tmp_item, 2); @@ -148,15 +149,23 @@ is_subclass = PyObject_IsSubclass(category, cat); ln = PyLong_AsSsize_t(ln_obj); if (good_msg == -1 || good_mod == -1 || is_subclass == -1 || - (ln == -1 && PyErr_Occurred())) + (ln == -1 && PyErr_Occurred())) { + Py_DECREF(tmp_item); return NULL; + } - if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) + if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) { + *item = tmp_item; return _PyUnicode_AsString(action); + } + + Py_DECREF(tmp_item); } action = get_default_action(); if (action != NULL) { + Py_INCREF(Py_None); + *item = Py_None; return _PyUnicode_AsString(action); } @@ -295,7 +304,7 @@ PyObject *module, PyObject *registry, PyObject *sourceline) { PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; - PyObject *item = Py_None; + PyObject *item = NULL; const char *action; int rc; @@ -436,6 +445,7 @@ Py_INCREF(result); cleanup: + Py_XDECREF(item); Py_XDECREF(key); Py_XDECREF(text); Py_XDECREF(lineno_obj); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 17:30:07 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 15:30:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwOTYp?= Message-ID: <20150503153007.76604.52534@psf.io> https://hg.python.org/cpython/rev/bfea101f9402 changeset: 95872:bfea101f9402 parent: 95869:1eaaf27b3956 parent: 95871:47f4c3a5d86a user: Benjamin Peterson date: Sun May 03 11:29:58 2015 -0400 summary: merge 3.4 (#24096) files: Lib/test/test_warnings.py | 12 ++++++++ Misc/NEWS | 3 ++ Python/_warnings.c | 37 +++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -247,6 +247,18 @@ self.assertEqual(str(w[-1].message), text) self.assertTrue(w[-1].category is UserWarning) + def test_mutate_filter_list(self): + class X: + def match(self, a): + L[:] = [] + + L = [("default",X(),UserWarning,X(),0) for i in range(2)] + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + self.module.filters = L + self.module.warn_explicit(UserWarning("b"), None, "f.py", 42) + self.assertEqual(str(w[-1].message), "b") + class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24096: Make warnings.warn_explicit more robust against mutation of the + warnings.filters list. + - Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel. diff --git a/Python/_warnings.c b/Python/_warnings.c --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -101,7 +101,7 @@ } -/* The item is a borrowed reference. */ +/* The item is a new reference. */ static PyObject* get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, PyObject *module, PyObject **item) @@ -132,14 +132,15 @@ Py_ssize_t ln; int is_subclass, good_msg, good_mod; - tmp_item = *item = PyList_GET_ITEM(_filters, i); - if (PyTuple_Size(tmp_item) != 5) { + tmp_item = PyList_GET_ITEM(_filters, i); + if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) { PyErr_Format(PyExc_ValueError, MODULE_NAME ".filters item %zd isn't a 5-tuple", i); return NULL; } /* Python code: action, msg, cat, mod, ln = item */ + Py_INCREF(tmp_item); action = PyTuple_GET_ITEM(tmp_item, 0); msg = PyTuple_GET_ITEM(tmp_item, 1); cat = PyTuple_GET_ITEM(tmp_item, 2); @@ -147,28 +148,43 @@ ln_obj = PyTuple_GET_ITEM(tmp_item, 4); good_msg = check_matched(msg, text); - if (good_msg == -1) + if (good_msg == -1) { + Py_DECREF(tmp_item); return NULL; + } good_mod = check_matched(mod, module); - if (good_mod == -1) + if (good_mod == -1) { + Py_DECREF(tmp_item); return NULL; + } is_subclass = PyObject_IsSubclass(category, cat); - if (is_subclass == -1) + if (is_subclass == -1) { + Py_DECREF(tmp_item); return NULL; + } ln = PyLong_AsSsize_t(ln_obj); - if (ln == -1 && PyErr_Occurred()) + if (ln == -1 && PyErr_Occurred()) { + Py_DECREF(tmp_item); return NULL; + } - if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) + if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) { + *item = tmp_item; return action; + } + + Py_DECREF(tmp_item); } action = get_default_action(); - if (action != NULL) + if (action != NULL) { + Py_INCREF(Py_None); + *item = Py_None; return action; + } PyErr_SetString(PyExc_ValueError, MODULE_NAME ".defaultaction not found"); @@ -349,7 +365,7 @@ PyObject *module, PyObject *registry, PyObject *sourceline) { PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; - PyObject *item = Py_None; + PyObject *item = NULL; PyObject *action; int rc; @@ -488,6 +504,7 @@ Py_INCREF(result); cleanup: + Py_XDECREF(item); Py_XDECREF(key); Py_XDECREF(text); Py_XDECREF(lineno_obj); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 3 19:00:43 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 03 May 2015 17:00:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_update_example?= =?utf-8?q?=2C_since_python=2Eorg_is_HTTPS-only_now_=28closes_=2324118=29?= Message-ID: <20150503170043.1924.56627@psf.io> https://hg.python.org/cpython/rev/71ec881d8347 changeset: 95873:71ec881d8347 branch: 3.4 parent: 95871:47f4c3a5d86a user: Benjamin Peterson date: Sun May 03 12:59:09 2015 -0400 summary: update example, since python.org is HTTPS-only now (closes #24118) files: Doc/library/http.client.rst | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -615,18 +615,18 @@ Here is an example session that uses the ``GET`` method:: >>> import http.client - >>> conn = http.client.HTTPConnection("www.python.org") - >>> conn.request("GET", "/index.html") + >>> conn = http.client.HTTPSConnection("www.python.org") + >>> conn.request("GET", "/") >>> r1 = conn.getresponse() >>> print(r1.status, r1.reason) 200 OK >>> data1 = r1.read() # This will return entire content. >>> # The following example demonstrates reading data in chunks. - >>> conn.request("GET", "/index.html") + >>> conn.request("GET", "/") >>> r1 = conn.getresponse() >>> while not r1.closed: ... print(r1.read(200)) # 200 bytes - b'\n - - VersionNT > 600 - - - - - VersionNT > 600 - - - - - - VersionNT > 600 - - - - - - - VersionNT > 600 - - - - - - - - VersionNT = 600 - - - - - - - VersionNT = 600 - - - - - - diff --git a/Tools/msi/tcltk/tcltk_reg.wxs b/Tools/msi/tcltk/tcltk_reg.wxs new file mode 100644 --- /dev/null +++ b/Tools/msi/tcltk/tcltk_reg.wxs @@ -0,0 +1,48 @@ +? + + + + + + VersionNT > 600 + + + + + VersionNT > 600 + + + + + + VersionNT > 600 + + + + + + + VersionNT > 600 + + + + + + + + VersionNT = 600 + + + + + + + VersionNT = 600 + + + + + + + + -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon May 4 10:39:14 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 04 May 2015 08:39:14 +0000 Subject: [Python-checkins] Daily reference leaks (73a665cc2333): sum=3 Message-ID: <20150504083913.14376.55467@psf.io> results for 73a665cc2333 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogjCJLox', '--timeout', '7200'] From python-checkins at python.org Mon May 4 14:33:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 04 May 2015 12:33:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320159=2E_Converte?= =?utf-8?q?d_the_=5Felementtree_module_to_Argument_Clinic=2E?= Message-ID: <20150504123327.1921.5919@psf.io> https://hg.python.org/cpython/rev/fea94f9cb5a0 changeset: 95878:fea94f9cb5a0 user: Serhiy Storchaka date: Mon May 04 15:32:48 2015 +0300 summary: Issue #20159. Converted the _elementtree module to Argument Clinic. files: Modules/_elementtree.c | 2578 ++++++++------- Modules/_elementtree.c | 4337 +++------------------------ 2 files changed, 1978 insertions(+), 4937 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -370,6 +370,14 @@ return attrib; } +/*[clinic input] +module _elementtree +class _elementtree.Element "ElementObject *" "&Element_Type" +class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type" +class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=159aa50a54061c22]*/ + static int element_init(PyObject *self, PyObject *args, PyObject *kwds) { @@ -658,25 +666,33 @@ /* -------------------------------------------------------------------- */ -static PyObject* -element_append(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.append + + subelement: object(subclass_of='&Element_Type') + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_append_impl(ElementObject *self, PyObject *subelement) +/*[clinic end generated code: output=54a884b7cf2295f4 input=3ed648beb5bfa22a]*/ { - PyObject* element; - if (!PyArg_ParseTuple(args, "O!:append", &Element_Type, &element)) - return NULL; - - if (element_add_subelement(self, element) < 0) + if (element_add_subelement(self, subelement) < 0) return NULL; Py_RETURN_NONE; } -static PyObject* -element_clearmethod(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.clear + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_clear_impl(ElementObject *self) +/*[clinic end generated code: output=8bcd7a51f94cfff6 input=3c719ff94bf45dd6]*/ { - if (!PyArg_ParseTuple(args, ":clear")) - return NULL; - dealloc_extra(self); Py_INCREF(Py_None); @@ -690,15 +706,18 @@ Py_RETURN_NONE; } -static PyObject* -element_copy(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.__copy__ + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element___copy___impl(ElementObject *self) +/*[clinic end generated code: output=2c701ebff7247781 input=ad87aaebe95675bf]*/ { Py_ssize_t i; ElementObject* element; - if (!PyArg_ParseTuple(args, ":__copy__")) - return NULL; - element = (ElementObject*) create_new_element( self->tag, (self->extra) ? self->extra->attrib : Py_None); if (!element) @@ -729,8 +748,17 @@ return (PyObject*) element; } -static PyObject* -element_deepcopy(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.__deepcopy__ + + memo: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element___deepcopy__(ElementObject *self, PyObject *memo) +/*[clinic end generated code: output=d1f19851d17bf239 input=df24c2b602430b77]*/ { Py_ssize_t i; ElementObject* element; @@ -740,10 +768,6 @@ PyObject* tail; PyObject* id; - PyObject* memo; - if (!PyArg_ParseTuple(args, "O:__deepcopy__", &memo)) - return NULL; - tag = deepcopy(self->tag, memo); if (!tag) return NULL; @@ -814,17 +838,22 @@ return NULL; } -static PyObject* -element_sizeof(PyObject* myself, PyObject* args) +/*[clinic input] +_elementtree.Element.__sizeof__ -> Py_ssize_t + +[clinic start generated code]*/ + +static Py_ssize_t +_elementtree_Element___sizeof___impl(ElementObject *self) +/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/ { - ElementObject *self = (ElementObject*)myself; Py_ssize_t result = sizeof(ElementObject); if (self->extra) { result += sizeof(ElementObjectExtra); if (self->extra->children != self->extra->_children) result += sizeof(PyObject*) * self->extra->allocated; } - return PyLong_FromSsize_t(result); + return result; } /* dict keys for getstate/setstate. */ @@ -840,8 +869,14 @@ * any unnecessary structures there; and (b) it buys compatibility with 3.2 * pickles. See issue #16076. */ +/*[clinic input] +_elementtree.Element.__getstate__ + +[clinic start generated code]*/ + static PyObject * -element_getstate(ElementObject *self) +_elementtree_Element___getstate___impl(ElementObject *self) +/*[clinic end generated code: output=37279aeeb6bb5b04 input=f0d16d7ec2f7adc1]*/ { Py_ssize_t i, noattrib; PyObject *instancedict = NULL, *children; @@ -956,6 +991,7 @@ /* __setstate__ for Element instance from the Python implementation. * 'state' should be the instance dict. */ + static PyObject * element_setstate_from_Python(ElementObject *self, PyObject *state) { @@ -981,8 +1017,17 @@ return retval; } +/*[clinic input] +_elementtree.Element.__setstate__ + + state: object + / + +[clinic start generated code]*/ + static PyObject * -element_setstate(ElementObject *self, PyObject *state) +_elementtree_Element___setstate__(ElementObject *self, PyObject *state) +/*[clinic end generated code: output=ea28bf3491b1f75e input=aaf80abea7c1e3b9]*/ { if (!PyDict_CheckExact(state)) { PyErr_Format(PyExc_TypeError, @@ -1036,21 +1081,26 @@ return 1; /* unknown type; might be path expression */ } -static PyObject* -element_extend(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.extend + + elements: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_extend(ElementObject *self, PyObject *elements) +/*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/ { PyObject* seq; Py_ssize_t i, seqlen = 0; - PyObject* seq_in; - if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) - return NULL; - - seq = PySequence_Fast(seq_in, ""); + seq = PySequence_Fast(elements, ""); if (!seq) { PyErr_Format( PyExc_TypeError, - "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name + "expected sequence, not \"%.200s\"", Py_TYPE(elements)->tp_name ); return NULL; } @@ -1078,23 +1128,26 @@ Py_RETURN_NONE; } -static PyObject* -element_find(ElementObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_elementtree.Element.find + + path: object + namespaces: object = None + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_find_impl(ElementObject *self, PyObject *path, + PyObject *namespaces) +/*[clinic end generated code: output=41b43f0f0becafae input=359b6985f6489d2e]*/ { Py_ssize_t i; - PyObject* tag; - PyObject* namespaces = Py_None; - static char *kwlist[] = {"path", "namespaces", 0}; elementtreestate *st = ET_STATE_GLOBAL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:find", kwlist, - &tag, &namespaces)) - return NULL; - - if (checkpath(tag) || namespaces != Py_None) { + if (checkpath(path) || namespaces != Py_None) { _Py_IDENTIFIER(find); return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_find, "OOO", self, tag, namespaces + st->elementpath_obj, &PyId_find, "OOO", self, path, namespaces ); } @@ -1104,7 +1157,7 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { + PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ) == 1) { Py_INCREF(item); return item; } @@ -1113,24 +1166,28 @@ Py_RETURN_NONE; } -static PyObject* -element_findtext(ElementObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_elementtree.Element.findtext + + path: object + default: object = None + namespaces: object = None + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_findtext_impl(ElementObject *self, PyObject *path, + PyObject *default_value, + PyObject *namespaces) +/*[clinic end generated code: output=83b3ba4535d308d2 input=b53a85aa5aa2a916]*/ { Py_ssize_t i; - PyObject* tag; - PyObject* default_value = Py_None; - PyObject* namespaces = Py_None; _Py_IDENTIFIER(findtext); - static char *kwlist[] = {"path", "default", "namespaces", 0}; elementtreestate *st = ET_STATE_GLOBAL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:findtext", kwlist, - &tag, &default_value, &namespaces)) - return NULL; - - if (checkpath(tag) || namespaces != Py_None) + if (checkpath(path) || namespaces != Py_None) return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_findtext, "OOOO", self, tag, default_value, namespaces + st->elementpath_obj, &PyId_findtext, "OOOO", self, path, default_value, namespaces ); if (!self->extra) { @@ -1141,7 +1198,7 @@ for (i = 0; i < self->extra->length; i++) { ElementObject* item = (ElementObject*) self->extra->children[i]; if (Element_CheckExact(item) && - (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) { + (PyObject_RichCompareBool(item->tag, path, Py_EQ) == 1)) { PyObject* text = element_get_text(item); if (text == Py_None) return PyUnicode_New(0, 0); @@ -1154,20 +1211,24 @@ return default_value; } -static PyObject* -element_findall(ElementObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_elementtree.Element.findall + + path: object + namespaces: object = None + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_findall_impl(ElementObject *self, PyObject *path, + PyObject *namespaces) +/*[clinic end generated code: output=1a0bd9f5541b711d input=4d9e6505a638550c]*/ { Py_ssize_t i; PyObject* out; - PyObject* tag; - PyObject* namespaces = Py_None; - static char *kwlist[] = {"path", "namespaces", 0}; + PyObject* tag = path; elementtreestate *st = ET_STATE_GLOBAL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:findall", kwlist, - &tag, &namespaces)) - return NULL; - if (checkpath(tag) || namespaces != Py_None) { _Py_IDENTIFIER(findall); return _PyObject_CallMethodId( @@ -1196,36 +1257,41 @@ return out; } -static PyObject* -element_iterfind(ElementObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_elementtree.Element.iterfind + + path: object + namespaces: object = None + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path, + PyObject *namespaces) +/*[clinic end generated code: output=ecdd56d63b19d40f input=abb974e350fb65c7]*/ { - PyObject* tag; - PyObject* namespaces = Py_None; + PyObject* tag = path; _Py_IDENTIFIER(iterfind); - static char *kwlist[] = {"path", "namespaces", 0}; elementtreestate *st = ET_STATE_GLOBAL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:iterfind", kwlist, - &tag, &namespaces)) { - return NULL; - } - return _PyObject_CallMethodId( st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces); } -static PyObject* -element_get(ElementObject* self, PyObject* args, PyObject* kwds) +/*[clinic input] +_elementtree.Element.get + + key: object + default: object = None + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_get_impl(ElementObject *self, PyObject *key, + PyObject *default_value) +/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/ { PyObject* value; - static char* kwlist[] = {"key", "default", 0}; - - PyObject* key; - PyObject* default_value = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:get", kwlist, &key, - &default_value)) - return NULL; if (!self->extra || self->extra->attrib == Py_None) value = default_value; @@ -1239,17 +1305,20 @@ return value; } -static PyObject* -element_getchildren(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.getchildren + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_getchildren_impl(ElementObject *self) +/*[clinic end generated code: output=e50ffe118637b14f input=0f754dfded150d5f]*/ { Py_ssize_t i; PyObject* list; /* FIXME: report as deprecated? */ - if (!PyArg_ParseTuple(args, ":getchildren")) - return NULL; - if (!self->extra) return PyList_New(0); @@ -1271,25 +1340,30 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext); +/*[clinic input] +_elementtree.Element.iter + + tag: object = None + +[clinic start generated code]*/ + static PyObject * -element_iter(ElementObject *self, PyObject *args, PyObject *kwds) +_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag) +/*[clinic end generated code: output=3f49f9a862941cc5 input=774d5b12e573aedd]*/ { - PyObject* tag = Py_None; - static char* kwlist[] = {"tag", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:iter", kwlist, &tag)) - return NULL; - return create_elementiter(self, tag, 0); } -static PyObject* -element_itertext(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.itertext + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_itertext_impl(ElementObject *self) +/*[clinic end generated code: output=5fa34b2fbcb65df6 input=af8f0e42cb239c89]*/ { - if (!PyArg_ParseTuple(args, ":itertext")) - return NULL; - return create_elementiter(self, Py_None, 1); } @@ -1311,14 +1385,21 @@ return self->extra->children[index]; } -static PyObject* -element_insert(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.insert + + index: Py_ssize_t + subelement: object(subclass_of='&Element_Type') + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, + PyObject *subelement) +/*[clinic end generated code: output=990adfef4d424c0b input=cd6fbfcdab52d7a8]*/ { - Py_ssize_t index, i; - PyObject* element; - if (!PyArg_ParseTuple(args, "nO!:insert", &index, - &Element_Type, &element)) - return NULL; + Py_ssize_t i; if (!self->extra) { if (create_extra(self, NULL) < 0) @@ -1339,32 +1420,38 @@ for (i = self->extra->length; i > index; i--) self->extra->children[i] = self->extra->children[i-1]; - Py_INCREF(element); - self->extra->children[index] = element; + Py_INCREF(subelement); + self->extra->children[index] = subelement; self->extra->length++; Py_RETURN_NONE; } -static PyObject* -element_items(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.items + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_items_impl(ElementObject *self) +/*[clinic end generated code: output=6db2c778ce3f5a4d input=adbe09aaea474447]*/ { - if (!PyArg_ParseTuple(args, ":items")) - return NULL; - if (!self->extra || self->extra->attrib == Py_None) return PyList_New(0); return PyDict_Items(self->extra->attrib); } -static PyObject* -element_keys(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.keys + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_keys_impl(ElementObject *self) +/*[clinic end generated code: output=bc5bfabbf20eeb3c input=f02caf5b496b5b0b]*/ { - if (!PyArg_ParseTuple(args, ":keys")) - return NULL; - if (!self->extra || self->extra->attrib == Py_None) return PyList_New(0); @@ -1380,16 +1467,22 @@ return self->extra->length; } -static PyObject* -element_makeelement(PyObject* self, PyObject* args, PyObject* kw) +/*[clinic input] +_elementtree.Element.makeelement + + tag: object + attrib: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, + PyObject *attrib) +/*[clinic end generated code: output=4109832d5bb789ef input=9480d1d2e3e68235]*/ { PyObject* elem; - PyObject* tag; - PyObject* attrib; - if (!PyArg_ParseTuple(args, "OO:makeelement", &tag, &attrib)) - return NULL; - attrib = PyDict_Copy(attrib); if (!attrib) return NULL; @@ -1401,15 +1494,20 @@ return elem; } -static PyObject* -element_remove(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.remove + + subelement: object(subclass_of='&Element_Type') + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) +/*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/ { Py_ssize_t i; - PyObject* element; - if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element)) - return NULL; - if (!self->extra) { /* element has no children, so raise exception */ PyErr_SetString( @@ -1420,14 +1518,14 @@ } for (i = 0; i < self->extra->length; i++) { - if (self->extra->children[i] == element) + if (self->extra->children[i] == subelement) break; - if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1) + if (PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ) == 1) break; } if (i == self->extra->length) { - /* element is not in children, so raise exception */ + /* subelement is not in children, so raise exception */ PyErr_SetString( PyExc_ValueError, "list.remove(x): x not in list" @@ -1454,16 +1552,22 @@ return PyUnicode_FromFormat("", self); } -static PyObject* -element_set(ElementObject* self, PyObject* args) +/*[clinic input] +_elementtree.Element.set + + key: object + value: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_Element_set_impl(ElementObject *self, PyObject *key, + PyObject *value) +/*[clinic end generated code: output=fb938806be3c5656 input=1efe90f7d82b3fe9]*/ { PyObject* attrib; - PyObject* key; - PyObject* value; - if (!PyArg_ParseTuple(args, "OO:set", &key, &value)) - return NULL; - if (!self->extra) { if (create_extra(self, NULL) < 0) return NULL; @@ -1744,43 +1848,6 @@ } } -static PyMethodDef element_methods[] = { - - {"clear", (PyCFunction) element_clearmethod, METH_VARARGS}, - - {"get", (PyCFunction) element_get, METH_VARARGS | METH_KEYWORDS}, - {"set", (PyCFunction) element_set, METH_VARARGS}, - - {"find", (PyCFunction) element_find, METH_VARARGS | METH_KEYWORDS}, - {"findtext", (PyCFunction) element_findtext, METH_VARARGS | METH_KEYWORDS}, - {"findall", (PyCFunction) element_findall, METH_VARARGS | METH_KEYWORDS}, - - {"append", (PyCFunction) element_append, METH_VARARGS}, - {"extend", (PyCFunction) element_extend, METH_VARARGS}, - {"insert", (PyCFunction) element_insert, METH_VARARGS}, - {"remove", (PyCFunction) element_remove, METH_VARARGS}, - - {"iter", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS}, - {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, - {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS | METH_KEYWORDS}, - - {"getiterator", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS}, - {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, - - {"items", (PyCFunction) element_items, METH_VARARGS}, - {"keys", (PyCFunction) element_keys, METH_VARARGS}, - - {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, - - {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, - {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, - {"__sizeof__", element_sizeof, METH_NOARGS}, - {"__getstate__", (PyCFunction)element_getstate, METH_NOARGS}, - {"__setstate__", (PyCFunction)element_setstate, METH_O}, - - {NULL, NULL} -}; - static PyObject* element_getattro(ElementObject* self, PyObject* nameobj) { @@ -1877,54 +1944,6 @@ 0, }; -static PyMappingMethods element_as_mapping = { - (lenfunc) element_length, - (binaryfunc) element_subscr, - (objobjargproc) element_ass_subscr, -}; - -static PyTypeObject Element_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.Element", sizeof(ElementObject), 0, - /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)element_repr, /* tp_repr */ - 0, /* tp_as_number */ - &element_as_sequence, /* tp_as_sequence */ - &element_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc)element_getattro, /* tp_getattro */ - (setattrofunc)element_setattro, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)element_gc_traverse, /* tp_traverse */ - (inquiry)element_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - element_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 */ - (initproc)element_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - element_new, /* tp_new */ - 0, /* tp_free */ -}; - /******************************* Element iterator ****************************/ /* ElementIterObject represents the iteration state over an XML element in @@ -2264,23 +2283,24 @@ return (PyObject *)t; } +/*[clinic input] +_elementtree.TreeBuilder.__init__ + + element_factory: object = NULL + +[clinic start generated code]*/ + static int -treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds) +_elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, + PyObject *element_factory) +/*[clinic end generated code: output=91cfa7558970ee96 input=1b424eeefc35249c]*/ { - static char *kwlist[] = {"element_factory", 0}; - PyObject *element_factory = NULL; - TreeBuilderObject *self_tb = (TreeBuilderObject *)self; PyObject *tmp; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:TreeBuilder", kwlist, - &element_factory)) { - return -1; - } - if (element_factory) { Py_INCREF(element_factory); - tmp = self_tb->element_factory; - self_tb->element_factory = element_factory; + tmp = self->element_factory; + self->element_factory = element_factory; Py_XDECREF(tmp); } @@ -2600,23 +2620,33 @@ /* -------------------------------------------------------------------- */ /* methods (in alphabetical order) */ -static PyObject* -treebuilder_data(TreeBuilderObject* self, PyObject* args) +/*[clinic input] +_elementtree.TreeBuilder.data + + data: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_data(TreeBuilderObject *self, PyObject *data) +/*[clinic end generated code: output=69144c7100795bb2 input=a0540c532b284d29]*/ { - PyObject* data; - if (!PyArg_ParseTuple(args, "O:data", &data)) - return NULL; - return treebuilder_handle_data(self, data); } -static PyObject* -treebuilder_end(TreeBuilderObject* self, PyObject* args) +/*[clinic input] +_elementtree.TreeBuilder.end + + tag: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_end(TreeBuilderObject *self, PyObject *tag) +/*[clinic end generated code: output=9a98727cc691cd9d input=22dc3674236f5745]*/ { - PyObject* tag; - if (!PyArg_ParseTuple(args, "O:end", &tag)) - return NULL; - return treebuilder_handle_end(self, tag); } @@ -2636,31 +2666,1089 @@ return res; } -static PyObject* -treebuilder_close(TreeBuilderObject* self, PyObject* args) +/*[clinic input] +_elementtree.TreeBuilder.close + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_close_impl(TreeBuilderObject *self) +/*[clinic end generated code: output=b441fee3202f61ee input=f7c9c65dc718de14]*/ { - if (!PyArg_ParseTuple(args, ":close")) - return NULL; - return treebuilder_done(self); } -static PyObject* -treebuilder_start(TreeBuilderObject* self, PyObject* args) +/*[clinic input] +_elementtree.TreeBuilder.start + + tag: object + attrs: object = None + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, + PyObject *attrs) +/*[clinic end generated code: output=e7e9dc2861349411 input=95fc1758dd042c65]*/ +{ + return treebuilder_handle_start(self, tag, attrs); +} + +/* ==================================================================== */ +/* the expat interface */ + +#include "expat.h" +#include "pyexpat.h" + +/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be + * cached globally without being in per-module state. + */ +static struct PyExpat_CAPI *expat_capi; +#define EXPAT(func) (expat_capi->func) + +static XML_Memory_Handling_Suite ExpatMemoryHandler = { + PyObject_Malloc, PyObject_Realloc, PyObject_Free}; + +typedef struct { + PyObject_HEAD + + XML_Parser parser; + + PyObject *target; + PyObject *entity; + + PyObject *names; + + PyObject *handle_start; + PyObject *handle_data; + PyObject *handle_end; + + PyObject *handle_comment; + PyObject *handle_pi; + PyObject *handle_doctype; + + PyObject *handle_close; + +} XMLParserObject; + +#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type) + +/* helpers */ + +LOCAL(PyObject*) +makeuniversal(XMLParserObject* self, const char* string) +{ + /* convert a UTF-8 tag/attribute name from the expat parser + to a universal name string */ + + Py_ssize_t size = (Py_ssize_t) strlen(string); + PyObject* key; + PyObject* value; + + /* look the 'raw' name up in the names dictionary */ + key = PyBytes_FromStringAndSize(string, size); + if (!key) + return NULL; + + value = PyDict_GetItem(self->names, key); + + if (value) { + Py_INCREF(value); + } else { + /* new name. convert to universal name, and decode as + necessary */ + + PyObject* tag; + char* p; + Py_ssize_t i; + + /* look for namespace separator */ + for (i = 0; i < size; i++) + if (string[i] == '}') + break; + if (i != size) { + /* convert to universal name */ + tag = PyBytes_FromStringAndSize(NULL, size+1); + if (tag == NULL) { + Py_DECREF(key); + return NULL; + } + p = PyBytes_AS_STRING(tag); + p[0] = '{'; + memcpy(p+1, string, size); + size++; + } else { + /* plain name; use key as tag */ + Py_INCREF(key); + tag = key; + } + + /* decode universal name */ + p = PyBytes_AS_STRING(tag); + value = PyUnicode_DecodeUTF8(p, size, "strict"); + Py_DECREF(tag); + if (!value) { + Py_DECREF(key); + return NULL; + } + + /* add to names dictionary */ + if (PyDict_SetItem(self->names, key, value) < 0) { + Py_DECREF(key); + Py_DECREF(value); + return NULL; + } + } + + Py_DECREF(key); + return value; +} + +/* Set the ParseError exception with the given parameters. + * If message is not NULL, it's used as the error string. Otherwise, the + * message string is the default for the given error_code. +*/ +static void +expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column, + const char *message) +{ + PyObject *errmsg, *error, *position, *code; + elementtreestate *st = ET_STATE_GLOBAL; + + errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd", + message ? message : EXPAT(ErrorString)(error_code), + line, column); + if (errmsg == NULL) + return; + + error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg); + Py_DECREF(errmsg); + if (!error) + return; + + /* Add code and position attributes */ + code = PyLong_FromLong((long)error_code); + if (!code) { + Py_DECREF(error); + return; + } + if (PyObject_SetAttrString(error, "code", code) == -1) { + Py_DECREF(error); + Py_DECREF(code); + return; + } + Py_DECREF(code); + + position = Py_BuildValue("(nn)", line, column); + if (!position) { + Py_DECREF(error); + return; + } + if (PyObject_SetAttrString(error, "position", position) == -1) { + Py_DECREF(error); + Py_DECREF(position); + return; + } + Py_DECREF(position); + + PyErr_SetObject(st->parseerror_obj, error); + Py_DECREF(error); +} + +/* -------------------------------------------------------------------- */ +/* handlers */ + +static void +expat_default_handler(XMLParserObject* self, const XML_Char* data_in, + int data_len) +{ + PyObject* key; + PyObject* value; + PyObject* res; + + if (data_len < 2 || data_in[0] != '&') + return; + + if (PyErr_Occurred()) + return; + + key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict"); + if (!key) + return; + + value = PyDict_GetItem(self->entity, key); + + if (value) { + if (TreeBuilder_CheckExact(self->target)) + res = treebuilder_handle_data( + (TreeBuilderObject*) self->target, value + ); + else if (self->handle_data) + res = PyObject_CallFunction(self->handle_data, "O", value); + else + res = NULL; + Py_XDECREF(res); + } else if (!PyErr_Occurred()) { + /* Report the first error, not the last */ + char message[128] = "undefined entity "; + strncat(message, data_in, data_len < 100?data_len:100); + expat_set_error( + XML_ERROR_UNDEFINED_ENTITY, + EXPAT(GetErrorLineNumber)(self->parser), + EXPAT(GetErrorColumnNumber)(self->parser), + message + ); + } + + Py_DECREF(key); +} + +static void +expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, + const XML_Char **attrib_in) +{ + PyObject* res; + PyObject* tag; + PyObject* attrib; + int ok; + + if (PyErr_Occurred()) + return; + + /* tag name */ + tag = makeuniversal(self, tag_in); + if (!tag) + return; /* parser will look for errors */ + + /* attributes */ + if (attrib_in[0]) { + attrib = PyDict_New(); + if (!attrib) + return; + while (attrib_in[0] && attrib_in[1]) { + PyObject* key = makeuniversal(self, attrib_in[0]); + PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict"); + if (!key || !value) { + Py_XDECREF(value); + Py_XDECREF(key); + Py_DECREF(attrib); + return; + } + ok = PyDict_SetItem(attrib, key, value); + Py_DECREF(value); + Py_DECREF(key); + if (ok < 0) { + Py_DECREF(attrib); + return; + } + attrib_in += 2; + } + } else { + /* Pass an empty dictionary on */ + attrib = PyDict_New(); + if (!attrib) + return; + } + + if (TreeBuilder_CheckExact(self->target)) { + /* shortcut */ + res = treebuilder_handle_start((TreeBuilderObject*) self->target, + tag, attrib); + } + else if (self->handle_start) { + res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); + } else + res = NULL; + + Py_DECREF(tag); + Py_DECREF(attrib); + + Py_XDECREF(res); +} + +static void +expat_data_handler(XMLParserObject* self, const XML_Char* data_in, + int data_len) +{ + PyObject* data; + PyObject* res; + + if (PyErr_Occurred()) + return; + + data = PyUnicode_DecodeUTF8(data_in, data_len, "strict"); + if (!data) + return; /* parser will look for errors */ + + if (TreeBuilder_CheckExact(self->target)) + /* shortcut */ + res = treebuilder_handle_data((TreeBuilderObject*) self->target, data); + else if (self->handle_data) + res = PyObject_CallFunction(self->handle_data, "O", data); + else + res = NULL; + + Py_DECREF(data); + + Py_XDECREF(res); +} + +static void +expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) { PyObject* tag; - PyObject* attrib = Py_None; - if (!PyArg_ParseTuple(args, "O|O:start", &tag, &attrib)) + PyObject* res = NULL; + + if (PyErr_Occurred()) + return; + + if (TreeBuilder_CheckExact(self->target)) + /* shortcut */ + /* the standard tree builder doesn't look at the end tag */ + res = treebuilder_handle_end( + (TreeBuilderObject*) self->target, Py_None + ); + else if (self->handle_end) { + tag = makeuniversal(self, tag_in); + if (tag) { + res = PyObject_CallFunction(self->handle_end, "O", tag); + Py_DECREF(tag); + } + } + + Py_XDECREF(res); +} + +static void +expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, + const XML_Char *uri) +{ + PyObject* sprefix = NULL; + PyObject* suri = NULL; + + if (PyErr_Occurred()) + return; + + if (uri) + suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict"); + else + suri = PyUnicode_FromString(""); + if (!suri) + return; + + if (prefix) + sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict"); + else + sprefix = PyUnicode_FromString(""); + if (!sprefix) { + Py_DECREF(suri); + return; + } + + treebuilder_handle_namespace( + (TreeBuilderObject*) self->target, 1, sprefix, suri + ); + + Py_DECREF(sprefix); + Py_DECREF(suri); +} + +static void +expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) +{ + if (PyErr_Occurred()) + return; + + treebuilder_handle_namespace( + (TreeBuilderObject*) self->target, 0, NULL, NULL + ); +} + +static void +expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in) +{ + PyObject* comment; + PyObject* res; + + if (PyErr_Occurred()) + return; + + if (self->handle_comment) { + comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict"); + if (comment) { + res = PyObject_CallFunction(self->handle_comment, "O", comment); + Py_XDECREF(res); + Py_DECREF(comment); + } + } +} + +static void +expat_start_doctype_handler(XMLParserObject *self, + const XML_Char *doctype_name, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset) +{ + PyObject *self_pyobj = (PyObject *)self; + PyObject *doctype_name_obj, *sysid_obj, *pubid_obj; + PyObject *parser_doctype = NULL; + PyObject *res = NULL; + + if (PyErr_Occurred()) + return; + + doctype_name_obj = makeuniversal(self, doctype_name); + if (!doctype_name_obj) + return; + + if (sysid) { + sysid_obj = makeuniversal(self, sysid); + if (!sysid_obj) { + Py_DECREF(doctype_name_obj); + return; + } + } else { + Py_INCREF(Py_None); + sysid_obj = Py_None; + } + + if (pubid) { + pubid_obj = makeuniversal(self, pubid); + if (!pubid_obj) { + Py_DECREF(doctype_name_obj); + Py_DECREF(sysid_obj); + return; + } + } else { + Py_INCREF(Py_None); + pubid_obj = Py_None; + } + + /* If the target has a handler for doctype, call it. */ + if (self->handle_doctype) { + res = PyObject_CallFunction(self->handle_doctype, "OOO", + doctype_name_obj, pubid_obj, sysid_obj); + Py_CLEAR(res); + } + + /* Now see if the parser itself has a doctype method. If yes and it's + * a subclass, call it but warn about deprecation. If it's not a subclass + * (i.e. vanilla XMLParser), do nothing. + */ + parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype"); + if (parser_doctype) { + if (!XMLParser_CheckExact(self_pyobj)) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "This method of XMLParser is deprecated. Define" + " doctype() method on the TreeBuilder target.", + 1) < 0) { + goto clear; + } + res = PyObject_CallFunction(parser_doctype, "OOO", + doctype_name_obj, pubid_obj, sysid_obj); + Py_CLEAR(res); + } + } + +clear: + Py_XDECREF(parser_doctype); + Py_DECREF(doctype_name_obj); + Py_DECREF(pubid_obj); + Py_DECREF(sysid_obj); +} + +static void +expat_pi_handler(XMLParserObject* self, const XML_Char* target_in, + const XML_Char* data_in) +{ + PyObject* target; + PyObject* data; + PyObject* res; + + if (PyErr_Occurred()) + return; + + if (self->handle_pi) { + target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); + data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); + if (target && data) { + res = PyObject_CallFunction(self->handle_pi, "OO", target, data); + Py_XDECREF(res); + Py_DECREF(data); + Py_DECREF(target); + } else { + Py_XDECREF(data); + Py_XDECREF(target); + } + } +} + +/* -------------------------------------------------------------------- */ + +static PyObject * +xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0); + if (self) { + self->parser = NULL; + self->target = self->entity = self->names = NULL; + self->handle_start = self->handle_data = self->handle_end = NULL; + self->handle_comment = self->handle_pi = self->handle_close = NULL; + self->handle_doctype = NULL; + } + return (PyObject *)self; +} + +/*[clinic input] +_elementtree.XMLParser.__init__ + + html: object = NULL + target: object = NULL + encoding: str(nullable=True) = NULL + +[clinic start generated code]*/ + +static int +_elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html, + PyObject *target, const char *encoding) +/*[clinic end generated code: output=d6a16c63dda54441 input=a870da39c80d7d68]*/ +{ + self->entity = PyDict_New(); + if (!self->entity) + return -1; + + self->names = PyDict_New(); + if (!self->names) { + Py_CLEAR(self->entity); + return -1; + } + + self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); + if (!self->parser) { + Py_CLEAR(self->entity); + Py_CLEAR(self->names); + PyErr_NoMemory(); + return -1; + } + + if (target) { + Py_INCREF(target); + } else { + target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); + if (!target) { + Py_CLEAR(self->entity); + Py_CLEAR(self->names); + EXPAT(ParserFree)(self->parser); + return -1; + } + } + self->target = target; + + self->handle_start = PyObject_GetAttrString(target, "start"); + self->handle_data = PyObject_GetAttrString(target, "data"); + self->handle_end = PyObject_GetAttrString(target, "end"); + self->handle_comment = PyObject_GetAttrString(target, "comment"); + self->handle_pi = PyObject_GetAttrString(target, "pi"); + self->handle_close = PyObject_GetAttrString(target, "close"); + self->handle_doctype = PyObject_GetAttrString(target, "doctype"); + + PyErr_Clear(); + + /* configure parser */ + EXPAT(SetUserData)(self->parser, self); + EXPAT(SetElementHandler)( + self->parser, + (XML_StartElementHandler) expat_start_handler, + (XML_EndElementHandler) expat_end_handler + ); + EXPAT(SetDefaultHandlerExpand)( + self->parser, + (XML_DefaultHandler) expat_default_handler + ); + EXPAT(SetCharacterDataHandler)( + self->parser, + (XML_CharacterDataHandler) expat_data_handler + ); + if (self->handle_comment) + EXPAT(SetCommentHandler)( + self->parser, + (XML_CommentHandler) expat_comment_handler + ); + if (self->handle_pi) + EXPAT(SetProcessingInstructionHandler)( + self->parser, + (XML_ProcessingInstructionHandler) expat_pi_handler + ); + EXPAT(SetStartDoctypeDeclHandler)( + self->parser, + (XML_StartDoctypeDeclHandler) expat_start_doctype_handler + ); + EXPAT(SetUnknownEncodingHandler)( + self->parser, + EXPAT(DefaultUnknownEncodingHandler), NULL + ); + + return 0; +} + +static int +xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->handle_close); + Py_VISIT(self->handle_pi); + Py_VISIT(self->handle_comment); + Py_VISIT(self->handle_end); + Py_VISIT(self->handle_data); + Py_VISIT(self->handle_start); + + Py_VISIT(self->target); + Py_VISIT(self->entity); + Py_VISIT(self->names); + + return 0; +} + +static int +xmlparser_gc_clear(XMLParserObject *self) +{ + EXPAT(ParserFree)(self->parser); + + Py_CLEAR(self->handle_close); + Py_CLEAR(self->handle_pi); + Py_CLEAR(self->handle_comment); + Py_CLEAR(self->handle_end); + Py_CLEAR(self->handle_data); + Py_CLEAR(self->handle_start); + Py_CLEAR(self->handle_doctype); + + Py_CLEAR(self->target); + Py_CLEAR(self->entity); + Py_CLEAR(self->names); + + return 0; +} + +static void +xmlparser_dealloc(XMLParserObject* self) +{ + PyObject_GC_UnTrack(self); + xmlparser_gc_clear(self); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +LOCAL(PyObject*) +expat_parse(XMLParserObject* self, const char* data, int data_len, int final) +{ + int ok; + + assert(!PyErr_Occurred()); + ok = EXPAT(Parse)(self->parser, data, data_len, final); + + if (PyErr_Occurred()) return NULL; - return treebuilder_handle_start(self, tag, attrib); + if (!ok) { + expat_set_error( + EXPAT(GetErrorCode)(self->parser), + EXPAT(GetErrorLineNumber)(self->parser), + EXPAT(GetErrorColumnNumber)(self->parser), + NULL + ); + return NULL; + } + + Py_RETURN_NONE; } +/*[clinic input] +_elementtree.XMLParser.close + +[clinic start generated code]*/ + +static PyObject * +_elementtree_XMLParser_close_impl(XMLParserObject *self) +/*[clinic end generated code: output=d68d375dd23bc7fb input=ca7909ca78c3abfe]*/ +{ + /* end feeding data to parser */ + + PyObject* res; + res = expat_parse(self, "", 0, 1); + if (!res) + return NULL; + + if (TreeBuilder_CheckExact(self->target)) { + Py_DECREF(res); + return treebuilder_done((TreeBuilderObject*) self->target); + } + else if (self->handle_close) { + Py_DECREF(res); + return PyObject_CallFunction(self->handle_close, ""); + } + else { + return res; + } +} + +/*[clinic input] +_elementtree.XMLParser.feed + + data: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data) +/*[clinic end generated code: output=e42b6a78eec7446d input=fe231b6b8de3ce1f]*/ +{ + /* feed data to parser */ + + if (PyUnicode_Check(data)) { + Py_ssize_t data_len; + const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len); + if (data_ptr == NULL) + return NULL; + if (data_len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); + return NULL; + } + /* Explicitly set UTF-8 encoding. Return code ignored. */ + (void)EXPAT(SetEncoding)(self->parser, "utf-8"); + return expat_parse(self, data_ptr, (int)data_len, 0); + } + else { + Py_buffer view; + PyObject *res; + if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0) + return NULL; + if (view.len > INT_MAX) { + PyBuffer_Release(&view); + PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); + return NULL; + } + res = expat_parse(self, view.buf, (int)view.len, 0); + PyBuffer_Release(&view); + return res; + } +} + +/*[clinic input] +_elementtree.XMLParser._parse_whole + + file: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file) +/*[clinic end generated code: output=f797197bb818dda3 input=19ecc893b6f3e752]*/ +{ + /* (internal) parse the whole input, until end of stream */ + PyObject* reader; + PyObject* buffer; + PyObject* temp; + PyObject* res; + + reader = PyObject_GetAttrString(file, "read"); + if (!reader) + return NULL; + + /* read from open file object */ + for (;;) { + + buffer = PyObject_CallFunction(reader, "i", 64*1024); + + if (!buffer) { + /* read failed (e.g. due to KeyboardInterrupt) */ + Py_DECREF(reader); + return NULL; + } + + if (PyUnicode_CheckExact(buffer)) { + /* A unicode object is encoded into bytes using UTF-8 */ + if (PyUnicode_GET_LENGTH(buffer) == 0) { + Py_DECREF(buffer); + break; + } + temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass"); + Py_DECREF(buffer); + if (!temp) { + /* Propagate exception from PyUnicode_AsEncodedString */ + Py_DECREF(reader); + return NULL; + } + buffer = temp; + } + else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) { + Py_DECREF(buffer); + break; + } + + if (PyBytes_GET_SIZE(buffer) > INT_MAX) { + Py_DECREF(buffer); + Py_DECREF(reader); + PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); + return NULL; + } + res = expat_parse( + self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0 + ); + + Py_DECREF(buffer); + + if (!res) { + Py_DECREF(reader); + return NULL; + } + Py_DECREF(res); + + } + + Py_DECREF(reader); + + res = expat_parse(self, "", 0, 1); + + if (res && TreeBuilder_CheckExact(self->target)) { + Py_DECREF(res); + return treebuilder_done((TreeBuilderObject*) self->target); + } + + return res; +} + +/*[clinic input] +_elementtree.XMLParser.doctype + +[clinic start generated code]*/ + +static PyObject * +_elementtree_XMLParser_doctype_impl(XMLParserObject *self) +/*[clinic end generated code: output=d09fdb9c45f3a602 input=20d5e0febf902a2f]*/ +{ + Py_RETURN_NONE; +} + +/*[clinic input] +_elementtree.XMLParser._setevents + + events_queue: object(subclass_of='&PyList_Type') + events_to_report: object = None + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_XMLParser__setevents_impl(XMLParserObject *self, + PyObject *events_queue, + PyObject *events_to_report) +/*[clinic end generated code: output=1440092922b13ed1 input=59db9742910c6174]*/ +{ + /* activate element event reporting */ + Py_ssize_t i, seqlen; + TreeBuilderObject *target; + PyObject *events_seq; + + if (!TreeBuilder_CheckExact(self->target)) { + PyErr_SetString( + PyExc_TypeError, + "event handling only supported for ElementTree.TreeBuilder " + "targets" + ); + return NULL; + } + + target = (TreeBuilderObject*) self->target; + + Py_INCREF(events_queue); + Py_XDECREF(target->events); + target->events = events_queue; + + /* clear out existing events */ + Py_CLEAR(target->start_event_obj); + Py_CLEAR(target->end_event_obj); + Py_CLEAR(target->start_ns_event_obj); + Py_CLEAR(target->end_ns_event_obj); + + if (events_to_report == Py_None) { + /* default is "end" only */ + target->end_event_obj = PyUnicode_FromString("end"); + Py_RETURN_NONE; + } + + if (!(events_seq = PySequence_Fast(events_to_report, + "events must be a sequence"))) { + return NULL; + } + + seqlen = PySequence_Size(events_seq); + for (i = 0; i < seqlen; ++i) { + PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i); + char *event_name = NULL; + if (PyUnicode_Check(event_name_obj)) { + event_name = _PyUnicode_AsString(event_name_obj); + } else if (PyBytes_Check(event_name_obj)) { + event_name = PyBytes_AS_STRING(event_name_obj); + } + + if (event_name == NULL) { + Py_DECREF(events_seq); + PyErr_Format(PyExc_ValueError, "invalid events sequence"); + return NULL; + } else if (strcmp(event_name, "start") == 0) { + Py_INCREF(event_name_obj); + target->start_event_obj = event_name_obj; + } else if (strcmp(event_name, "end") == 0) { + Py_INCREF(event_name_obj); + Py_XDECREF(target->end_event_obj); + target->end_event_obj = event_name_obj; + } else if (strcmp(event_name, "start-ns") == 0) { + Py_INCREF(event_name_obj); + Py_XDECREF(target->start_ns_event_obj); + target->start_ns_event_obj = event_name_obj; + EXPAT(SetNamespaceDeclHandler)( + self->parser, + (XML_StartNamespaceDeclHandler) expat_start_ns_handler, + (XML_EndNamespaceDeclHandler) expat_end_ns_handler + ); + } else if (strcmp(event_name, "end-ns") == 0) { + Py_INCREF(event_name_obj); + Py_XDECREF(target->end_ns_event_obj); + target->end_ns_event_obj = event_name_obj; + EXPAT(SetNamespaceDeclHandler)( + self->parser, + (XML_StartNamespaceDeclHandler) expat_start_ns_handler, + (XML_EndNamespaceDeclHandler) expat_end_ns_handler + ); + } else { + Py_DECREF(events_seq); + PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name); + return NULL; + } + } + + Py_DECREF(events_seq); + Py_RETURN_NONE; +} + +static PyObject* +xmlparser_getattro(XMLParserObject* self, PyObject* nameobj) +{ + if (PyUnicode_Check(nameobj)) { + PyObject* res; + if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0) + res = self->entity; + else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0) + res = self->target; + else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) { + return PyUnicode_FromFormat( + "Expat %d.%d.%d", XML_MAJOR_VERSION, + XML_MINOR_VERSION, XML_MICRO_VERSION); + } + else + goto generic; + + Py_INCREF(res); + return res; + } + generic: + return PyObject_GenericGetAttr((PyObject*) self, nameobj); +} + +#include "clinic/_elementtree.c.h" + +static PyMethodDef element_methods[] = { + + _ELEMENTTREE_ELEMENT_CLEAR_METHODDEF + + _ELEMENTTREE_ELEMENT_GET_METHODDEF + _ELEMENTTREE_ELEMENT_SET_METHODDEF + + _ELEMENTTREE_ELEMENT_FIND_METHODDEF + _ELEMENTTREE_ELEMENT_FINDTEXT_METHODDEF + _ELEMENTTREE_ELEMENT_FINDALL_METHODDEF + + _ELEMENTTREE_ELEMENT_APPEND_METHODDEF + _ELEMENTTREE_ELEMENT_EXTEND_METHODDEF + _ELEMENTTREE_ELEMENT_INSERT_METHODDEF + _ELEMENTTREE_ELEMENT_REMOVE_METHODDEF + + _ELEMENTTREE_ELEMENT_ITER_METHODDEF + _ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF + _ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF + + {"getiterator", (PyCFunction)_elementtree_Element_iter, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iter__doc__}, + _ELEMENTTREE_ELEMENT_GETCHILDREN_METHODDEF + + _ELEMENTTREE_ELEMENT_ITEMS_METHODDEF + _ELEMENTTREE_ELEMENT_KEYS_METHODDEF + + _ELEMENTTREE_ELEMENT_MAKEELEMENT_METHODDEF + + _ELEMENTTREE_ELEMENT___COPY___METHODDEF + _ELEMENTTREE_ELEMENT___DEEPCOPY___METHODDEF + _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF + _ELEMENTTREE_ELEMENT___GETSTATE___METHODDEF + _ELEMENTTREE_ELEMENT___SETSTATE___METHODDEF + + {NULL, NULL} +}; + +static PyMappingMethods element_as_mapping = { + (lenfunc) element_length, + (binaryfunc) element_subscr, + (objobjargproc) element_ass_subscr, +}; + +static PyTypeObject Element_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "xml.etree.ElementTree.Element", sizeof(ElementObject), 0, + /* methods */ + (destructor)element_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)element_repr, /* tp_repr */ + 0, /* tp_as_number */ + &element_as_sequence, /* tp_as_sequence */ + &element_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + (getattrofunc)element_getattro, /* tp_getattro */ + (setattrofunc)element_setattro, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)element_gc_traverse, /* tp_traverse */ + (inquiry)element_gc_clear, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + element_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 */ + (initproc)element_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + element_new, /* tp_new */ + 0, /* tp_free */ +}; + static PyMethodDef treebuilder_methods[] = { - {"data", (PyCFunction) treebuilder_data, METH_VARARGS}, - {"start", (PyCFunction) treebuilder_start, METH_VARARGS}, - {"end", (PyCFunction) treebuilder_end, METH_VARARGS}, - {"close", (PyCFunction) treebuilder_close, METH_VARARGS}, + _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF + _ELEMENTTREE_TREEBUILDER_START_METHODDEF + _ELEMENTTREE_TREEBUILDER_END_METHODDEF + _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF {NULL, NULL} }; @@ -2700,953 +3788,21 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)treebuilder_init, /* tp_init */ + _elementtree_TreeBuilder___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ treebuilder_new, /* tp_new */ 0, /* tp_free */ }; -/* ==================================================================== */ -/* the expat interface */ - -#include "expat.h" -#include "pyexpat.h" - -/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be - * cached globally without being in per-module state. - */ -static struct PyExpat_CAPI *expat_capi; -#define EXPAT(func) (expat_capi->func) - -static XML_Memory_Handling_Suite ExpatMemoryHandler = { - PyObject_Malloc, PyObject_Realloc, PyObject_Free}; - -typedef struct { - PyObject_HEAD - - XML_Parser parser; - - PyObject *target; - PyObject *entity; - - PyObject *names; - - PyObject *handle_start; - PyObject *handle_data; - PyObject *handle_end; - - PyObject *handle_comment; - PyObject *handle_pi; - PyObject *handle_doctype; - - PyObject *handle_close; - -} XMLParserObject; - -#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type) - -/* helpers */ - -LOCAL(PyObject*) -makeuniversal(XMLParserObject* self, const char* string) -{ - /* convert a UTF-8 tag/attribute name from the expat parser - to a universal name string */ - - Py_ssize_t size = (Py_ssize_t) strlen(string); - PyObject* key; - PyObject* value; - - /* look the 'raw' name up in the names dictionary */ - key = PyBytes_FromStringAndSize(string, size); - if (!key) - return NULL; - - value = PyDict_GetItem(self->names, key); - - if (value) { - Py_INCREF(value); - } else { - /* new name. convert to universal name, and decode as - necessary */ - - PyObject* tag; - char* p; - Py_ssize_t i; - - /* look for namespace separator */ - for (i = 0; i < size; i++) - if (string[i] == '}') - break; - if (i != size) { - /* convert to universal name */ - tag = PyBytes_FromStringAndSize(NULL, size+1); - if (tag == NULL) { - Py_DECREF(key); - return NULL; - } - p = PyBytes_AS_STRING(tag); - p[0] = '{'; - memcpy(p+1, string, size); - size++; - } else { - /* plain name; use key as tag */ - Py_INCREF(key); - tag = key; - } - - /* decode universal name */ - p = PyBytes_AS_STRING(tag); - value = PyUnicode_DecodeUTF8(p, size, "strict"); - Py_DECREF(tag); - if (!value) { - Py_DECREF(key); - return NULL; - } - - /* add to names dictionary */ - if (PyDict_SetItem(self->names, key, value) < 0) { - Py_DECREF(key); - Py_DECREF(value); - return NULL; - } - } - - Py_DECREF(key); - return value; -} - -/* Set the ParseError exception with the given parameters. - * If message is not NULL, it's used as the error string. Otherwise, the - * message string is the default for the given error_code. -*/ -static void -expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column, - const char *message) -{ - PyObject *errmsg, *error, *position, *code; - elementtreestate *st = ET_STATE_GLOBAL; - - errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd", - message ? message : EXPAT(ErrorString)(error_code), - line, column); - if (errmsg == NULL) - return; - - error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg); - Py_DECREF(errmsg); - if (!error) - return; - - /* Add code and position attributes */ - code = PyLong_FromLong((long)error_code); - if (!code) { - Py_DECREF(error); - return; - } - if (PyObject_SetAttrString(error, "code", code) == -1) { - Py_DECREF(error); - Py_DECREF(code); - return; - } - Py_DECREF(code); - - position = Py_BuildValue("(nn)", line, column); - if (!position) { - Py_DECREF(error); - return; - } - if (PyObject_SetAttrString(error, "position", position) == -1) { - Py_DECREF(error); - Py_DECREF(position); - return; - } - Py_DECREF(position); - - PyErr_SetObject(st->parseerror_obj, error); - Py_DECREF(error); -} - -/* -------------------------------------------------------------------- */ -/* handlers */ - -static void -expat_default_handler(XMLParserObject* self, const XML_Char* data_in, - int data_len) -{ - PyObject* key; - PyObject* value; - PyObject* res; - - if (data_len < 2 || data_in[0] != '&') - return; - - if (PyErr_Occurred()) - return; - - key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict"); - if (!key) - return; - - value = PyDict_GetItem(self->entity, key); - - if (value) { - if (TreeBuilder_CheckExact(self->target)) - res = treebuilder_handle_data( - (TreeBuilderObject*) self->target, value - ); - else if (self->handle_data) - res = PyObject_CallFunction(self->handle_data, "O", value); - else - res = NULL; - Py_XDECREF(res); - } else if (!PyErr_Occurred()) { - /* Report the first error, not the last */ - char message[128] = "undefined entity "; - strncat(message, data_in, data_len < 100?data_len:100); - expat_set_error( - XML_ERROR_UNDEFINED_ENTITY, - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), - message - ); - } - - Py_DECREF(key); -} - -static void -expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, - const XML_Char **attrib_in) -{ - PyObject* res; - PyObject* tag; - PyObject* attrib; - int ok; - - if (PyErr_Occurred()) - return; - - /* tag name */ - tag = makeuniversal(self, tag_in); - if (!tag) - return; /* parser will look for errors */ - - /* attributes */ - if (attrib_in[0]) { - attrib = PyDict_New(); - if (!attrib) - return; - while (attrib_in[0] && attrib_in[1]) { - PyObject* key = makeuniversal(self, attrib_in[0]); - PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict"); - if (!key || !value) { - Py_XDECREF(value); - Py_XDECREF(key); - Py_DECREF(attrib); - return; - } - ok = PyDict_SetItem(attrib, key, value); - Py_DECREF(value); - Py_DECREF(key); - if (ok < 0) { - Py_DECREF(attrib); - return; - } - attrib_in += 2; - } - } else { - /* Pass an empty dictionary on */ - attrib = PyDict_New(); - if (!attrib) - return; - } - - if (TreeBuilder_CheckExact(self->target)) { - /* shortcut */ - res = treebuilder_handle_start((TreeBuilderObject*) self->target, - tag, attrib); - } - else if (self->handle_start) { - res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); - } else - res = NULL; - - Py_DECREF(tag); - Py_DECREF(attrib); - - Py_XDECREF(res); -} - -static void -expat_data_handler(XMLParserObject* self, const XML_Char* data_in, - int data_len) -{ - PyObject* data; - PyObject* res; - - if (PyErr_Occurred()) - return; - - data = PyUnicode_DecodeUTF8(data_in, data_len, "strict"); - if (!data) - return; /* parser will look for errors */ - - if (TreeBuilder_CheckExact(self->target)) - /* shortcut */ - res = treebuilder_handle_data((TreeBuilderObject*) self->target, data); - else if (self->handle_data) - res = PyObject_CallFunction(self->handle_data, "O", data); - else - res = NULL; - - Py_DECREF(data); - - Py_XDECREF(res); -} - -static void -expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) -{ - PyObject* tag; - PyObject* res = NULL; - - if (PyErr_Occurred()) - return; - - if (TreeBuilder_CheckExact(self->target)) - /* shortcut */ - /* the standard tree builder doesn't look at the end tag */ - res = treebuilder_handle_end( - (TreeBuilderObject*) self->target, Py_None - ); - else if (self->handle_end) { - tag = makeuniversal(self, tag_in); - if (tag) { - res = PyObject_CallFunction(self->handle_end, "O", tag); - Py_DECREF(tag); - } - } - - Py_XDECREF(res); -} - -static void -expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, - const XML_Char *uri) -{ - PyObject* sprefix = NULL; - PyObject* suri = NULL; - - if (PyErr_Occurred()) - return; - - if (uri) - suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict"); - else - suri = PyUnicode_FromString(""); - if (!suri) - return; - - if (prefix) - sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict"); - else - sprefix = PyUnicode_FromString(""); - if (!sprefix) { - Py_DECREF(suri); - return; - } - - treebuilder_handle_namespace( - (TreeBuilderObject*) self->target, 1, sprefix, suri - ); - - Py_DECREF(sprefix); - Py_DECREF(suri); -} - -static void -expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) -{ - if (PyErr_Occurred()) - return; - - treebuilder_handle_namespace( - (TreeBuilderObject*) self->target, 0, NULL, NULL - ); -} - -static void -expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in) -{ - PyObject* comment; - PyObject* res; - - if (PyErr_Occurred()) - return; - - if (self->handle_comment) { - comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict"); - if (comment) { - res = PyObject_CallFunction(self->handle_comment, "O", comment); - Py_XDECREF(res); - Py_DECREF(comment); - } - } -} - -static void -expat_start_doctype_handler(XMLParserObject *self, - const XML_Char *doctype_name, - const XML_Char *sysid, - const XML_Char *pubid, - int has_internal_subset) -{ - PyObject *self_pyobj = (PyObject *)self; - PyObject *doctype_name_obj, *sysid_obj, *pubid_obj; - PyObject *parser_doctype = NULL; - PyObject *res = NULL; - - if (PyErr_Occurred()) - return; - - doctype_name_obj = makeuniversal(self, doctype_name); - if (!doctype_name_obj) - return; - - if (sysid) { - sysid_obj = makeuniversal(self, sysid); - if (!sysid_obj) { - Py_DECREF(doctype_name_obj); - return; - } - } else { - Py_INCREF(Py_None); - sysid_obj = Py_None; - } - - if (pubid) { - pubid_obj = makeuniversal(self, pubid); - if (!pubid_obj) { - Py_DECREF(doctype_name_obj); - Py_DECREF(sysid_obj); - return; - } - } else { - Py_INCREF(Py_None); - pubid_obj = Py_None; - } - - /* If the target has a handler for doctype, call it. */ - if (self->handle_doctype) { - res = PyObject_CallFunction(self->handle_doctype, "OOO", - doctype_name_obj, pubid_obj, sysid_obj); - Py_CLEAR(res); - } - - /* Now see if the parser itself has a doctype method. If yes and it's - * a subclass, call it but warn about deprecation. If it's not a subclass - * (i.e. vanilla XMLParser), do nothing. - */ - parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype"); - if (parser_doctype) { - if (!XMLParser_CheckExact(self_pyobj)) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "This method of XMLParser is deprecated. Define" - " doctype() method on the TreeBuilder target.", - 1) < 0) { - goto clear; - } - res = PyObject_CallFunction(parser_doctype, "OOO", - doctype_name_obj, pubid_obj, sysid_obj); - Py_CLEAR(res); - } - } - -clear: - Py_XDECREF(parser_doctype); - Py_DECREF(doctype_name_obj); - Py_DECREF(pubid_obj); - Py_DECREF(sysid_obj); -} - -static void -expat_pi_handler(XMLParserObject* self, const XML_Char* target_in, - const XML_Char* data_in) -{ - PyObject* target; - PyObject* data; - PyObject* res; - - if (PyErr_Occurred()) - return; - - if (self->handle_pi) { - target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); - data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); - if (target && data) { - res = PyObject_CallFunction(self->handle_pi, "OO", target, data); - Py_XDECREF(res); - Py_DECREF(data); - Py_DECREF(target); - } else { - Py_XDECREF(data); - Py_XDECREF(target); - } - } -} - -/* -------------------------------------------------------------------- */ - -static PyObject * -xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0); - if (self) { - self->parser = NULL; - self->target = self->entity = self->names = NULL; - self->handle_start = self->handle_data = self->handle_end = NULL; - self->handle_comment = self->handle_pi = self->handle_close = NULL; - self->handle_doctype = NULL; - } - return (PyObject *)self; -} - -static int -xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - XMLParserObject *self_xp = (XMLParserObject *)self; - PyObject *target = NULL, *html = NULL; - char *encoding = NULL; - static char *kwlist[] = {"html", "target", "encoding", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOz:XMLParser", kwlist, - &html, &target, &encoding)) { - return -1; - } - - self_xp->entity = PyDict_New(); - if (!self_xp->entity) - return -1; - - self_xp->names = PyDict_New(); - if (!self_xp->names) { - Py_CLEAR(self_xp->entity); - return -1; - } - - self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); - if (!self_xp->parser) { - Py_CLEAR(self_xp->entity); - Py_CLEAR(self_xp->names); - PyErr_NoMemory(); - return -1; - } - - if (target) { - Py_INCREF(target); - } else { - target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); - if (!target) { - Py_CLEAR(self_xp->entity); - Py_CLEAR(self_xp->names); - EXPAT(ParserFree)(self_xp->parser); - return -1; - } - } - self_xp->target = target; - - self_xp->handle_start = PyObject_GetAttrString(target, "start"); - self_xp->handle_data = PyObject_GetAttrString(target, "data"); - self_xp->handle_end = PyObject_GetAttrString(target, "end"); - self_xp->handle_comment = PyObject_GetAttrString(target, "comment"); - self_xp->handle_pi = PyObject_GetAttrString(target, "pi"); - self_xp->handle_close = PyObject_GetAttrString(target, "close"); - self_xp->handle_doctype = PyObject_GetAttrString(target, "doctype"); - - PyErr_Clear(); - - /* configure parser */ - EXPAT(SetUserData)(self_xp->parser, self_xp); - EXPAT(SetElementHandler)( - self_xp->parser, - (XML_StartElementHandler) expat_start_handler, - (XML_EndElementHandler) expat_end_handler - ); - EXPAT(SetDefaultHandlerExpand)( - self_xp->parser, - (XML_DefaultHandler) expat_default_handler - ); - EXPAT(SetCharacterDataHandler)( - self_xp->parser, - (XML_CharacterDataHandler) expat_data_handler - ); - if (self_xp->handle_comment) - EXPAT(SetCommentHandler)( - self_xp->parser, - (XML_CommentHandler) expat_comment_handler - ); - if (self_xp->handle_pi) - EXPAT(SetProcessingInstructionHandler)( - self_xp->parser, - (XML_ProcessingInstructionHandler) expat_pi_handler - ); - EXPAT(SetStartDoctypeDeclHandler)( - self_xp->parser, - (XML_StartDoctypeDeclHandler) expat_start_doctype_handler - ); - EXPAT(SetUnknownEncodingHandler)( - self_xp->parser, - EXPAT(DefaultUnknownEncodingHandler), NULL - ); - - return 0; -} - -static int -xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) -{ - Py_VISIT(self->handle_close); - Py_VISIT(self->handle_pi); - Py_VISIT(self->handle_comment); - Py_VISIT(self->handle_end); - Py_VISIT(self->handle_data); - Py_VISIT(self->handle_start); - - Py_VISIT(self->target); - Py_VISIT(self->entity); - Py_VISIT(self->names); - - return 0; -} - -static int -xmlparser_gc_clear(XMLParserObject *self) -{ - EXPAT(ParserFree)(self->parser); - - Py_CLEAR(self->handle_close); - Py_CLEAR(self->handle_pi); - Py_CLEAR(self->handle_comment); - Py_CLEAR(self->handle_end); - Py_CLEAR(self->handle_data); - Py_CLEAR(self->handle_start); - Py_CLEAR(self->handle_doctype); - - Py_CLEAR(self->target); - Py_CLEAR(self->entity); - Py_CLEAR(self->names); - - return 0; -} - -static void -xmlparser_dealloc(XMLParserObject* self) -{ - PyObject_GC_UnTrack(self); - xmlparser_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -LOCAL(PyObject*) -expat_parse(XMLParserObject* self, const char* data, int data_len, int final) -{ - int ok; - - assert(!PyErr_Occurred()); - ok = EXPAT(Parse)(self->parser, data, data_len, final); - - if (PyErr_Occurred()) - return NULL; - - if (!ok) { - expat_set_error( - EXPAT(GetErrorCode)(self->parser), - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), - NULL - ); - return NULL; - } - - Py_RETURN_NONE; -} - -static PyObject* -xmlparser_close(XMLParserObject* self, PyObject* args) -{ - /* end feeding data to parser */ - - PyObject* res; - if (!PyArg_ParseTuple(args, ":close")) - return NULL; - - res = expat_parse(self, "", 0, 1); - if (!res) - return NULL; - - if (TreeBuilder_CheckExact(self->target)) { - Py_DECREF(res); - return treebuilder_done((TreeBuilderObject*) self->target); - } - else if (self->handle_close) { - Py_DECREF(res); - return PyObject_CallFunction(self->handle_close, ""); - } - else { - return res; - } -} - -static PyObject* -xmlparser_feed(XMLParserObject* self, PyObject* arg) -{ - /* feed data to parser */ - - if (PyUnicode_Check(arg)) { - Py_ssize_t data_len; - const char *data = PyUnicode_AsUTF8AndSize(arg, &data_len); - if (data == NULL) - return NULL; - if (data_len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - /* Explicitly set UTF-8 encoding. Return code ignored. */ - (void)EXPAT(SetEncoding)(self->parser, "utf-8"); - return expat_parse(self, data, (int)data_len, 0); - } - else { - Py_buffer view; - PyObject *res; - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0) - return NULL; - if (view.len > INT_MAX) { - PyBuffer_Release(&view); - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - res = expat_parse(self, view.buf, (int)view.len, 0); - PyBuffer_Release(&view); - return res; - } -} - -static PyObject* -xmlparser_parse_whole(XMLParserObject* self, PyObject* args) -{ - /* (internal) parse the whole input, until end of stream */ - PyObject* reader; - PyObject* buffer; - PyObject* temp; - PyObject* res; - - PyObject* fileobj; - if (!PyArg_ParseTuple(args, "O:_parse", &fileobj)) - return NULL; - - reader = PyObject_GetAttrString(fileobj, "read"); - if (!reader) - return NULL; - - /* read from open file object */ - for (;;) { - - buffer = PyObject_CallFunction(reader, "i", 64*1024); - - if (!buffer) { - /* read failed (e.g. due to KeyboardInterrupt) */ - Py_DECREF(reader); - return NULL; - } - - if (PyUnicode_CheckExact(buffer)) { - /* A unicode object is encoded into bytes using UTF-8 */ - if (PyUnicode_GET_LENGTH(buffer) == 0) { - Py_DECREF(buffer); - break; - } - temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass"); - Py_DECREF(buffer); - if (!temp) { - /* Propagate exception from PyUnicode_AsEncodedString */ - Py_DECREF(reader); - return NULL; - } - buffer = temp; - } - else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) { - Py_DECREF(buffer); - break; - } - - if (PyBytes_GET_SIZE(buffer) > INT_MAX) { - Py_DECREF(buffer); - Py_DECREF(reader); - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - res = expat_parse( - self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0 - ); - - Py_DECREF(buffer); - - if (!res) { - Py_DECREF(reader); - return NULL; - } - Py_DECREF(res); - - } - - Py_DECREF(reader); - - res = expat_parse(self, "", 0, 1); - - if (res && TreeBuilder_CheckExact(self->target)) { - Py_DECREF(res); - return treebuilder_done((TreeBuilderObject*) self->target); - } - - return res; -} - -static PyObject* -xmlparser_doctype(XMLParserObject *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyObject* -xmlparser_setevents(XMLParserObject *self, PyObject* args) -{ - /* activate element event reporting */ - Py_ssize_t i, seqlen; - TreeBuilderObject *target; - - PyObject *events_queue; - PyObject *events_to_report = Py_None; - PyObject *events_seq; - if (!PyArg_ParseTuple(args, "O!|O:_setevents", &PyList_Type, &events_queue, - &events_to_report)) - return NULL; - - if (!TreeBuilder_CheckExact(self->target)) { - PyErr_SetString( - PyExc_TypeError, - "event handling only supported for ElementTree.TreeBuilder " - "targets" - ); - return NULL; - } - - target = (TreeBuilderObject*) self->target; - - Py_INCREF(events_queue); - Py_XDECREF(target->events); - target->events = events_queue; - - /* clear out existing events */ - Py_CLEAR(target->start_event_obj); - Py_CLEAR(target->end_event_obj); - Py_CLEAR(target->start_ns_event_obj); - Py_CLEAR(target->end_ns_event_obj); - - if (events_to_report == Py_None) { - /* default is "end" only */ - target->end_event_obj = PyUnicode_FromString("end"); - Py_RETURN_NONE; - } - - if (!(events_seq = PySequence_Fast(events_to_report, - "events must be a sequence"))) { - return NULL; - } - - seqlen = PySequence_Size(events_seq); - for (i = 0; i < seqlen; ++i) { - PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i); - char *event_name = NULL; - if (PyUnicode_Check(event_name_obj)) { - event_name = _PyUnicode_AsString(event_name_obj); - } else if (PyBytes_Check(event_name_obj)) { - event_name = PyBytes_AS_STRING(event_name_obj); - } - - if (event_name == NULL) { - Py_DECREF(events_seq); - PyErr_Format(PyExc_ValueError, "invalid events sequence"); - return NULL; - } else if (strcmp(event_name, "start") == 0) { - Py_INCREF(event_name_obj); - target->start_event_obj = event_name_obj; - } else if (strcmp(event_name, "end") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->end_event_obj); - target->end_event_obj = event_name_obj; - } else if (strcmp(event_name, "start-ns") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->start_ns_event_obj); - target->start_ns_event_obj = event_name_obj; - EXPAT(SetNamespaceDeclHandler)( - self->parser, - (XML_StartNamespaceDeclHandler) expat_start_ns_handler, - (XML_EndNamespaceDeclHandler) expat_end_ns_handler - ); - } else if (strcmp(event_name, "end-ns") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->end_ns_event_obj); - target->end_ns_event_obj = event_name_obj; - EXPAT(SetNamespaceDeclHandler)( - self->parser, - (XML_StartNamespaceDeclHandler) expat_start_ns_handler, - (XML_EndNamespaceDeclHandler) expat_end_ns_handler - ); - } else { - Py_DECREF(events_seq); - PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name); - return NULL; - } - } - - Py_DECREF(events_seq); - Py_RETURN_NONE; -} - static PyMethodDef xmlparser_methods[] = { - {"feed", (PyCFunction) xmlparser_feed, METH_O}, - {"close", (PyCFunction) xmlparser_close, METH_VARARGS}, - {"_parse_whole", (PyCFunction) xmlparser_parse_whole, METH_VARARGS}, - {"_setevents", (PyCFunction) xmlparser_setevents, METH_VARARGS}, - {"doctype", (PyCFunction) xmlparser_doctype, METH_VARARGS}, + _ELEMENTTREE_XMLPARSER_FEED_METHODDEF + _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF + _ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF + _ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF + _ELEMENTTREE_XMLPARSER_DOCTYPE_METHODDEF {NULL, NULL} }; -static PyObject* -xmlparser_getattro(XMLParserObject* self, PyObject* nameobj) -{ - if (PyUnicode_Check(nameobj)) { - PyObject* res; - if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0) - res = self->entity; - else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0) - res = self->target; - else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) { - return PyUnicode_FromFormat( - "Expat %d.%d.%d", XML_MAJOR_VERSION, - XML_MINOR_VERSION, XML_MICRO_VERSION); - } - else - goto generic; - - Py_INCREF(res); - return res; - } - generic: - return PyObject_GenericGetAttr((PyObject*) self, nameobj); -} - static PyTypeObject XMLParser_Type = { PyVarObject_HEAD_INIT(NULL, 0) "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0, @@ -3683,7 +3839,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)xmlparser_init, /* tp_init */ + _elementtree_XMLParser___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ xmlparser_new, /* tp_new */ 0, /* tp_free */ diff --git a/Modules/_elementtree.c b/Modules/clinic/_elementtree.c.h copy from Modules/_elementtree.c copy to Modules/clinic/_elementtree.c.h --- a/Modules/_elementtree.c +++ b/Modules/clinic/_elementtree.c.h @@ -1,3781 +1,666 @@ -/*-------------------------------------------------------------------- - * Licensed to PSF under a Contributor Agreement. - * See http://www.python.org/psf/license for licensing details. - * - * _elementtree - C accelerator for xml.etree.ElementTree - * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. - * Copyright (c) 1999-2009 by Fredrik Lundh. - * - * info at pythonware.com - * http://www.pythonware.com - *-------------------------------------------------------------------- - */ +/*[clinic input] +preserve +[clinic start generated code]*/ -#define PY_SSIZE_T_CLEAN +PyDoc_STRVAR(_elementtree_Element_append__doc__, +"append($self, subelement, /)\n" +"--\n" +"\n"); -#include "Python.h" -#include "structmember.h" +#define _ELEMENTTREE_ELEMENT_APPEND_METHODDEF \ + {"append", (PyCFunction)_elementtree_Element_append, METH_O, _elementtree_Element_append__doc__}, -/* -------------------------------------------------------------------- */ -/* configuration */ +static PyObject * +_elementtree_Element_append_impl(ElementObject *self, PyObject *subelement); -/* An element can hold this many children without extra memory - allocations. */ -#define STATIC_CHILDREN 4 +static PyObject * +_elementtree_Element_append(ElementObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *subelement; -/* For best performance, chose a value so that 80-90% of all nodes - have no more than the given number of children. Set this to zero - to minimize the size of the element structure itself (this only - helps if you have lots of leaf nodes with attributes). */ + if (!PyArg_Parse(arg, "O!:append", &Element_Type, &subelement)) + goto exit; + return_value = _elementtree_Element_append_impl(self, subelement); -/* Also note that pymalloc always allocates blocks in multiples of - eight bytes. For the current C version of ElementTree, this means - that the number of children should be an even number, at least on - 32-bit platforms. */ - -/* -------------------------------------------------------------------- */ - -#if 0 -static int memory = 0; -#define ALLOC(size, comment)\ -do { memory += size; printf("%8d - %s\n", memory, comment); } while (0) -#define RELEASE(size, comment)\ -do { memory -= size; printf("%8d - %s\n", memory, comment); } while (0) -#else -#define ALLOC(size, comment) -#define RELEASE(size, comment) -#endif - -/* compiler tweaks */ -#if defined(_MSC_VER) -#define LOCAL(type) static __inline type __fastcall -#else -#define LOCAL(type) static type -#endif - -/* macros used to store 'join' flags in string object pointers. note - that all use of text and tail as object pointers must be wrapped in - JOIN_OBJ. see comments in the ElementObject definition for more - info. */ -#define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) -#define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag))) -#define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~(Py_uintptr_t)1)) - -/* Py_CLEAR for a PyObject* that uses a join flag. Pass the pointer by - * reference since this function sets it to NULL. -*/ -static void _clear_joined_ptr(PyObject **p) -{ - if (*p) { - PyObject *tmp = JOIN_OBJ(*p); - *p = NULL; - Py_DECREF(tmp); - } +exit: + return return_value; } -/* Types defined by this extension */ -static PyTypeObject Element_Type; -static PyTypeObject ElementIter_Type; -static PyTypeObject TreeBuilder_Type; -static PyTypeObject XMLParser_Type; +PyDoc_STRVAR(_elementtree_Element_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n"); +#define _ELEMENTTREE_ELEMENT_CLEAR_METHODDEF \ + {"clear", (PyCFunction)_elementtree_Element_clear, METH_NOARGS, _elementtree_Element_clear__doc__}, -/* Per-module state; PEP 3121 */ -typedef struct { - PyObject *parseerror_obj; - PyObject *deepcopy_obj; - PyObject *elementpath_obj; -} elementtreestate; +static PyObject * +_elementtree_Element_clear_impl(ElementObject *self); -static struct PyModuleDef elementtreemodule; +static PyObject * +_elementtree_Element_clear(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element_clear_impl(self); +} -/* Given a module object (assumed to be _elementtree), get its per-module - * state. - */ -#define ET_STATE(mod) ((elementtreestate *) PyModule_GetState(mod)) +PyDoc_STRVAR(_elementtree_Element___copy____doc__, +"__copy__($self, /)\n" +"--\n" +"\n"); -/* Find the module instance imported in the currently running sub-interpreter - * and get its state. - */ -#define ET_STATE_GLOBAL \ - ((elementtreestate *) PyModule_GetState(PyState_FindModule(&elementtreemodule))) +#define _ELEMENTTREE_ELEMENT___COPY___METHODDEF \ + {"__copy__", (PyCFunction)_elementtree_Element___copy__, METH_NOARGS, _elementtree_Element___copy____doc__}, -static int -elementtree_clear(PyObject *m) +static PyObject * +_elementtree_Element___copy___impl(ElementObject *self); + +static PyObject * +_elementtree_Element___copy__(ElementObject *self, PyObject *Py_UNUSED(ignored)) { - elementtreestate *st = ET_STATE(m); - Py_CLEAR(st->parseerror_obj); - Py_CLEAR(st->deepcopy_obj); - Py_CLEAR(st->elementpath_obj); - return 0; + return _elementtree_Element___copy___impl(self); +} + +PyDoc_STRVAR(_elementtree_Element___deepcopy____doc__, +"__deepcopy__($self, memo, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT___DEEPCOPY___METHODDEF \ + {"__deepcopy__", (PyCFunction)_elementtree_Element___deepcopy__, METH_O, _elementtree_Element___deepcopy____doc__}, + +PyDoc_STRVAR(_elementtree_Element___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)_elementtree_Element___sizeof__, METH_NOARGS, _elementtree_Element___sizeof____doc__}, + +static Py_ssize_t +_elementtree_Element___sizeof___impl(ElementObject *self); + +static PyObject * +_elementtree_Element___sizeof__(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + Py_ssize_t _return_value; + + _return_value = _elementtree_Element___sizeof___impl(self); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element___getstate____doc__, +"__getstate__($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT___GETSTATE___METHODDEF \ + {"__getstate__", (PyCFunction)_elementtree_Element___getstate__, METH_NOARGS, _elementtree_Element___getstate____doc__}, + +static PyObject * +_elementtree_Element___getstate___impl(ElementObject *self); + +static PyObject * +_elementtree_Element___getstate__(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element___getstate___impl(self); +} + +PyDoc_STRVAR(_elementtree_Element___setstate____doc__, +"__setstate__($self, state, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT___SETSTATE___METHODDEF \ + {"__setstate__", (PyCFunction)_elementtree_Element___setstate__, METH_O, _elementtree_Element___setstate____doc__}, + +PyDoc_STRVAR(_elementtree_Element_extend__doc__, +"extend($self, elements, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_EXTEND_METHODDEF \ + {"extend", (PyCFunction)_elementtree_Element_extend, METH_O, _elementtree_Element_extend__doc__}, + +PyDoc_STRVAR(_elementtree_Element_find__doc__, +"find($self, /, path, namespaces=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_FIND_METHODDEF \ + {"find", (PyCFunction)_elementtree_Element_find, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_find__doc__}, + +static PyObject * +_elementtree_Element_find_impl(ElementObject *self, PyObject *path, + PyObject *namespaces); + +static PyObject * +_elementtree_Element_find(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "namespaces", NULL}; + PyObject *path; + PyObject *namespaces = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:find", _keywords, + &path, &namespaces)) + goto exit; + return_value = _elementtree_Element_find_impl(self, path, namespaces); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_findtext__doc__, +"findtext($self, /, path, default=None, namespaces=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_FINDTEXT_METHODDEF \ + {"findtext", (PyCFunction)_elementtree_Element_findtext, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_findtext__doc__}, + +static PyObject * +_elementtree_Element_findtext_impl(ElementObject *self, PyObject *path, + PyObject *default_value, + PyObject *namespaces); + +static PyObject * +_elementtree_Element_findtext(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "default", "namespaces", NULL}; + PyObject *path; + PyObject *default_value = Py_None; + PyObject *namespaces = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:findtext", _keywords, + &path, &default_value, &namespaces)) + goto exit; + return_value = _elementtree_Element_findtext_impl(self, path, default_value, namespaces); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_findall__doc__, +"findall($self, /, path, namespaces=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_FINDALL_METHODDEF \ + {"findall", (PyCFunction)_elementtree_Element_findall, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_findall__doc__}, + +static PyObject * +_elementtree_Element_findall_impl(ElementObject *self, PyObject *path, + PyObject *namespaces); + +static PyObject * +_elementtree_Element_findall(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "namespaces", NULL}; + PyObject *path; + PyObject *namespaces = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:findall", _keywords, + &path, &namespaces)) + goto exit; + return_value = _elementtree_Element_findall_impl(self, path, namespaces); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_iterfind__doc__, +"iterfind($self, /, path, namespaces=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF \ + {"iterfind", (PyCFunction)_elementtree_Element_iterfind, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iterfind__doc__}, + +static PyObject * +_elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path, + PyObject *namespaces); + +static PyObject * +_elementtree_Element_iterfind(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "namespaces", NULL}; + PyObject *path; + PyObject *namespaces = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:iterfind", _keywords, + &path, &namespaces)) + goto exit; + return_value = _elementtree_Element_iterfind_impl(self, path, namespaces); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_get__doc__, +"get($self, /, key, default=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_GET_METHODDEF \ + {"get", (PyCFunction)_elementtree_Element_get, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_get__doc__}, + +static PyObject * +_elementtree_Element_get_impl(ElementObject *self, PyObject *key, + PyObject *default_value); + +static PyObject * +_elementtree_Element_get(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "default", NULL}; + PyObject *key; + PyObject *default_value = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get", _keywords, + &key, &default_value)) + goto exit; + return_value = _elementtree_Element_get_impl(self, key, default_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_getchildren__doc__, +"getchildren($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_GETCHILDREN_METHODDEF \ + {"getchildren", (PyCFunction)_elementtree_Element_getchildren, METH_NOARGS, _elementtree_Element_getchildren__doc__}, + +static PyObject * +_elementtree_Element_getchildren_impl(ElementObject *self); + +static PyObject * +_elementtree_Element_getchildren(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element_getchildren_impl(self); +} + +PyDoc_STRVAR(_elementtree_Element_iter__doc__, +"iter($self, /, tag=None)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_ITER_METHODDEF \ + {"iter", (PyCFunction)_elementtree_Element_iter, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iter__doc__}, + +static PyObject * +_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag); + +static PyObject * +_elementtree_Element_iter(ElementObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"tag", NULL}; + PyObject *tag = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:iter", _keywords, + &tag)) + goto exit; + return_value = _elementtree_Element_iter_impl(self, tag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_itertext__doc__, +"itertext($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF \ + {"itertext", (PyCFunction)_elementtree_Element_itertext, METH_NOARGS, _elementtree_Element_itertext__doc__}, + +static PyObject * +_elementtree_Element_itertext_impl(ElementObject *self); + +static PyObject * +_elementtree_Element_itertext(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element_itertext_impl(self); +} + +PyDoc_STRVAR(_elementtree_Element_insert__doc__, +"insert($self, index, subelement, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_INSERT_METHODDEF \ + {"insert", (PyCFunction)_elementtree_Element_insert, METH_VARARGS, _elementtree_Element_insert__doc__}, + +static PyObject * +_elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, + PyObject *subelement); + +static PyObject * +_elementtree_Element_insert(ElementObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + Py_ssize_t index; + PyObject *subelement; + + if (!PyArg_ParseTuple(args, "nO!:insert", + &index, &Element_Type, &subelement)) + goto exit; + return_value = _elementtree_Element_insert_impl(self, index, subelement); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_items__doc__, +"items($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_ITEMS_METHODDEF \ + {"items", (PyCFunction)_elementtree_Element_items, METH_NOARGS, _elementtree_Element_items__doc__}, + +static PyObject * +_elementtree_Element_items_impl(ElementObject *self); + +static PyObject * +_elementtree_Element_items(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element_items_impl(self); +} + +PyDoc_STRVAR(_elementtree_Element_keys__doc__, +"keys($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_KEYS_METHODDEF \ + {"keys", (PyCFunction)_elementtree_Element_keys, METH_NOARGS, _elementtree_Element_keys__doc__}, + +static PyObject * +_elementtree_Element_keys_impl(ElementObject *self); + +static PyObject * +_elementtree_Element_keys(ElementObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _elementtree_Element_keys_impl(self); +} + +PyDoc_STRVAR(_elementtree_Element_makeelement__doc__, +"makeelement($self, tag, attrib, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_MAKEELEMENT_METHODDEF \ + {"makeelement", (PyCFunction)_elementtree_Element_makeelement, METH_VARARGS, _elementtree_Element_makeelement__doc__}, + +static PyObject * +_elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, + PyObject *attrib); + +static PyObject * +_elementtree_Element_makeelement(ElementObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *tag; + PyObject *attrib; + + if (!PyArg_UnpackTuple(args, "makeelement", + 2, 2, + &tag, &attrib)) + goto exit; + return_value = _elementtree_Element_makeelement_impl(self, tag, attrib); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_remove__doc__, +"remove($self, subelement, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_REMOVE_METHODDEF \ + {"remove", (PyCFunction)_elementtree_Element_remove, METH_O, _elementtree_Element_remove__doc__}, + +static PyObject * +_elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement); + +static PyObject * +_elementtree_Element_remove(ElementObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *subelement; + + if (!PyArg_Parse(arg, "O!:remove", &Element_Type, &subelement)) + goto exit; + return_value = _elementtree_Element_remove_impl(self, subelement); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree_Element_set__doc__, +"set($self, key, value, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_ELEMENT_SET_METHODDEF \ + {"set", (PyCFunction)_elementtree_Element_set, METH_VARARGS, _elementtree_Element_set__doc__}, + +static PyObject * +_elementtree_Element_set_impl(ElementObject *self, PyObject *key, + PyObject *value); + +static PyObject * +_elementtree_Element_set(ElementObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *key; + PyObject *value; + + if (!PyArg_UnpackTuple(args, "set", + 2, 2, + &key, &value)) + goto exit; + return_value = _elementtree_Element_set_impl(self, key, value); + +exit: + return return_value; } static int -elementtree_traverse(PyObject *m, visitproc visit, void *arg) +_elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, + PyObject *element_factory); + +static int +_elementtree_TreeBuilder___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - elementtreestate *st = ET_STATE(m); - Py_VISIT(st->parseerror_obj); - Py_VISIT(st->deepcopy_obj); - Py_VISIT(st->elementpath_obj); - return 0; + int return_value = -1; + static char *_keywords[] = {"element_factory", NULL}; + PyObject *element_factory = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:TreeBuilder", _keywords, + &element_factory)) + goto exit; + return_value = _elementtree_TreeBuilder___init___impl((TreeBuilderObject *)self, element_factory); + +exit: + return return_value; } -static void -elementtree_free(void *m) +PyDoc_STRVAR(_elementtree_TreeBuilder_data__doc__, +"data($self, data, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF \ + {"data", (PyCFunction)_elementtree_TreeBuilder_data, METH_O, _elementtree_TreeBuilder_data__doc__}, + +PyDoc_STRVAR(_elementtree_TreeBuilder_end__doc__, +"end($self, tag, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_TREEBUILDER_END_METHODDEF \ + {"end", (PyCFunction)_elementtree_TreeBuilder_end, METH_O, _elementtree_TreeBuilder_end__doc__}, + +PyDoc_STRVAR(_elementtree_TreeBuilder_close__doc__, +"close($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF \ + {"close", (PyCFunction)_elementtree_TreeBuilder_close, METH_NOARGS, _elementtree_TreeBuilder_close__doc__}, + +static PyObject * +_elementtree_TreeBuilder_close_impl(TreeBuilderObject *self); + +static PyObject * +_elementtree_TreeBuilder_close(TreeBuilderObject *self, PyObject *Py_UNUSED(ignored)) { - elementtree_clear((PyObject *)m); + return _elementtree_TreeBuilder_close_impl(self); } -/* helpers */ +PyDoc_STRVAR(_elementtree_TreeBuilder_start__doc__, +"start($self, tag, attrs=None, /)\n" +"--\n" +"\n"); -LOCAL(PyObject*) -deepcopy(PyObject* object, PyObject* memo) -{ - /* do a deep copy of the given object */ - PyObject* args; - PyObject* result; - elementtreestate *st = ET_STATE_GLOBAL; - - if (!st->deepcopy_obj) { - PyErr_SetString( - PyExc_RuntimeError, - "deepcopy helper not found" - ); - return NULL; - } - - args = PyTuple_Pack(2, object, memo); - if (!args) - return NULL; - result = PyObject_CallObject(st->deepcopy_obj, args); - Py_DECREF(args); - return result; -} - -LOCAL(PyObject*) -list_join(PyObject* list) -{ - /* join list elements (destroying the list in the process) */ - PyObject* joiner; - PyObject* result; - - joiner = PyUnicode_FromStringAndSize("", 0); - if (!joiner) - return NULL; - result = PyUnicode_Join(joiner, list); - Py_DECREF(joiner); - if (result) - Py_DECREF(list); - return result; -} - -/* Is the given object an empty dictionary? -*/ -static int -is_empty_dict(PyObject *obj) -{ - return PyDict_CheckExact(obj) && PyDict_Size(obj) == 0; -} - - -/* -------------------------------------------------------------------- */ -/* the Element type */ - -typedef struct { - - /* attributes (a dictionary object), or None if no attributes */ - PyObject* attrib; - - /* child elements */ - Py_ssize_t length; /* actual number of items */ - Py_ssize_t allocated; /* allocated items */ - - /* this either points to _children or to a malloced buffer */ - PyObject* *children; - - PyObject* _children[STATIC_CHILDREN]; - -} ElementObjectExtra; - -typedef struct { - PyObject_HEAD - - /* element tag (a string). */ - PyObject* tag; - - /* text before first child. note that this is a tagged pointer; - use JOIN_OBJ to get the object pointer. the join flag is used - to distinguish lists created by the tree builder from lists - assigned to the attribute by application code; the former - should be joined before being returned to the user, the latter - should be left intact. */ - PyObject* text; - - /* text after this element, in parent. note that this is a tagged - pointer; use JOIN_OBJ to get the object pointer. */ - PyObject* tail; - - ElementObjectExtra* extra; - - PyObject *weakreflist; /* For tp_weaklistoffset */ - -} ElementObject; - - -#define Element_CheckExact(op) (Py_TYPE(op) == &Element_Type) - -/* -------------------------------------------------------------------- */ -/* Element constructors and destructor */ - -LOCAL(int) -create_extra(ElementObject* self, PyObject* attrib) -{ - self->extra = PyObject_Malloc(sizeof(ElementObjectExtra)); - if (!self->extra) { - PyErr_NoMemory(); - return -1; - } - - if (!attrib) - attrib = Py_None; - - Py_INCREF(attrib); - self->extra->attrib = attrib; - - self->extra->length = 0; - self->extra->allocated = STATIC_CHILDREN; - self->extra->children = self->extra->_children; - - return 0; -} - -LOCAL(void) -dealloc_extra(ElementObject* self) -{ - ElementObjectExtra *myextra; - Py_ssize_t i; - - if (!self->extra) - return; - - /* Avoid DECREFs calling into this code again (cycles, etc.) - */ - myextra = self->extra; - self->extra = NULL; - - Py_DECREF(myextra->attrib); - - for (i = 0; i < myextra->length; i++) - Py_DECREF(myextra->children[i]); - - if (myextra->children != myextra->_children) - PyObject_Free(myextra->children); - - PyObject_Free(myextra); -} - -/* Convenience internal function to create new Element objects with the given - * tag and attributes. -*/ -LOCAL(PyObject*) -create_new_element(PyObject* tag, PyObject* attrib) -{ - ElementObject* self; - - self = PyObject_GC_New(ElementObject, &Element_Type); - if (self == NULL) - return NULL; - self->extra = NULL; - - Py_INCREF(tag); - self->tag = tag; - - Py_INCREF(Py_None); - self->text = Py_None; - - Py_INCREF(Py_None); - self->tail = Py_None; - - self->weakreflist = NULL; - - ALLOC(sizeof(ElementObject), "create element"); - PyObject_GC_Track(self); - - if (attrib != Py_None && !is_empty_dict(attrib)) { - if (create_extra(self, attrib) < 0) { - Py_DECREF(self); - return NULL; - } - } - - return (PyObject*) self; -} +#define _ELEMENTTREE_TREEBUILDER_START_METHODDEF \ + {"start", (PyCFunction)_elementtree_TreeBuilder_start, METH_VARARGS, _elementtree_TreeBuilder_start__doc__}, static PyObject * -element_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +_elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, + PyObject *attrs); + +static PyObject * +_elementtree_TreeBuilder_start(TreeBuilderObject *self, PyObject *args) { - ElementObject *e = (ElementObject *)type->tp_alloc(type, 0); - if (e != NULL) { - Py_INCREF(Py_None); - e->tag = Py_None; + PyObject *return_value = NULL; + PyObject *tag; + PyObject *attrs = Py_None; - Py_INCREF(Py_None); - e->text = Py_None; + if (!PyArg_UnpackTuple(args, "start", + 1, 2, + &tag, &attrs)) + goto exit; + return_value = _elementtree_TreeBuilder_start_impl(self, tag, attrs); - Py_INCREF(Py_None); - e->tail = Py_None; - - e->extra = NULL; - e->weakreflist = NULL; - } - return (PyObject *)e; -} - -/* Helper function for extracting the attrib dictionary from a keywords dict. - * This is required by some constructors/functions in this module that can - * either accept attrib as a keyword argument or all attributes splashed - * directly into *kwds. - * - * Return a dictionary with the content of kwds merged into the content of - * attrib. If there is no attrib keyword, return a copy of kwds. - */ -static PyObject* -get_attrib_from_keywords(PyObject *kwds) -{ - PyObject *attrib_str = PyUnicode_FromString("attrib"); - PyObject *attrib = PyDict_GetItem(kwds, attrib_str); - - if (attrib) { - /* If attrib was found in kwds, copy its value and remove it from - * kwds - */ - if (!PyDict_Check(attrib)) { - Py_DECREF(attrib_str); - PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s", - Py_TYPE(attrib)->tp_name); - return NULL; - } - attrib = PyDict_Copy(attrib); - PyDict_DelItem(kwds, attrib_str); - } else { - attrib = PyDict_New(); - } - - Py_DECREF(attrib_str); - - /* attrib can be NULL if PyDict_New failed */ - if (attrib) - if (PyDict_Update(attrib, kwds) < 0) - return NULL; - return attrib; +exit: + return return_value; } static int -element_init(PyObject *self, PyObject *args, PyObject *kwds) +_elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html, + PyObject *target, const char *encoding); + +static int +_elementtree_XMLParser___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *tag; - PyObject *tmp; - PyObject *attrib = NULL; - ElementObject *self_elem; + int return_value = -1; + static char *_keywords[] = {"html", "target", "encoding", NULL}; + PyObject *html = NULL; + PyObject *target = NULL; + const char *encoding = NULL; - if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib)) - return -1; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOz:XMLParser", _keywords, + &html, &target, &encoding)) + goto exit; + return_value = _elementtree_XMLParser___init___impl((XMLParserObject *)self, html, target, encoding); - if (attrib) { - /* attrib passed as positional arg */ - attrib = PyDict_Copy(attrib); - if (!attrib) - return -1; - if (kwds) { - if (PyDict_Update(attrib, kwds) < 0) { - Py_DECREF(attrib); - return -1; - } - } - } else if (kwds) { - /* have keywords args */ - attrib = get_attrib_from_keywords(kwds); - if (!attrib) - return -1; - } - - self_elem = (ElementObject *)self; - - if (attrib != NULL && !is_empty_dict(attrib)) { - if (create_extra(self_elem, attrib) < 0) { - Py_DECREF(attrib); - return -1; - } - } - - /* We own a reference to attrib here and it's no longer needed. */ - Py_XDECREF(attrib); - - /* Replace the objects already pointed to by tag, text and tail. */ - tmp = self_elem->tag; - Py_INCREF(tag); - self_elem->tag = tag; - Py_DECREF(tmp); - - tmp = self_elem->text; - Py_INCREF(Py_None); - self_elem->text = Py_None; - Py_DECREF(JOIN_OBJ(tmp)); - - tmp = self_elem->tail; - Py_INCREF(Py_None); - self_elem->tail = Py_None; - Py_DECREF(JOIN_OBJ(tmp)); - - return 0; +exit: + return return_value; } -LOCAL(int) -element_resize(ElementObject* self, Py_ssize_t extra) +PyDoc_STRVAR(_elementtree_XMLParser_close__doc__, +"close($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF \ + {"close", (PyCFunction)_elementtree_XMLParser_close, METH_NOARGS, _elementtree_XMLParser_close__doc__}, + +static PyObject * +_elementtree_XMLParser_close_impl(XMLParserObject *self); + +static PyObject * +_elementtree_XMLParser_close(XMLParserObject *self, PyObject *Py_UNUSED(ignored)) { - Py_ssize_t size; - PyObject* *children; - - /* make sure self->children can hold the given number of extra - elements. set an exception and return -1 if allocation failed */ - - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return -1; - } - - size = self->extra->length + extra; /* never overflows */ - - if (size > self->extra->allocated) { - /* use Python 2.4's list growth strategy */ - size = (size >> 3) + (size < 9 ? 3 : 6) + size; - /* Coverity CID #182 size_error: Allocating 1 bytes to pointer "children" - * which needs at least 4 bytes. - * Although it's a false alarm always assume at least one child to - * be safe. - */ - size = size ? size : 1; - if ((size_t)size > PY_SSIZE_T_MAX/sizeof(PyObject*)) - goto nomemory; - if (self->extra->children != self->extra->_children) { - /* Coverity CID #182 size_error: Allocating 1 bytes to pointer - * "children", which needs at least 4 bytes. Although it's a - * false alarm always assume at least one child to be safe. - */ - children = PyObject_Realloc(self->extra->children, - size * sizeof(PyObject*)); - if (!children) - goto nomemory; - } else { - children = PyObject_Malloc(size * sizeof(PyObject*)); - if (!children) - goto nomemory; - /* copy existing children from static area to malloc buffer */ - memcpy(children, self->extra->children, - self->extra->length * sizeof(PyObject*)); - } - self->extra->children = children; - self->extra->allocated = size; - } - - return 0; - - nomemory: - PyErr_NoMemory(); - return -1; + return _elementtree_XMLParser_close_impl(self); } -LOCAL(int) -element_add_subelement(ElementObject* self, PyObject* element) +PyDoc_STRVAR(_elementtree_XMLParser_feed__doc__, +"feed($self, data, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_XMLPARSER_FEED_METHODDEF \ + {"feed", (PyCFunction)_elementtree_XMLParser_feed, METH_O, _elementtree_XMLParser_feed__doc__}, + +PyDoc_STRVAR(_elementtree_XMLParser__parse_whole__doc__, +"_parse_whole($self, file, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF \ + {"_parse_whole", (PyCFunction)_elementtree_XMLParser__parse_whole, METH_O, _elementtree_XMLParser__parse_whole__doc__}, + +PyDoc_STRVAR(_elementtree_XMLParser_doctype__doc__, +"doctype($self, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_XMLPARSER_DOCTYPE_METHODDEF \ + {"doctype", (PyCFunction)_elementtree_XMLParser_doctype, METH_NOARGS, _elementtree_XMLParser_doctype__doc__}, + +static PyObject * +_elementtree_XMLParser_doctype_impl(XMLParserObject *self); + +static PyObject * +_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject *Py_UNUSED(ignored)) { - /* add a child element to a parent */ - - if (element_resize(self, 1) < 0) - return -1; - - Py_INCREF(element); - self->extra->children[self->extra->length] = element; - - self->extra->length++; - - return 0; + return _elementtree_XMLParser_doctype_impl(self); } -LOCAL(PyObject*) -element_get_attrib(ElementObject* self) -{ - /* return borrowed reference to attrib dictionary */ - /* note: this function assumes that the extra section exists */ +PyDoc_STRVAR(_elementtree_XMLParser__setevents__doc__, +"_setevents($self, events_queue, events_to_report=None, /)\n" +"--\n" +"\n"); - PyObject* res = self->extra->attrib; - - if (res == Py_None) { - /* create missing dictionary */ - res = PyDict_New(); - if (!res) - return NULL; - Py_DECREF(Py_None); - self->extra->attrib = res; - } - - return res; -} - -LOCAL(PyObject*) -element_get_text(ElementObject* self) -{ - /* return borrowed reference to text attribute */ - - PyObject* res = self->text; - - if (JOIN_GET(res)) { - res = JOIN_OBJ(res); - if (PyList_CheckExact(res)) { - res = list_join(res); - if (!res) - return NULL; - self->text = res; - } - } - - return res; -} - -LOCAL(PyObject*) -element_get_tail(ElementObject* self) -{ - /* return borrowed reference to text attribute */ - - PyObject* res = self->tail; - - if (JOIN_GET(res)) { - res = JOIN_OBJ(res); - if (PyList_CheckExact(res)) { - res = list_join(res); - if (!res) - return NULL; - self->tail = res; - } - } - - return res; -} - -static PyObject* -subelement(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject* elem; - - ElementObject* parent; - PyObject* tag; - PyObject* attrib = NULL; - if (!PyArg_ParseTuple(args, "O!O|O!:SubElement", - &Element_Type, &parent, &tag, - &PyDict_Type, &attrib)) { - return NULL; - } - - if (attrib) { - /* attrib passed as positional arg */ - attrib = PyDict_Copy(attrib); - if (!attrib) - return NULL; - if (kwds) { - if (PyDict_Update(attrib, kwds) < 0) { - return NULL; - } - } - } else if (kwds) { - /* have keyword args */ - attrib = get_attrib_from_keywords(kwds); - if (!attrib) - return NULL; - } else { - /* no attrib arg, no kwds, so no attribute */ - Py_INCREF(Py_None); - attrib = Py_None; - } - - elem = create_new_element(tag, attrib); - Py_DECREF(attrib); - if (elem == NULL) - return NULL; - - if (element_add_subelement(parent, elem) < 0) { - Py_DECREF(elem); - return NULL; - } - - return elem; -} - -static int -element_gc_traverse(ElementObject *self, visitproc visit, void *arg) -{ - Py_VISIT(self->tag); - Py_VISIT(JOIN_OBJ(self->text)); - Py_VISIT(JOIN_OBJ(self->tail)); - - if (self->extra) { - Py_ssize_t i; - Py_VISIT(self->extra->attrib); - - for (i = 0; i < self->extra->length; ++i) - Py_VISIT(self->extra->children[i]); - } - return 0; -} - -static int -element_gc_clear(ElementObject *self) -{ - Py_CLEAR(self->tag); - _clear_joined_ptr(&self->text); - _clear_joined_ptr(&self->tail); - - /* After dropping all references from extra, it's no longer valid anyway, - * so fully deallocate it. - */ - dealloc_extra(self); - return 0; -} - -static void -element_dealloc(ElementObject* self) -{ - PyObject_GC_UnTrack(self); - - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - - /* element_gc_clear clears all references and deallocates extra - */ - element_gc_clear(self); - - RELEASE(sizeof(ElementObject), "destroy element"); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -/* -------------------------------------------------------------------- */ - -static PyObject* -element_append(ElementObject* self, PyObject* args) -{ - PyObject* element; - if (!PyArg_ParseTuple(args, "O!:append", &Element_Type, &element)) - return NULL; - - if (element_add_subelement(self, element) < 0) - return NULL; - - Py_RETURN_NONE; -} - -static PyObject* -element_clearmethod(ElementObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":clear")) - return NULL; - - dealloc_extra(self); - - Py_INCREF(Py_None); - Py_DECREF(JOIN_OBJ(self->text)); - self->text = Py_None; - - Py_INCREF(Py_None); - Py_DECREF(JOIN_OBJ(self->tail)); - self->tail = Py_None; - - Py_RETURN_NONE; -} - -static PyObject* -element_copy(ElementObject* self, PyObject* args) -{ - Py_ssize_t i; - ElementObject* element; - - if (!PyArg_ParseTuple(args, ":__copy__")) - return NULL; - - element = (ElementObject*) create_new_element( - self->tag, (self->extra) ? self->extra->attrib : Py_None); - if (!element) - return NULL; - - Py_DECREF(JOIN_OBJ(element->text)); - element->text = self->text; - Py_INCREF(JOIN_OBJ(element->text)); - - Py_DECREF(JOIN_OBJ(element->tail)); - element->tail = self->tail; - Py_INCREF(JOIN_OBJ(element->tail)); - - if (self->extra) { - if (element_resize(element, self->extra->length) < 0) { - Py_DECREF(element); - return NULL; - } - - for (i = 0; i < self->extra->length; i++) { - Py_INCREF(self->extra->children[i]); - element->extra->children[i] = self->extra->children[i]; - } - - element->extra->length = self->extra->length; - } - - return (PyObject*) element; -} - -static PyObject* -element_deepcopy(ElementObject* self, PyObject* args) -{ - Py_ssize_t i; - ElementObject* element; - PyObject* tag; - PyObject* attrib; - PyObject* text; - PyObject* tail; - PyObject* id; - - PyObject* memo; - if (!PyArg_ParseTuple(args, "O:__deepcopy__", &memo)) - return NULL; - - tag = deepcopy(self->tag, memo); - if (!tag) - return NULL; - - if (self->extra) { - attrib = deepcopy(self->extra->attrib, memo); - if (!attrib) { - Py_DECREF(tag); - return NULL; - } - } else { - Py_INCREF(Py_None); - attrib = Py_None; - } - - element = (ElementObject*) create_new_element(tag, attrib); - - Py_DECREF(tag); - Py_DECREF(attrib); - - if (!element) - return NULL; - - text = deepcopy(JOIN_OBJ(self->text), memo); - if (!text) - goto error; - Py_DECREF(element->text); - element->text = JOIN_SET(text, JOIN_GET(self->text)); - - tail = deepcopy(JOIN_OBJ(self->tail), memo); - if (!tail) - goto error; - Py_DECREF(element->tail); - element->tail = JOIN_SET(tail, JOIN_GET(self->tail)); - - if (self->extra) { - if (element_resize(element, self->extra->length) < 0) - goto error; - - for (i = 0; i < self->extra->length; i++) { - PyObject* child = deepcopy(self->extra->children[i], memo); - if (!child) { - element->extra->length = i; - goto error; - } - element->extra->children[i] = child; - } - - element->extra->length = self->extra->length; - } - - /* add object to memo dictionary (so deepcopy won't visit it again) */ - id = PyLong_FromSsize_t((Py_uintptr_t) self); - if (!id) - goto error; - - i = PyDict_SetItem(memo, id, (PyObject*) element); - - Py_DECREF(id); - - if (i < 0) - goto error; - - return (PyObject*) element; - - error: - Py_DECREF(element); - return NULL; -} - -static PyObject* -element_sizeof(PyObject* myself, PyObject* args) -{ - ElementObject *self = (ElementObject*)myself; - Py_ssize_t result = sizeof(ElementObject); - if (self->extra) { - result += sizeof(ElementObjectExtra); - if (self->extra->children != self->extra->_children) - result += sizeof(PyObject*) * self->extra->allocated; - } - return PyLong_FromSsize_t(result); -} - -/* dict keys for getstate/setstate. */ -#define PICKLED_TAG "tag" -#define PICKLED_CHILDREN "_children" -#define PICKLED_ATTRIB "attrib" -#define PICKLED_TAIL "tail" -#define PICKLED_TEXT "text" - -/* __getstate__ returns a fabricated instance dict as in the pure-Python - * Element implementation, for interoperability/interchangeability. This - * makes the pure-Python implementation details an API, but (a) there aren't - * any unnecessary structures there; and (b) it buys compatibility with 3.2 - * pickles. See issue #16076. - */ -static PyObject * -element_getstate(ElementObject *self) -{ - Py_ssize_t i, noattrib; - PyObject *instancedict = NULL, *children; - - /* Build a list of children. */ - children = PyList_New(self->extra ? self->extra->length : 0); - if (!children) - return NULL; - for (i = 0; i < PyList_GET_SIZE(children); i++) { - PyObject *child = self->extra->children[i]; - Py_INCREF(child); - PyList_SET_ITEM(children, i, child); - } - - /* Construct the state object. */ - noattrib = (self->extra == NULL || self->extra->attrib == Py_None); - if (noattrib) - instancedict = Py_BuildValue("{sOsOs{}sOsO}", - PICKLED_TAG, self->tag, - PICKLED_CHILDREN, children, - PICKLED_ATTRIB, - PICKLED_TEXT, JOIN_OBJ(self->text), - PICKLED_TAIL, JOIN_OBJ(self->tail)); - else - instancedict = Py_BuildValue("{sOsOsOsOsO}", - PICKLED_TAG, self->tag, - PICKLED_CHILDREN, children, - PICKLED_ATTRIB, self->extra->attrib, - PICKLED_TEXT, JOIN_OBJ(self->text), - PICKLED_TAIL, JOIN_OBJ(self->tail)); - if (instancedict) { - Py_DECREF(children); - return instancedict; - } - else { - for (i = 0; i < PyList_GET_SIZE(children); i++) - Py_DECREF(PyList_GET_ITEM(children, i)); - Py_DECREF(children); - - return NULL; - } -} +#define _ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF \ + {"_setevents", (PyCFunction)_elementtree_XMLParser__setevents, METH_VARARGS, _elementtree_XMLParser__setevents__doc__}, static PyObject * -element_setstate_from_attributes(ElementObject *self, - PyObject *tag, - PyObject *attrib, - PyObject *text, - PyObject *tail, - PyObject *children) -{ - Py_ssize_t i, nchildren; - - if (!tag) { - PyErr_SetString(PyExc_TypeError, "tag may not be NULL"); - return NULL; - } - - Py_CLEAR(self->tag); - self->tag = tag; - Py_INCREF(self->tag); - - _clear_joined_ptr(&self->text); - self->text = text ? JOIN_SET(text, PyList_CheckExact(text)) : Py_None; - Py_INCREF(JOIN_OBJ(self->text)); - - _clear_joined_ptr(&self->tail); - self->tail = tail ? JOIN_SET(tail, PyList_CheckExact(tail)) : Py_None; - Py_INCREF(JOIN_OBJ(self->tail)); - - /* Handle ATTRIB and CHILDREN. */ - if (!children && !attrib) - Py_RETURN_NONE; - - /* Compute 'nchildren'. */ - if (children) { - if (!PyList_Check(children)) { - PyErr_SetString(PyExc_TypeError, "'_children' is not a list"); - return NULL; - } - nchildren = PyList_Size(children); - } - else { - nchildren = 0; - } - - /* Allocate 'extra'. */ - if (element_resize(self, nchildren)) { - return NULL; - } - assert(self->extra && self->extra->allocated >= nchildren); - - /* Copy children */ - for (i = 0; i < nchildren; i++) { - self->extra->children[i] = PyList_GET_ITEM(children, i); - Py_INCREF(self->extra->children[i]); - } - - self->extra->length = nchildren; - self->extra->allocated = nchildren; - - /* Stash attrib. */ - if (attrib) { - Py_CLEAR(self->extra->attrib); - self->extra->attrib = attrib; - Py_INCREF(attrib); - } - - Py_RETURN_NONE; -} - -/* __setstate__ for Element instance from the Python implementation. - * 'state' should be the instance dict. - */ -static PyObject * -element_setstate_from_Python(ElementObject *self, PyObject *state) -{ - static char *kwlist[] = {PICKLED_TAG, PICKLED_ATTRIB, PICKLED_TEXT, - PICKLED_TAIL, PICKLED_CHILDREN, 0}; - PyObject *args; - PyObject *tag, *attrib, *text, *tail, *children; - PyObject *retval; - - tag = attrib = text = tail = children = NULL; - args = PyTuple_New(0); - if (!args) - return NULL; - - if (PyArg_ParseTupleAndKeywords(args, state, "|$OOOOO", kwlist, &tag, - &attrib, &text, &tail, &children)) - retval = element_setstate_from_attributes(self, tag, attrib, text, - tail, children); - else - retval = NULL; - - Py_DECREF(args); - return retval; -} +_elementtree_XMLParser__setevents_impl(XMLParserObject *self, + PyObject *events_queue, + PyObject *events_to_report); static PyObject * -element_setstate(ElementObject *self, PyObject *state) +_elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *args) { - if (!PyDict_CheckExact(state)) { - PyErr_Format(PyExc_TypeError, - "Don't know how to unpickle \"%.200R\" as an Element", - state); - return NULL; - } - else - return element_setstate_from_Python(self, state); -} - -LOCAL(int) -checkpath(PyObject* tag) -{ - Py_ssize_t i; - int check = 1; - - /* check if a tag contains an xpath character */ - -#define PATHCHAR(ch) \ - (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.') - - if (PyUnicode_Check(tag)) { - const Py_ssize_t len = PyUnicode_GET_LENGTH(tag); - void *data = PyUnicode_DATA(tag); - unsigned int kind = PyUnicode_KIND(tag); - for (i = 0; i < len; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (ch == '{') - check = 0; - else if (ch == '}') - check = 1; - else if (check && PATHCHAR(ch)) - return 1; - } - return 0; - } - if (PyBytes_Check(tag)) { - char *p = PyBytes_AS_STRING(tag); - for (i = 0; i < PyBytes_GET_SIZE(tag); i++) { - if (p[i] == '{') - check = 0; - else if (p[i] == '}') - check = 1; - else if (check && PATHCHAR(p[i])) - return 1; - } - return 0; - } - - return 1; /* unknown type; might be path expression */ -} - -static PyObject* -element_extend(ElementObject* self, PyObject* args) -{ - PyObject* seq; - Py_ssize_t i, seqlen = 0; - - PyObject* seq_in; - if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) - return NULL; - - seq = PySequence_Fast(seq_in, ""); - if (!seq) { - PyErr_Format( - PyExc_TypeError, - "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name - ); - return NULL; - } - - seqlen = PySequence_Size(seq); - for (i = 0; i < seqlen; i++) { - PyObject* element = PySequence_Fast_GET_ITEM(seq, i); - if (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) { - Py_DECREF(seq); - PyErr_Format( - PyExc_TypeError, - "expected an Element, not \"%.200s\"", - Py_TYPE(element)->tp_name); - return NULL; - } - - if (element_add_subelement(self, element) < 0) { - Py_DECREF(seq); - return NULL; - } - } - - Py_DECREF(seq); - - Py_RETURN_NONE; -} - -static PyObject* -element_find(ElementObject *self, PyObject *args, PyObject *kwds) -{ - Py_ssize_t i; - PyObject* tag; - PyObject* namespaces = Py_None; - static char *kwlist[] = {"path", "namespaces", 0}; - elementtreestate *st = ET_STATE_GLOBAL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:find", kwlist, - &tag, &namespaces)) - return NULL; - - if (checkpath(tag) || namespaces != Py_None) { - _Py_IDENTIFIER(find); - return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_find, "OOO", self, tag, namespaces - ); - } - - if (!self->extra) - Py_RETURN_NONE; - - for (i = 0; i < self->extra->length; i++) { - PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { - Py_INCREF(item); - return item; - } - } - - Py_RETURN_NONE; -} - -static PyObject* -element_findtext(ElementObject *self, PyObject *args, PyObject *kwds) -{ - Py_ssize_t i; - PyObject* tag; - PyObject* default_value = Py_None; - PyObject* namespaces = Py_None; - _Py_IDENTIFIER(findtext); - static char *kwlist[] = {"path", "default", "namespaces", 0}; - elementtreestate *st = ET_STATE_GLOBAL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:findtext", kwlist, - &tag, &default_value, &namespaces)) - return NULL; - - if (checkpath(tag) || namespaces != Py_None) - return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_findtext, "OOOO", self, tag, default_value, namespaces - ); - - if (!self->extra) { - Py_INCREF(default_value); - return default_value; - } - - for (i = 0; i < self->extra->length; i++) { - ElementObject* item = (ElementObject*) self->extra->children[i]; - if (Element_CheckExact(item) && - (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) { - PyObject* text = element_get_text(item); - if (text == Py_None) - return PyUnicode_New(0, 0); - Py_XINCREF(text); - return text; - } - } - - Py_INCREF(default_value); - return default_value; -} - -static PyObject* -element_findall(ElementObject *self, PyObject *args, PyObject *kwds) -{ - Py_ssize_t i; - PyObject* out; - PyObject* tag; - PyObject* namespaces = Py_None; - static char *kwlist[] = {"path", "namespaces", 0}; - elementtreestate *st = ET_STATE_GLOBAL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:findall", kwlist, - &tag, &namespaces)) - return NULL; - - if (checkpath(tag) || namespaces != Py_None) { - _Py_IDENTIFIER(findall); - return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_findall, "OOO", self, tag, namespaces - ); - } - - out = PyList_New(0); - if (!out) - return NULL; - - if (!self->extra) - return out; - - for (i = 0; i < self->extra->length; i++) { - PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { - if (PyList_Append(out, item) < 0) { - Py_DECREF(out); - return NULL; - } - } - } - - return out; -} - -static PyObject* -element_iterfind(ElementObject *self, PyObject *args, PyObject *kwds) -{ - PyObject* tag; - PyObject* namespaces = Py_None; - _Py_IDENTIFIER(iterfind); - static char *kwlist[] = {"path", "namespaces", 0}; - elementtreestate *st = ET_STATE_GLOBAL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:iterfind", kwlist, - &tag, &namespaces)) { - return NULL; - } - - return _PyObject_CallMethodId( - st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces); -} - -static PyObject* -element_get(ElementObject* self, PyObject* args, PyObject* kwds) -{ - PyObject* value; - static char* kwlist[] = {"key", "default", 0}; - - PyObject* key; - PyObject* default_value = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:get", kwlist, &key, - &default_value)) - return NULL; - - if (!self->extra || self->extra->attrib == Py_None) - value = default_value; - else { - value = PyDict_GetItem(self->extra->attrib, key); - if (!value) - value = default_value; - } - - Py_INCREF(value); - return value; -} - -static PyObject* -element_getchildren(ElementObject* self, PyObject* args) -{ - Py_ssize_t i; - PyObject* list; - - /* FIXME: report as deprecated? */ - - if (!PyArg_ParseTuple(args, ":getchildren")) - return NULL; - - if (!self->extra) - return PyList_New(0); - - list = PyList_New(self->extra->length); - if (!list) - return NULL; - - for (i = 0; i < self->extra->length; i++) { - PyObject* item = self->extra->children[i]; - Py_INCREF(item); - PyList_SET_ITEM(list, i, item); - } - - return list; -} - - -static PyObject * -create_elementiter(ElementObject *self, PyObject *tag, int gettext); - - -static PyObject * -element_iter(ElementObject *self, PyObject *args, PyObject *kwds) -{ - PyObject* tag = Py_None; - static char* kwlist[] = {"tag", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:iter", kwlist, &tag)) - return NULL; - - return create_elementiter(self, tag, 0); -} - - -static PyObject* -element_itertext(ElementObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":itertext")) - return NULL; - - return create_elementiter(self, Py_None, 1); -} - - -static PyObject* -element_getitem(PyObject* self_, Py_ssize_t index) -{ - ElementObject* self = (ElementObject*) self_; - - if (!self->extra || index < 0 || index >= self->extra->length) { - PyErr_SetString( - PyExc_IndexError, - "child index out of range" - ); - return NULL; - } - - Py_INCREF(self->extra->children[index]); - return self->extra->children[index]; -} - -static PyObject* -element_insert(ElementObject* self, PyObject* args) -{ - Py_ssize_t index, i; - PyObject* element; - if (!PyArg_ParseTuple(args, "nO!:insert", &index, - &Element_Type, &element)) - return NULL; - - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return NULL; - } - - if (index < 0) { - index += self->extra->length; - if (index < 0) - index = 0; - } - if (index > self->extra->length) - index = self->extra->length; - - if (element_resize(self, 1) < 0) - return NULL; - - for (i = self->extra->length; i > index; i--) - self->extra->children[i] = self->extra->children[i-1]; - - Py_INCREF(element); - self->extra->children[index] = element; - - self->extra->length++; - - Py_RETURN_NONE; -} - -static PyObject* -element_items(ElementObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":items")) - return NULL; - - if (!self->extra || self->extra->attrib == Py_None) - return PyList_New(0); - - return PyDict_Items(self->extra->attrib); -} - -static PyObject* -element_keys(ElementObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":keys")) - return NULL; - - if (!self->extra || self->extra->attrib == Py_None) - return PyList_New(0); - - return PyDict_Keys(self->extra->attrib); -} - -static Py_ssize_t -element_length(ElementObject* self) -{ - if (!self->extra) - return 0; - - return self->extra->length; -} - -static PyObject* -element_makeelement(PyObject* self, PyObject* args, PyObject* kw) -{ - PyObject* elem; - - PyObject* tag; - PyObject* attrib; - if (!PyArg_ParseTuple(args, "OO:makeelement", &tag, &attrib)) - return NULL; - - attrib = PyDict_Copy(attrib); - if (!attrib) - return NULL; - - elem = create_new_element(tag, attrib); - - Py_DECREF(attrib); - - return elem; -} - -static PyObject* -element_remove(ElementObject* self, PyObject* args) -{ - Py_ssize_t i; - - PyObject* element; - if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element)) - return NULL; - - if (!self->extra) { - /* element has no children, so raise exception */ - PyErr_SetString( - PyExc_ValueError, - "list.remove(x): x not in list" - ); - return NULL; - } - - for (i = 0; i < self->extra->length; i++) { - if (self->extra->children[i] == element) - break; - if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1) - break; - } - - if (i == self->extra->length) { - /* element is not in children, so raise exception */ - PyErr_SetString( - PyExc_ValueError, - "list.remove(x): x not in list" - ); - return NULL; - } - - Py_DECREF(self->extra->children[i]); - - self->extra->length--; - - for (; i < self->extra->length; i++) - self->extra->children[i] = self->extra->children[i+1]; - - Py_RETURN_NONE; -} - -static PyObject* -element_repr(ElementObject* self) -{ - if (self->tag) - return PyUnicode_FromFormat("", self->tag, self); - else - return PyUnicode_FromFormat("", self); -} - -static PyObject* -element_set(ElementObject* self, PyObject* args) -{ - PyObject* attrib; - - PyObject* key; - PyObject* value; - if (!PyArg_ParseTuple(args, "OO:set", &key, &value)) - return NULL; - - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return NULL; - } - - attrib = element_get_attrib(self); - if (!attrib) - return NULL; - - if (PyDict_SetItem(attrib, key, value) < 0) - return NULL; - - Py_RETURN_NONE; -} - -static int -element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) -{ - ElementObject* self = (ElementObject*) self_; - Py_ssize_t i; - PyObject* old; - - if (!self->extra || index < 0 || index >= self->extra->length) { - PyErr_SetString( - PyExc_IndexError, - "child assignment index out of range"); - return -1; - } - - old = self->extra->children[index]; - - if (item) { - Py_INCREF(item); - self->extra->children[index] = item; - } else { - self->extra->length--; - for (i = index; i < self->extra->length; i++) - self->extra->children[i] = self->extra->children[i+1]; - } - - Py_DECREF(old); - - return 0; -} - -static PyObject* -element_subscr(PyObject* self_, PyObject* item) -{ - ElementObject* self = (ElementObject*) self_; - - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (i < 0 && self->extra) - i += self->extra->length; - return element_getitem(self_, i); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelen, cur, i; - PyObject* list; - - if (!self->extra) - return PyList_New(0); - - if (PySlice_GetIndicesEx(item, - self->extra->length, - &start, &stop, &step, &slicelen) < 0) { - return NULL; - } - - if (slicelen <= 0) - return PyList_New(0); - else { - list = PyList_New(slicelen); - if (!list) - return NULL; - - for (cur = start, i = 0; i < slicelen; - cur += step, i++) { - PyObject* item = self->extra->children[cur]; - Py_INCREF(item); - PyList_SET_ITEM(list, i, item); - } - - return list; - } - } - else { - PyErr_SetString(PyExc_TypeError, - "element indices must be integers"); - return NULL; - } -} - -static int -element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) -{ - ElementObject* self = (ElementObject*) self_; - - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - - if (i == -1 && PyErr_Occurred()) { - return -1; - } - if (i < 0 && self->extra) - i += self->extra->length; - return element_setitem(self_, i, value); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelen, newlen, cur, i; - - PyObject* recycle = NULL; - PyObject* seq = NULL; - - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return -1; - } - - if (PySlice_GetIndicesEx(item, - self->extra->length, - &start, &stop, &step, &slicelen) < 0) { - return -1; - } - - if (value == NULL) { - /* Delete slice */ - size_t cur; - Py_ssize_t i; - - if (slicelen <= 0) - return 0; - - /* Since we're deleting, the direction of the range doesn't matter, - * so for simplicity make it always ascending. - */ - if (step < 0) { - stop = start + 1; - start = stop + step * (slicelen - 1) - 1; - step = -step; - } - - assert((size_t)slicelen <= PY_SIZE_MAX / sizeof(PyObject *)); - - /* recycle is a list that will contain all the children - * scheduled for removal. - */ - if (!(recycle = PyList_New(slicelen))) { - PyErr_NoMemory(); - return -1; - } - - /* This loop walks over all the children that have to be deleted, - * with cur pointing at them. num_moved is the amount of children - * until the next deleted child that have to be "shifted down" to - * occupy the deleted's places. - * Note that in the ith iteration, shifting is done i+i places down - * because i children were already removed. - */ - for (cur = start, i = 0; cur < (size_t)stop; cur += step, ++i) { - /* Compute how many children have to be moved, clipping at the - * list end. - */ - Py_ssize_t num_moved = step - 1; - if (cur + step >= (size_t)self->extra->length) { - num_moved = self->extra->length - cur - 1; - } - - PyList_SET_ITEM(recycle, i, self->extra->children[cur]); - - memmove( - self->extra->children + cur - i, - self->extra->children + cur + 1, - num_moved * sizeof(PyObject *)); - } - - /* Leftover "tail" after the last removed child */ - cur = start + (size_t)slicelen * step; - if (cur < (size_t)self->extra->length) { - memmove( - self->extra->children + cur - slicelen, - self->extra->children + cur, - (self->extra->length - cur) * sizeof(PyObject *)); - } - - self->extra->length -= slicelen; - - /* Discard the recycle list with all the deleted sub-elements */ - Py_XDECREF(recycle); - return 0; - } - else { - /* A new slice is actually being assigned */ - seq = PySequence_Fast(value, ""); - if (!seq) { - PyErr_Format( - PyExc_TypeError, - "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name - ); - return -1; - } - newlen = PySequence_Size(seq); - } - - if (step != 1 && newlen != slicelen) - { - PyErr_Format(PyExc_ValueError, - "attempt to assign sequence of size %zd " - "to extended slice of size %zd", - newlen, slicelen - ); - return -1; - } - - /* Resize before creating the recycle bin, to prevent refleaks. */ - if (newlen > slicelen) { - if (element_resize(self, newlen - slicelen) < 0) { - if (seq) { - Py_DECREF(seq); - } - return -1; - } - } - - if (slicelen > 0) { - /* to avoid recursive calls to this method (via decref), move - old items to the recycle bin here, and get rid of them when - we're done modifying the element */ - recycle = PyList_New(slicelen); - if (!recycle) { - if (seq) { - Py_DECREF(seq); - } - return -1; - } - for (cur = start, i = 0; i < slicelen; - cur += step, i++) - PyList_SET_ITEM(recycle, i, self->extra->children[cur]); - } - - if (newlen < slicelen) { - /* delete slice */ - for (i = stop; i < self->extra->length; i++) - self->extra->children[i + newlen - slicelen] = self->extra->children[i]; - } else if (newlen > slicelen) { - /* insert slice */ - for (i = self->extra->length-1; i >= stop; i--) - self->extra->children[i + newlen - slicelen] = self->extra->children[i]; - } - - /* replace the slice */ - for (cur = start, i = 0; i < newlen; - cur += step, i++) { - PyObject* element = PySequence_Fast_GET_ITEM(seq, i); - Py_INCREF(element); - self->extra->children[cur] = element; - } - - self->extra->length += newlen - slicelen; - - if (seq) { - Py_DECREF(seq); - } - - /* discard the recycle bin, and everything in it */ - Py_XDECREF(recycle); - - return 0; - } - else { - PyErr_SetString(PyExc_TypeError, - "element indices must be integers"); - return -1; - } -} - -static PyMethodDef element_methods[] = { - - {"clear", (PyCFunction) element_clearmethod, METH_VARARGS}, - - {"get", (PyCFunction) element_get, METH_VARARGS | METH_KEYWORDS}, - {"set", (PyCFunction) element_set, METH_VARARGS}, - - {"find", (PyCFunction) element_find, METH_VARARGS | METH_KEYWORDS}, - {"findtext", (PyCFunction) element_findtext, METH_VARARGS | METH_KEYWORDS}, - {"findall", (PyCFunction) element_findall, METH_VARARGS | METH_KEYWORDS}, - - {"append", (PyCFunction) element_append, METH_VARARGS}, - {"extend", (PyCFunction) element_extend, METH_VARARGS}, - {"insert", (PyCFunction) element_insert, METH_VARARGS}, - {"remove", (PyCFunction) element_remove, METH_VARARGS}, - - {"iter", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS}, - {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, - {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS | METH_KEYWORDS}, - - {"getiterator", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS}, - {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, - - {"items", (PyCFunction) element_items, METH_VARARGS}, - {"keys", (PyCFunction) element_keys, METH_VARARGS}, - - {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, - - {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, - {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, - {"__sizeof__", element_sizeof, METH_NOARGS}, - {"__getstate__", (PyCFunction)element_getstate, METH_NOARGS}, - {"__setstate__", (PyCFunction)element_setstate, METH_O}, - - {NULL, NULL} -}; - -static PyObject* -element_getattro(ElementObject* self, PyObject* nameobj) -{ - PyObject* res; - char *name = ""; - - if (PyUnicode_Check(nameobj)) - name = _PyUnicode_AsString(nameobj); - - if (name == NULL) - return NULL; - - /* handle common attributes first */ - if (strcmp(name, "tag") == 0) { - res = self->tag; - Py_INCREF(res); - return res; - } else if (strcmp(name, "text") == 0) { - res = element_get_text(self); - Py_XINCREF(res); - return res; - } - - /* methods */ - res = PyObject_GenericGetAttr((PyObject*) self, nameobj); - if (res) - return res; - - /* less common attributes */ - if (strcmp(name, "tail") == 0) { - PyErr_Clear(); - res = element_get_tail(self); - } else if (strcmp(name, "attrib") == 0) { - PyErr_Clear(); - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return NULL; - } - res = element_get_attrib(self); - } - - if (!res) - return NULL; - - Py_INCREF(res); - return res; -} - -static int -element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value) -{ - char *name = ""; - if (PyUnicode_Check(nameobj)) - name = _PyUnicode_AsString(nameobj); - if (name == NULL) - return -1; - - if (strcmp(name, "tag") == 0) { - Py_DECREF(self->tag); - self->tag = value; - Py_INCREF(self->tag); - } else if (strcmp(name, "text") == 0) { - Py_DECREF(JOIN_OBJ(self->text)); - self->text = value; - Py_INCREF(self->text); - } else if (strcmp(name, "tail") == 0) { - Py_DECREF(JOIN_OBJ(self->tail)); - self->tail = value; - Py_INCREF(self->tail); - } else if (strcmp(name, "attrib") == 0) { - if (!self->extra) { - if (create_extra(self, NULL) < 0) - return -1; - } - Py_DECREF(self->extra->attrib); - self->extra->attrib = value; - Py_INCREF(self->extra->attrib); - } else { - PyErr_SetString(PyExc_AttributeError, - "Can't set arbitrary attributes on Element"); - return -1; - } - - return 0; -} - -static PySequenceMethods element_as_sequence = { - (lenfunc) element_length, - 0, /* sq_concat */ - 0, /* sq_repeat */ - element_getitem, - 0, - element_setitem, - 0, -}; - -static PyMappingMethods element_as_mapping = { - (lenfunc) element_length, - (binaryfunc) element_subscr, - (objobjargproc) element_ass_subscr, -}; - -static PyTypeObject Element_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.Element", sizeof(ElementObject), 0, - /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)element_repr, /* tp_repr */ - 0, /* tp_as_number */ - &element_as_sequence, /* tp_as_sequence */ - &element_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc)element_getattro, /* tp_getattro */ - (setattrofunc)element_setattro, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)element_gc_traverse, /* tp_traverse */ - (inquiry)element_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - element_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 */ - (initproc)element_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - element_new, /* tp_new */ - 0, /* tp_free */ -}; - -/******************************* Element iterator ****************************/ - -/* ElementIterObject represents the iteration state over an XML element in - * pre-order traversal. To keep track of which sub-element should be returned - * next, a stack of parents is maintained. This is a standard stack-based - * iterative pre-order traversal of a tree. - * The stack is managed using a single-linked list starting at parent_stack. - * Each stack node contains the saved parent to which we should return after - * the current one is exhausted, and the next child to examine in that parent. - */ -typedef struct ParentLocator_t { - ElementObject *parent; - Py_ssize_t child_index; - struct ParentLocator_t *next; -} ParentLocator; - -typedef struct { - PyObject_HEAD - ParentLocator *parent_stack; - ElementObject *root_element; - PyObject *sought_tag; - int root_done; - int gettext; -} ElementIterObject; - - -static void -elementiter_dealloc(ElementIterObject *it) -{ - ParentLocator *p = it->parent_stack; - while (p) { - ParentLocator *temp = p; - Py_XDECREF(p->parent); - p = p->next; - PyObject_Free(temp); - } - - Py_XDECREF(it->sought_tag); - Py_XDECREF(it->root_element); - - PyObject_GC_UnTrack(it); - PyObject_GC_Del(it); -} - -static int -elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg) -{ - ParentLocator *p = it->parent_stack; - while (p) { - Py_VISIT(p->parent); - p = p->next; - } - - Py_VISIT(it->root_element); - Py_VISIT(it->sought_tag); - return 0; -} - -/* Helper function for elementiter_next. Add a new parent to the parent stack. - */ -static ParentLocator * -parent_stack_push_new(ParentLocator *stack, ElementObject *parent) -{ - ParentLocator *new_node = PyObject_Malloc(sizeof(ParentLocator)); - if (new_node) { - new_node->parent = parent; - Py_INCREF(parent); - new_node->child_index = 0; - new_node->next = stack; - } - return new_node; -} - -static PyObject * -elementiter_next(ElementIterObject *it) -{ - /* Sub-element iterator. - * - * A short note on gettext: this function serves both the iter() and - * itertext() methods to avoid code duplication. However, there are a few - * small differences in the way these iterations work. Namely: - * - itertext() only yields text from nodes that have it, and continues - * iterating when a node doesn't have text (so it doesn't return any - * node like iter()) - * - itertext() also has to handle tail, after finishing with all the - * children of a node. - */ - ElementObject *cur_parent; - Py_ssize_t child_index; - - while (1) { - /* Handle the case reached in the beginning and end of iteration, where - * the parent stack is empty. The root_done flag gives us indication - * whether we've just started iterating (so root_done is 0), in which - * case the root is returned. If root_done is 1 and we're here, the - * iterator is exhausted. - */ - if (!it->parent_stack->parent) { - if (it->root_done) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } else { - it->parent_stack = parent_stack_push_new(it->parent_stack, - it->root_element); - if (!it->parent_stack) { - PyErr_NoMemory(); - return NULL; - } - - it->root_done = 1; - if (it->sought_tag == Py_None || - PyObject_RichCompareBool(it->root_element->tag, - it->sought_tag, Py_EQ) == 1) { - if (it->gettext) { - PyObject *text = element_get_text(it->root_element); - if (!text) - return NULL; - if (PyObject_IsTrue(text)) { - Py_INCREF(text); - return text; - } - } else { - Py_INCREF(it->root_element); - return (PyObject *)it->root_element; - } - } - } - } - - /* See if there are children left to traverse in the current parent. If - * yes, visit the next child. If not, pop the stack and try again. - */ - cur_parent = it->parent_stack->parent; - child_index = it->parent_stack->child_index; - if (cur_parent->extra && child_index < cur_parent->extra->length) { - ElementObject *child = (ElementObject *) - cur_parent->extra->children[child_index]; - it->parent_stack->child_index++; - it->parent_stack = parent_stack_push_new(it->parent_stack, - child); - if (!it->parent_stack) { - PyErr_NoMemory(); - return NULL; - } - - if (it->gettext) { - PyObject *text = element_get_text(child); - if (!text) - return NULL; - if (PyObject_IsTrue(text)) { - Py_INCREF(text); - return text; - } - } else if (it->sought_tag == Py_None || - PyObject_RichCompareBool(child->tag, - it->sought_tag, Py_EQ) == 1) { - Py_INCREF(child); - return (PyObject *)child; - } - else - continue; - } - else { - PyObject *tail; - ParentLocator *next = it->parent_stack->next; - if (it->gettext) { - tail = element_get_tail(cur_parent); - if (!tail) - return NULL; - } - else - tail = Py_None; - Py_XDECREF(it->parent_stack->parent); - PyObject_Free(it->parent_stack); - it->parent_stack = next; - - /* Note that extra condition on it->parent_stack->parent here; - * this is because itertext() is supposed to only return *inner* - * text, not text following the element it began iteration with. - */ - if (it->parent_stack->parent && PyObject_IsTrue(tail)) { - Py_INCREF(tail); - return tail; - } - } - } - - return NULL; -} - - -static PyTypeObject ElementIter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - /* Using the module's name since the pure-Python implementation does not - have such a type. */ - "_elementtree._element_iterator", /* tp_name */ - sizeof(ElementIterObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)elementiter_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)elementiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)elementiter_next, /* 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 */ - 0, /* tp_new */ -}; - - -static PyObject * -create_elementiter(ElementObject *self, PyObject *tag, int gettext) -{ - ElementIterObject *it; - PyObject *star = NULL; - - it = PyObject_GC_New(ElementIterObject, &ElementIter_Type); - if (!it) - return NULL; - - if (PyUnicode_Check(tag)) - star = PyUnicode_FromString("*"); - else if (PyBytes_Check(tag)) - star = PyBytes_FromString("*"); - - if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1) - tag = Py_None; - Py_XDECREF(star); - - Py_INCREF(tag); - it->sought_tag = tag; - it->root_done = 0; - it->gettext = gettext; - Py_INCREF(self); - it->root_element = self; - - PyObject_GC_Track(it); - - it->parent_stack = PyObject_Malloc(sizeof(ParentLocator)); - if (it->parent_stack == NULL) { - Py_DECREF(it); - PyErr_NoMemory(); - return NULL; - } - it->parent_stack->parent = NULL; - it->parent_stack->child_index = 0; - it->parent_stack->next = NULL; - - return (PyObject *)it; -} - - -/* ==================================================================== */ -/* the tree builder type */ - -typedef struct { - PyObject_HEAD - - PyObject *root; /* root node (first created node) */ - - PyObject *this; /* current node */ - PyObject *last; /* most recently created node */ - - PyObject *data; /* data collector (string or list), or NULL */ - - PyObject *stack; /* element stack */ - Py_ssize_t index; /* current stack size (0 means empty) */ - - PyObject *element_factory; - - /* element tracing */ - PyObject *events; /* list of events, or NULL if not collecting */ - PyObject *start_event_obj; /* event objects (NULL to ignore) */ - PyObject *end_event_obj; - PyObject *start_ns_event_obj; - PyObject *end_ns_event_obj; -} TreeBuilderObject; - -#define TreeBuilder_CheckExact(op) (Py_TYPE(op) == &TreeBuilder_Type) - -/* -------------------------------------------------------------------- */ -/* constructor and destructor */ - -static PyObject * -treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - TreeBuilderObject *t = (TreeBuilderObject *)type->tp_alloc(type, 0); - if (t != NULL) { - t->root = NULL; - - Py_INCREF(Py_None); - t->this = Py_None; - Py_INCREF(Py_None); - t->last = Py_None; - - t->data = NULL; - t->element_factory = NULL; - t->stack = PyList_New(20); - if (!t->stack) { - Py_DECREF(t->this); - Py_DECREF(t->last); - Py_DECREF((PyObject *) t); - return NULL; - } - t->index = 0; - - t->events = NULL; - t->start_event_obj = t->end_event_obj = NULL; - t->start_ns_event_obj = t->end_ns_event_obj = NULL; - } - return (PyObject *)t; -} - -static int -treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"element_factory", 0}; - PyObject *element_factory = NULL; - TreeBuilderObject *self_tb = (TreeBuilderObject *)self; - PyObject *tmp; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:TreeBuilder", kwlist, - &element_factory)) { - return -1; - } - - if (element_factory) { - Py_INCREF(element_factory); - tmp = self_tb->element_factory; - self_tb->element_factory = element_factory; - Py_XDECREF(tmp); - } - - return 0; -} - -static int -treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) -{ - Py_VISIT(self->root); - Py_VISIT(self->this); - Py_VISIT(self->last); - Py_VISIT(self->data); - Py_VISIT(self->stack); - Py_VISIT(self->element_factory); - return 0; -} - -static int -treebuilder_gc_clear(TreeBuilderObject *self) -{ - Py_CLEAR(self->end_ns_event_obj); - Py_CLEAR(self->start_ns_event_obj); - Py_CLEAR(self->end_event_obj); - Py_CLEAR(self->start_event_obj); - Py_CLEAR(self->events); - Py_CLEAR(self->stack); - Py_CLEAR(self->data); - Py_CLEAR(self->last); - Py_CLEAR(self->this); - Py_CLEAR(self->element_factory); - Py_CLEAR(self->root); - return 0; -} - -static void -treebuilder_dealloc(TreeBuilderObject *self) -{ - PyObject_GC_UnTrack(self); - treebuilder_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -/* -------------------------------------------------------------------- */ -/* helpers for handling of arbitrary element-like objects */ - -static int -treebuilder_set_element_text_or_tail(PyObject *element, PyObject *data, - PyObject **dest, _Py_Identifier *name) -{ - if (Element_CheckExact(element)) { - Py_DECREF(JOIN_OBJ(*dest)); - *dest = JOIN_SET(data, PyList_CheckExact(data)); - return 0; - } - else { - PyObject *joined = list_join(data); - int r; - if (joined == NULL) - return -1; - r = _PyObject_SetAttrId(element, name, joined); - Py_DECREF(joined); - return r; - } -} - -/* These two functions steal a reference to data */ -static int -treebuilder_set_element_text(PyObject *element, PyObject *data) -{ - _Py_IDENTIFIER(text); - return treebuilder_set_element_text_or_tail( - element, data, &((ElementObject *) element)->text, &PyId_text); -} - -static int -treebuilder_set_element_tail(PyObject *element, PyObject *data) -{ - _Py_IDENTIFIER(tail); - return treebuilder_set_element_text_or_tail( - element, data, &((ElementObject *) element)->tail, &PyId_tail); -} - -static int -treebuilder_add_subelement(PyObject *element, PyObject *child) -{ - _Py_IDENTIFIER(append); - if (Element_CheckExact(element)) { - ElementObject *elem = (ElementObject *) element; - return element_add_subelement(elem, child); - } - else { - PyObject *res; - res = _PyObject_CallMethodId(element, &PyId_append, "O", child); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; - } -} - -/* -------------------------------------------------------------------- */ -/* handlers */ - -LOCAL(PyObject*) -treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, - PyObject* attrib) -{ - PyObject* node; - PyObject* this; - elementtreestate *st = ET_STATE_GLOBAL; - - if (self->data) { - if (self->this == self->last) { - if (treebuilder_set_element_text(self->last, self->data)) - return NULL; - } - else { - if (treebuilder_set_element_tail(self->last, self->data)) - return NULL; - } - self->data = NULL; - } - - if (self->element_factory && self->element_factory != Py_None) { - node = PyObject_CallFunction(self->element_factory, "OO", tag, attrib); - } else { - node = create_new_element(tag, attrib); - } - if (!node) { - return NULL; - } - - this = self->this; - - if (this != Py_None) { - if (treebuilder_add_subelement(this, node) < 0) - goto error; - } else { - if (self->root) { - PyErr_SetString( - st->parseerror_obj, - "multiple elements on top level" - ); - goto error; - } - Py_INCREF(node); - self->root = node; - } - - if (self->index < PyList_GET_SIZE(self->stack)) { - if (PyList_SetItem(self->stack, self->index, this) < 0) - goto error; - Py_INCREF(this); - } else { - if (PyList_Append(self->stack, this) < 0) - goto error; - } - self->index++; - - Py_DECREF(this); - Py_INCREF(node); - self->this = node; - - Py_DECREF(self->last); - Py_INCREF(node); - self->last = node; - - if (self->start_event_obj) { - PyObject* res; - PyObject* action = self->start_event_obj; - res = PyTuple_Pack(2, action, node); - if (res) { - PyList_Append(self->events, res); - Py_DECREF(res); - } else - PyErr_Clear(); /* FIXME: propagate error */ - } - - return node; - - error: - Py_DECREF(node); - return NULL; -} - -LOCAL(PyObject*) -treebuilder_handle_data(TreeBuilderObject* self, PyObject* data) -{ - if (!self->data) { - if (self->last == Py_None) { - /* ignore calls to data before the first call to start */ - Py_RETURN_NONE; - } - /* store the first item as is */ - Py_INCREF(data); self->data = data; - } else { - /* more than one item; use a list to collect items */ - if (PyBytes_CheckExact(self->data) && Py_REFCNT(self->data) == 1 && - PyBytes_CheckExact(data) && PyBytes_GET_SIZE(data) == 1) { - /* XXX this code path unused in Python 3? */ - /* expat often generates single character data sections; handle - the most common case by resizing the existing string... */ - Py_ssize_t size = PyBytes_GET_SIZE(self->data); - if (_PyBytes_Resize(&self->data, size + 1) < 0) - return NULL; - PyBytes_AS_STRING(self->data)[size] = PyBytes_AS_STRING(data)[0]; - } else if (PyList_CheckExact(self->data)) { - if (PyList_Append(self->data, data) < 0) - return NULL; - } else { - PyObject* list = PyList_New(2); - if (!list) - return NULL; - PyList_SET_ITEM(list, 0, self->data); - Py_INCREF(data); PyList_SET_ITEM(list, 1, data); - self->data = list; - } - } - - Py_RETURN_NONE; -} - -LOCAL(PyObject*) -treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag) -{ - PyObject* item; - - if (self->data) { - if (self->this == self->last) { - if (treebuilder_set_element_text(self->last, self->data)) - return NULL; - } else { - if (treebuilder_set_element_tail(self->last, self->data)) - return NULL; - } - self->data = NULL; - } - - if (self->index == 0) { - PyErr_SetString( - PyExc_IndexError, - "pop from empty stack" - ); - return NULL; - } - - self->index--; - - item = PyList_GET_ITEM(self->stack, self->index); - Py_INCREF(item); - - Py_DECREF(self->last); - - self->last = self->this; - self->this = item; - - if (self->end_event_obj) { - PyObject* res; - PyObject* action = self->end_event_obj; - PyObject* node = (PyObject*) self->last; - res = PyTuple_Pack(2, action, node); - if (res) { - PyList_Append(self->events, res); - Py_DECREF(res); - } else - PyErr_Clear(); /* FIXME: propagate error */ - } - - Py_INCREF(self->last); - return (PyObject*) self->last; -} - -LOCAL(void) -treebuilder_handle_namespace(TreeBuilderObject* self, int start, - PyObject *prefix, PyObject *uri) -{ - PyObject* res; - PyObject* action; - PyObject* parcel; - - if (!self->events) - return; - - if (start) { - if (!self->start_ns_event_obj) - return; - action = self->start_ns_event_obj; - parcel = Py_BuildValue("OO", prefix, uri); - if (!parcel) - return; - Py_INCREF(action); - } else { - if (!self->end_ns_event_obj) - return; - action = self->end_ns_event_obj; - Py_INCREF(action); - parcel = Py_None; - Py_INCREF(parcel); - } - - res = PyTuple_New(2); - - if (res) { - PyTuple_SET_ITEM(res, 0, action); - PyTuple_SET_ITEM(res, 1, parcel); - PyList_Append(self->events, res); - Py_DECREF(res); - } - else { - Py_DECREF(action); - Py_DECREF(parcel); - PyErr_Clear(); /* FIXME: propagate error */ - } -} - -/* -------------------------------------------------------------------- */ -/* methods (in alphabetical order) */ - -static PyObject* -treebuilder_data(TreeBuilderObject* self, PyObject* args) -{ - PyObject* data; - if (!PyArg_ParseTuple(args, "O:data", &data)) - return NULL; - - return treebuilder_handle_data(self, data); -} - -static PyObject* -treebuilder_end(TreeBuilderObject* self, PyObject* args) -{ - PyObject* tag; - if (!PyArg_ParseTuple(args, "O:end", &tag)) - return NULL; - - return treebuilder_handle_end(self, tag); -} - -LOCAL(PyObject*) -treebuilder_done(TreeBuilderObject* self) -{ - PyObject* res; - - /* FIXME: check stack size? */ - - if (self->root) - res = self->root; - else - res = Py_None; - - Py_INCREF(res); - return res; -} - -static PyObject* -treebuilder_close(TreeBuilderObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":close")) - return NULL; - - return treebuilder_done(self); -} - -static PyObject* -treebuilder_start(TreeBuilderObject* self, PyObject* args) -{ - PyObject* tag; - PyObject* attrib = Py_None; - if (!PyArg_ParseTuple(args, "O|O:start", &tag, &attrib)) - return NULL; - - return treebuilder_handle_start(self, tag, attrib); -} - -static PyMethodDef treebuilder_methods[] = { - {"data", (PyCFunction) treebuilder_data, METH_VARARGS}, - {"start", (PyCFunction) treebuilder_start, METH_VARARGS}, - {"end", (PyCFunction) treebuilder_end, METH_VARARGS}, - {"close", (PyCFunction) treebuilder_close, METH_VARARGS}, - {NULL, NULL} -}; - -static PyTypeObject TreeBuilder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.TreeBuilder", sizeof(TreeBuilderObject), 0, - /* methods */ - (destructor)treebuilder_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)treebuilder_gc_traverse, /* tp_traverse */ - (inquiry)treebuilder_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - treebuilder_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 */ - (initproc)treebuilder_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - treebuilder_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* ==================================================================== */ -/* the expat interface */ - -#include "expat.h" -#include "pyexpat.h" - -/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be - * cached globally without being in per-module state. - */ -static struct PyExpat_CAPI *expat_capi; -#define EXPAT(func) (expat_capi->func) - -static XML_Memory_Handling_Suite ExpatMemoryHandler = { - PyObject_Malloc, PyObject_Realloc, PyObject_Free}; - -typedef struct { - PyObject_HEAD - - XML_Parser parser; - - PyObject *target; - PyObject *entity; - - PyObject *names; - - PyObject *handle_start; - PyObject *handle_data; - PyObject *handle_end; - - PyObject *handle_comment; - PyObject *handle_pi; - PyObject *handle_doctype; - - PyObject *handle_close; - -} XMLParserObject; - -#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type) - -/* helpers */ - -LOCAL(PyObject*) -makeuniversal(XMLParserObject* self, const char* string) -{ - /* convert a UTF-8 tag/attribute name from the expat parser - to a universal name string */ - - Py_ssize_t size = (Py_ssize_t) strlen(string); - PyObject* key; - PyObject* value; - - /* look the 'raw' name up in the names dictionary */ - key = PyBytes_FromStringAndSize(string, size); - if (!key) - return NULL; - - value = PyDict_GetItem(self->names, key); - - if (value) { - Py_INCREF(value); - } else { - /* new name. convert to universal name, and decode as - necessary */ - - PyObject* tag; - char* p; - Py_ssize_t i; - - /* look for namespace separator */ - for (i = 0; i < size; i++) - if (string[i] == '}') - break; - if (i != size) { - /* convert to universal name */ - tag = PyBytes_FromStringAndSize(NULL, size+1); - if (tag == NULL) { - Py_DECREF(key); - return NULL; - } - p = PyBytes_AS_STRING(tag); - p[0] = '{'; - memcpy(p+1, string, size); - size++; - } else { - /* plain name; use key as tag */ - Py_INCREF(key); - tag = key; - } - - /* decode universal name */ - p = PyBytes_AS_STRING(tag); - value = PyUnicode_DecodeUTF8(p, size, "strict"); - Py_DECREF(tag); - if (!value) { - Py_DECREF(key); - return NULL; - } - - /* add to names dictionary */ - if (PyDict_SetItem(self->names, key, value) < 0) { - Py_DECREF(key); - Py_DECREF(value); - return NULL; - } - } - - Py_DECREF(key); - return value; -} - -/* Set the ParseError exception with the given parameters. - * If message is not NULL, it's used as the error string. Otherwise, the - * message string is the default for the given error_code. -*/ -static void -expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column, - const char *message) -{ - PyObject *errmsg, *error, *position, *code; - elementtreestate *st = ET_STATE_GLOBAL; - - errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd", - message ? message : EXPAT(ErrorString)(error_code), - line, column); - if (errmsg == NULL) - return; - - error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg); - Py_DECREF(errmsg); - if (!error) - return; - - /* Add code and position attributes */ - code = PyLong_FromLong((long)error_code); - if (!code) { - Py_DECREF(error); - return; - } - if (PyObject_SetAttrString(error, "code", code) == -1) { - Py_DECREF(error); - Py_DECREF(code); - return; - } - Py_DECREF(code); - - position = Py_BuildValue("(nn)", line, column); - if (!position) { - Py_DECREF(error); - return; - } - if (PyObject_SetAttrString(error, "position", position) == -1) { - Py_DECREF(error); - Py_DECREF(position); - return; - } - Py_DECREF(position); - - PyErr_SetObject(st->parseerror_obj, error); - Py_DECREF(error); -} - -/* -------------------------------------------------------------------- */ -/* handlers */ - -static void -expat_default_handler(XMLParserObject* self, const XML_Char* data_in, - int data_len) -{ - PyObject* key; - PyObject* value; - PyObject* res; - - if (data_len < 2 || data_in[0] != '&') - return; - - if (PyErr_Occurred()) - return; - - key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict"); - if (!key) - return; - - value = PyDict_GetItem(self->entity, key); - - if (value) { - if (TreeBuilder_CheckExact(self->target)) - res = treebuilder_handle_data( - (TreeBuilderObject*) self->target, value - ); - else if (self->handle_data) - res = PyObject_CallFunction(self->handle_data, "O", value); - else - res = NULL; - Py_XDECREF(res); - } else if (!PyErr_Occurred()) { - /* Report the first error, not the last */ - char message[128] = "undefined entity "; - strncat(message, data_in, data_len < 100?data_len:100); - expat_set_error( - XML_ERROR_UNDEFINED_ENTITY, - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), - message - ); - } - - Py_DECREF(key); -} - -static void -expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, - const XML_Char **attrib_in) -{ - PyObject* res; - PyObject* tag; - PyObject* attrib; - int ok; - - if (PyErr_Occurred()) - return; - - /* tag name */ - tag = makeuniversal(self, tag_in); - if (!tag) - return; /* parser will look for errors */ - - /* attributes */ - if (attrib_in[0]) { - attrib = PyDict_New(); - if (!attrib) - return; - while (attrib_in[0] && attrib_in[1]) { - PyObject* key = makeuniversal(self, attrib_in[0]); - PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict"); - if (!key || !value) { - Py_XDECREF(value); - Py_XDECREF(key); - Py_DECREF(attrib); - return; - } - ok = PyDict_SetItem(attrib, key, value); - Py_DECREF(value); - Py_DECREF(key); - if (ok < 0) { - Py_DECREF(attrib); - return; - } - attrib_in += 2; - } - } else { - /* Pass an empty dictionary on */ - attrib = PyDict_New(); - if (!attrib) - return; - } - - if (TreeBuilder_CheckExact(self->target)) { - /* shortcut */ - res = treebuilder_handle_start((TreeBuilderObject*) self->target, - tag, attrib); - } - else if (self->handle_start) { - res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); - } else - res = NULL; - - Py_DECREF(tag); - Py_DECREF(attrib); - - Py_XDECREF(res); -} - -static void -expat_data_handler(XMLParserObject* self, const XML_Char* data_in, - int data_len) -{ - PyObject* data; - PyObject* res; - - if (PyErr_Occurred()) - return; - - data = PyUnicode_DecodeUTF8(data_in, data_len, "strict"); - if (!data) - return; /* parser will look for errors */ - - if (TreeBuilder_CheckExact(self->target)) - /* shortcut */ - res = treebuilder_handle_data((TreeBuilderObject*) self->target, data); - else if (self->handle_data) - res = PyObject_CallFunction(self->handle_data, "O", data); - else - res = NULL; - - Py_DECREF(data); - - Py_XDECREF(res); -} - -static void -expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) -{ - PyObject* tag; - PyObject* res = NULL; - - if (PyErr_Occurred()) - return; - - if (TreeBuilder_CheckExact(self->target)) - /* shortcut */ - /* the standard tree builder doesn't look at the end tag */ - res = treebuilder_handle_end( - (TreeBuilderObject*) self->target, Py_None - ); - else if (self->handle_end) { - tag = makeuniversal(self, tag_in); - if (tag) { - res = PyObject_CallFunction(self->handle_end, "O", tag); - Py_DECREF(tag); - } - } - - Py_XDECREF(res); -} - -static void -expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, - const XML_Char *uri) -{ - PyObject* sprefix = NULL; - PyObject* suri = NULL; - - if (PyErr_Occurred()) - return; - - if (uri) - suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict"); - else - suri = PyUnicode_FromString(""); - if (!suri) - return; - - if (prefix) - sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict"); - else - sprefix = PyUnicode_FromString(""); - if (!sprefix) { - Py_DECREF(suri); - return; - } - - treebuilder_handle_namespace( - (TreeBuilderObject*) self->target, 1, sprefix, suri - ); - - Py_DECREF(sprefix); - Py_DECREF(suri); -} - -static void -expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) -{ - if (PyErr_Occurred()) - return; - - treebuilder_handle_namespace( - (TreeBuilderObject*) self->target, 0, NULL, NULL - ); -} - -static void -expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in) -{ - PyObject* comment; - PyObject* res; - - if (PyErr_Occurred()) - return; - - if (self->handle_comment) { - comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict"); - if (comment) { - res = PyObject_CallFunction(self->handle_comment, "O", comment); - Py_XDECREF(res); - Py_DECREF(comment); - } - } -} - -static void -expat_start_doctype_handler(XMLParserObject *self, - const XML_Char *doctype_name, - const XML_Char *sysid, - const XML_Char *pubid, - int has_internal_subset) -{ - PyObject *self_pyobj = (PyObject *)self; - PyObject *doctype_name_obj, *sysid_obj, *pubid_obj; - PyObject *parser_doctype = NULL; - PyObject *res = NULL; - - if (PyErr_Occurred()) - return; - - doctype_name_obj = makeuniversal(self, doctype_name); - if (!doctype_name_obj) - return; - - if (sysid) { - sysid_obj = makeuniversal(self, sysid); - if (!sysid_obj) { - Py_DECREF(doctype_name_obj); - return; - } - } else { - Py_INCREF(Py_None); - sysid_obj = Py_None; - } - - if (pubid) { - pubid_obj = makeuniversal(self, pubid); - if (!pubid_obj) { - Py_DECREF(doctype_name_obj); - Py_DECREF(sysid_obj); - return; - } - } else { - Py_INCREF(Py_None); - pubid_obj = Py_None; - } - - /* If the target has a handler for doctype, call it. */ - if (self->handle_doctype) { - res = PyObject_CallFunction(self->handle_doctype, "OOO", - doctype_name_obj, pubid_obj, sysid_obj); - Py_CLEAR(res); - } - - /* Now see if the parser itself has a doctype method. If yes and it's - * a subclass, call it but warn about deprecation. If it's not a subclass - * (i.e. vanilla XMLParser), do nothing. - */ - parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype"); - if (parser_doctype) { - if (!XMLParser_CheckExact(self_pyobj)) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "This method of XMLParser is deprecated. Define" - " doctype() method on the TreeBuilder target.", - 1) < 0) { - goto clear; - } - res = PyObject_CallFunction(parser_doctype, "OOO", - doctype_name_obj, pubid_obj, sysid_obj); - Py_CLEAR(res); - } - } - -clear: - Py_XDECREF(parser_doctype); - Py_DECREF(doctype_name_obj); - Py_DECREF(pubid_obj); - Py_DECREF(sysid_obj); -} - -static void -expat_pi_handler(XMLParserObject* self, const XML_Char* target_in, - const XML_Char* data_in) -{ - PyObject* target; - PyObject* data; - PyObject* res; - - if (PyErr_Occurred()) - return; - - if (self->handle_pi) { - target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); - data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); - if (target && data) { - res = PyObject_CallFunction(self->handle_pi, "OO", target, data); - Py_XDECREF(res); - Py_DECREF(data); - Py_DECREF(target); - } else { - Py_XDECREF(data); - Py_XDECREF(target); - } - } -} - -/* -------------------------------------------------------------------- */ - -static PyObject * -xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0); - if (self) { - self->parser = NULL; - self->target = self->entity = self->names = NULL; - self->handle_start = self->handle_data = self->handle_end = NULL; - self->handle_comment = self->handle_pi = self->handle_close = NULL; - self->handle_doctype = NULL; - } - return (PyObject *)self; -} - -static int -xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - XMLParserObject *self_xp = (XMLParserObject *)self; - PyObject *target = NULL, *html = NULL; - char *encoding = NULL; - static char *kwlist[] = {"html", "target", "encoding", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOz:XMLParser", kwlist, - &html, &target, &encoding)) { - return -1; - } - - self_xp->entity = PyDict_New(); - if (!self_xp->entity) - return -1; - - self_xp->names = PyDict_New(); - if (!self_xp->names) { - Py_CLEAR(self_xp->entity); - return -1; - } - - self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); - if (!self_xp->parser) { - Py_CLEAR(self_xp->entity); - Py_CLEAR(self_xp->names); - PyErr_NoMemory(); - return -1; - } - - if (target) { - Py_INCREF(target); - } else { - target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); - if (!target) { - Py_CLEAR(self_xp->entity); - Py_CLEAR(self_xp->names); - EXPAT(ParserFree)(self_xp->parser); - return -1; - } - } - self_xp->target = target; - - self_xp->handle_start = PyObject_GetAttrString(target, "start"); - self_xp->handle_data = PyObject_GetAttrString(target, "data"); - self_xp->handle_end = PyObject_GetAttrString(target, "end"); - self_xp->handle_comment = PyObject_GetAttrString(target, "comment"); - self_xp->handle_pi = PyObject_GetAttrString(target, "pi"); - self_xp->handle_close = PyObject_GetAttrString(target, "close"); - self_xp->handle_doctype = PyObject_GetAttrString(target, "doctype"); - - PyErr_Clear(); - - /* configure parser */ - EXPAT(SetUserData)(self_xp->parser, self_xp); - EXPAT(SetElementHandler)( - self_xp->parser, - (XML_StartElementHandler) expat_start_handler, - (XML_EndElementHandler) expat_end_handler - ); - EXPAT(SetDefaultHandlerExpand)( - self_xp->parser, - (XML_DefaultHandler) expat_default_handler - ); - EXPAT(SetCharacterDataHandler)( - self_xp->parser, - (XML_CharacterDataHandler) expat_data_handler - ); - if (self_xp->handle_comment) - EXPAT(SetCommentHandler)( - self_xp->parser, - (XML_CommentHandler) expat_comment_handler - ); - if (self_xp->handle_pi) - EXPAT(SetProcessingInstructionHandler)( - self_xp->parser, - (XML_ProcessingInstructionHandler) expat_pi_handler - ); - EXPAT(SetStartDoctypeDeclHandler)( - self_xp->parser, - (XML_StartDoctypeDeclHandler) expat_start_doctype_handler - ); - EXPAT(SetUnknownEncodingHandler)( - self_xp->parser, - EXPAT(DefaultUnknownEncodingHandler), NULL - ); - - return 0; -} - -static int -xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) -{ - Py_VISIT(self->handle_close); - Py_VISIT(self->handle_pi); - Py_VISIT(self->handle_comment); - Py_VISIT(self->handle_end); - Py_VISIT(self->handle_data); - Py_VISIT(self->handle_start); - - Py_VISIT(self->target); - Py_VISIT(self->entity); - Py_VISIT(self->names); - - return 0; -} - -static int -xmlparser_gc_clear(XMLParserObject *self) -{ - EXPAT(ParserFree)(self->parser); - - Py_CLEAR(self->handle_close); - Py_CLEAR(self->handle_pi); - Py_CLEAR(self->handle_comment); - Py_CLEAR(self->handle_end); - Py_CLEAR(self->handle_data); - Py_CLEAR(self->handle_start); - Py_CLEAR(self->handle_doctype); - - Py_CLEAR(self->target); - Py_CLEAR(self->entity); - Py_CLEAR(self->names); - - return 0; -} - -static void -xmlparser_dealloc(XMLParserObject* self) -{ - PyObject_GC_UnTrack(self); - xmlparser_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -LOCAL(PyObject*) -expat_parse(XMLParserObject* self, const char* data, int data_len, int final) -{ - int ok; - - assert(!PyErr_Occurred()); - ok = EXPAT(Parse)(self->parser, data, data_len, final); - - if (PyErr_Occurred()) - return NULL; - - if (!ok) { - expat_set_error( - EXPAT(GetErrorCode)(self->parser), - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), - NULL - ); - return NULL; - } - - Py_RETURN_NONE; -} - -static PyObject* -xmlparser_close(XMLParserObject* self, PyObject* args) -{ - /* end feeding data to parser */ - - PyObject* res; - if (!PyArg_ParseTuple(args, ":close")) - return NULL; - - res = expat_parse(self, "", 0, 1); - if (!res) - return NULL; - - if (TreeBuilder_CheckExact(self->target)) { - Py_DECREF(res); - return treebuilder_done((TreeBuilderObject*) self->target); - } - else if (self->handle_close) { - Py_DECREF(res); - return PyObject_CallFunction(self->handle_close, ""); - } - else { - return res; - } -} - -static PyObject* -xmlparser_feed(XMLParserObject* self, PyObject* arg) -{ - /* feed data to parser */ - - if (PyUnicode_Check(arg)) { - Py_ssize_t data_len; - const char *data = PyUnicode_AsUTF8AndSize(arg, &data_len); - if (data == NULL) - return NULL; - if (data_len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - /* Explicitly set UTF-8 encoding. Return code ignored. */ - (void)EXPAT(SetEncoding)(self->parser, "utf-8"); - return expat_parse(self, data, (int)data_len, 0); - } - else { - Py_buffer view; - PyObject *res; - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0) - return NULL; - if (view.len > INT_MAX) { - PyBuffer_Release(&view); - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - res = expat_parse(self, view.buf, (int)view.len, 0); - PyBuffer_Release(&view); - return res; - } -} - -static PyObject* -xmlparser_parse_whole(XMLParserObject* self, PyObject* args) -{ - /* (internal) parse the whole input, until end of stream */ - PyObject* reader; - PyObject* buffer; - PyObject* temp; - PyObject* res; - - PyObject* fileobj; - if (!PyArg_ParseTuple(args, "O:_parse", &fileobj)) - return NULL; - - reader = PyObject_GetAttrString(fileobj, "read"); - if (!reader) - return NULL; - - /* read from open file object */ - for (;;) { - - buffer = PyObject_CallFunction(reader, "i", 64*1024); - - if (!buffer) { - /* read failed (e.g. due to KeyboardInterrupt) */ - Py_DECREF(reader); - return NULL; - } - - if (PyUnicode_CheckExact(buffer)) { - /* A unicode object is encoded into bytes using UTF-8 */ - if (PyUnicode_GET_LENGTH(buffer) == 0) { - Py_DECREF(buffer); - break; - } - temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass"); - Py_DECREF(buffer); - if (!temp) { - /* Propagate exception from PyUnicode_AsEncodedString */ - Py_DECREF(reader); - return NULL; - } - buffer = temp; - } - else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) { - Py_DECREF(buffer); - break; - } - - if (PyBytes_GET_SIZE(buffer) > INT_MAX) { - Py_DECREF(buffer); - Py_DECREF(reader); - PyErr_SetString(PyExc_OverflowError, "size does not fit in an int"); - return NULL; - } - res = expat_parse( - self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0 - ); - - Py_DECREF(buffer); - - if (!res) { - Py_DECREF(reader); - return NULL; - } - Py_DECREF(res); - - } - - Py_DECREF(reader); - - res = expat_parse(self, "", 0, 1); - - if (res && TreeBuilder_CheckExact(self->target)) { - Py_DECREF(res); - return treebuilder_done((TreeBuilderObject*) self->target); - } - - return res; -} - -static PyObject* -xmlparser_doctype(XMLParserObject *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyObject* -xmlparser_setevents(XMLParserObject *self, PyObject* args) -{ - /* activate element event reporting */ - Py_ssize_t i, seqlen; - TreeBuilderObject *target; - + PyObject *return_value = NULL; PyObject *events_queue; PyObject *events_to_report = Py_None; - PyObject *events_seq; - if (!PyArg_ParseTuple(args, "O!|O:_setevents", &PyList_Type, &events_queue, - &events_to_report)) - return NULL; - if (!TreeBuilder_CheckExact(self->target)) { - PyErr_SetString( - PyExc_TypeError, - "event handling only supported for ElementTree.TreeBuilder " - "targets" - ); - return NULL; - } + if (!PyArg_ParseTuple(args, "O!|O:_setevents", + &PyList_Type, &events_queue, &events_to_report)) + goto exit; + return_value = _elementtree_XMLParser__setevents_impl(self, events_queue, events_to_report); - target = (TreeBuilderObject*) self->target; - - Py_INCREF(events_queue); - Py_XDECREF(target->events); - target->events = events_queue; - - /* clear out existing events */ - Py_CLEAR(target->start_event_obj); - Py_CLEAR(target->end_event_obj); - Py_CLEAR(target->start_ns_event_obj); - Py_CLEAR(target->end_ns_event_obj); - - if (events_to_report == Py_None) { - /* default is "end" only */ - target->end_event_obj = PyUnicode_FromString("end"); - Py_RETURN_NONE; - } - - if (!(events_seq = PySequence_Fast(events_to_report, - "events must be a sequence"))) { - return NULL; - } - - seqlen = PySequence_Size(events_seq); - for (i = 0; i < seqlen; ++i) { - PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i); - char *event_name = NULL; - if (PyUnicode_Check(event_name_obj)) { - event_name = _PyUnicode_AsString(event_name_obj); - } else if (PyBytes_Check(event_name_obj)) { - event_name = PyBytes_AS_STRING(event_name_obj); - } - - if (event_name == NULL) { - Py_DECREF(events_seq); - PyErr_Format(PyExc_ValueError, "invalid events sequence"); - return NULL; - } else if (strcmp(event_name, "start") == 0) { - Py_INCREF(event_name_obj); - target->start_event_obj = event_name_obj; - } else if (strcmp(event_name, "end") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->end_event_obj); - target->end_event_obj = event_name_obj; - } else if (strcmp(event_name, "start-ns") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->start_ns_event_obj); - target->start_ns_event_obj = event_name_obj; - EXPAT(SetNamespaceDeclHandler)( - self->parser, - (XML_StartNamespaceDeclHandler) expat_start_ns_handler, - (XML_EndNamespaceDeclHandler) expat_end_ns_handler - ); - } else if (strcmp(event_name, "end-ns") == 0) { - Py_INCREF(event_name_obj); - Py_XDECREF(target->end_ns_event_obj); - target->end_ns_event_obj = event_name_obj; - EXPAT(SetNamespaceDeclHandler)( - self->parser, - (XML_StartNamespaceDeclHandler) expat_start_ns_handler, - (XML_EndNamespaceDeclHandler) expat_end_ns_handler - ); - } else { - Py_DECREF(events_seq); - PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name); - return NULL; - } - } - - Py_DECREF(events_seq); - Py_RETURN_NONE; +exit: + return return_value; } - -static PyMethodDef xmlparser_methods[] = { - {"feed", (PyCFunction) xmlparser_feed, METH_O}, - {"close", (PyCFunction) xmlparser_close, METH_VARARGS}, - {"_parse_whole", (PyCFunction) xmlparser_parse_whole, METH_VARARGS}, - {"_setevents", (PyCFunction) xmlparser_setevents, METH_VARARGS}, - {"doctype", (PyCFunction) xmlparser_doctype, METH_VARARGS}, - {NULL, NULL} -}; - -static PyObject* -xmlparser_getattro(XMLParserObject* self, PyObject* nameobj) -{ - if (PyUnicode_Check(nameobj)) { - PyObject* res; - if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0) - res = self->entity; - else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0) - res = self->target; - else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) { - return PyUnicode_FromFormat( - "Expat %d.%d.%d", XML_MAJOR_VERSION, - XML_MINOR_VERSION, XML_MICRO_VERSION); - } - else - goto generic; - - Py_INCREF(res); - return res; - } - generic: - return PyObject_GenericGetAttr((PyObject*) self, nameobj); -} - -static PyTypeObject XMLParser_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0, - /* methods */ - (destructor)xmlparser_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 */ - (getattrofunc)xmlparser_getattro, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)xmlparser_gc_traverse, /* tp_traverse */ - (inquiry)xmlparser_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - xmlparser_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 */ - (initproc)xmlparser_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - xmlparser_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* ==================================================================== */ -/* python module interface */ - -static PyMethodDef _functions[] = { - {"SubElement", (PyCFunction) subelement, METH_VARARGS | METH_KEYWORDS}, - {NULL, NULL} -}; - - -static struct PyModuleDef elementtreemodule = { - PyModuleDef_HEAD_INIT, - "_elementtree", - NULL, - sizeof(elementtreestate), - _functions, - NULL, - elementtree_traverse, - elementtree_clear, - elementtree_free -}; - -PyMODINIT_FUNC -PyInit__elementtree(void) -{ - PyObject *m, *temp; - elementtreestate *st; - - m = PyState_FindModule(&elementtreemodule); - if (m) { - Py_INCREF(m); - return m; - } - - /* Initialize object types */ - if (PyType_Ready(&ElementIter_Type) < 0) - return NULL; - if (PyType_Ready(&TreeBuilder_Type) < 0) - return NULL; - if (PyType_Ready(&Element_Type) < 0) - return NULL; - if (PyType_Ready(&XMLParser_Type) < 0) - return NULL; - - m = PyModule_Create(&elementtreemodule); - if (!m) - return NULL; - st = ET_STATE(m); - - if (!(temp = PyImport_ImportModule("copy"))) - return NULL; - st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); - Py_XDECREF(temp); - - if (!(st->elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) - return NULL; - - /* link against pyexpat */ - expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); - if (expat_capi) { - /* check that it's usable */ - if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || - (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) || - expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || - expat_capi->MINOR_VERSION != XML_MINOR_VERSION || - expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { - PyErr_SetString(PyExc_ImportError, - "pyexpat version is incompatible"); - return NULL; - } - } else { - return NULL; - } - - st->parseerror_obj = PyErr_NewException( - "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL - ); - Py_INCREF(st->parseerror_obj); - PyModule_AddObject(m, "ParseError", st->parseerror_obj); - - Py_INCREF((PyObject *)&Element_Type); - PyModule_AddObject(m, "Element", (PyObject *)&Element_Type); - - Py_INCREF((PyObject *)&TreeBuilder_Type); - PyModule_AddObject(m, "TreeBuilder", (PyObject *)&TreeBuilder_Type); - - Py_INCREF((PyObject *)&XMLParser_Type); - PyModule_AddObject(m, "XMLParser", (PyObject *)&XMLParser_Type); - - return m; -} +/*[clinic end generated code: output=119aed84c1545187 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 4 16:00:09 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 04 May 2015 14:00:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324001=3A_Argument?= =?utf-8?q?_Clinic_converters_now_use_accept=3D=7Btype=7D?= Message-ID: <20150504140008.11932.83427@psf.io> https://hg.python.org/cpython/rev/41fb7fd04b5d changeset: 95879:41fb7fd04b5d user: Larry Hastings date: Mon May 04 06:59:46 2015 -0700 summary: Issue #24001: Argument Clinic converters now use accept={type} instead of types={'type'} to specify the types the converter accepts. files: Misc/NEWS | 3 + Modules/_dbmmodule.c | 8 +- Modules/_elementtree.c | 4 +- Modules/_gdbmmodule.c | 4 +- Modules/_io/_iomodule.c | 8 +- Modules/_io/bufferedio.c | 16 +- Modules/_io/bytesio.c | 4 +- Modules/_io/fileio.c | 4 +- Modules/_io/textio.c | 8 +- Modules/_ssl.c | 8 +- Modules/_tkinter.c | 6 +- Modules/arraymodule.c | 8 +- Modules/cjkcodecs/multibytecodec.c | 8 +- Modules/pyexpat.c | 10 +- Modules/unicodedata.c | 44 ++-- Tools/clinic/clinic.py | 144 ++++++++++------ 16 files changed, 164 insertions(+), 123 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -68,6 +68,9 @@ Tools/Demos ----------- +- Issue #24001: Argument Clinic converters now use accept={type} + instead of types={'type'} to specify the types the converter accepts. + - Issue #23330: h2py now supports arbitrary filenames in #include. - Issue #24031: make patchcheck now supports git checkouts, too. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -274,7 +274,7 @@ /*[clinic input] _dbm.dbm.get - key: str(types={'str', 'robuffer'}, length=True) + key: str(accept={str, robuffer}, length=True) default: object(c_default="NULL") = b'' / @@ -284,7 +284,7 @@ static PyObject * _dbm_dbm_get_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=b44f95eba8203d93 input=fee97bbe85e84822]*/ +/*[clinic end generated code: output=b44f95eba8203d93 input=3c7c1afd9c508457]*/ { datum dbm_key, val; @@ -301,7 +301,7 @@ /*[clinic input] _dbm.dbm.setdefault - key: str(types={'str', 'robuffer'}, length=True) + key: str(accept={str, robuffer}, length=True) default: object(c_default="NULL") = b'' / @@ -314,7 +314,7 @@ _dbm_dbm_setdefault_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=52545886cf272161 input=6a3b99ae91f20203]*/ +/*[clinic end generated code: output=52545886cf272161 input=a66fcb7f18ee2f50]*/ { datum dbm_key, val; Py_ssize_t tmp_size; diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -3206,14 +3206,14 @@ html: object = NULL target: object = NULL - encoding: str(nullable=True) = NULL + encoding: str(accept={str, NoneType}) = NULL [clinic start generated code]*/ static int _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html, PyObject *target, const char *encoding) -/*[clinic end generated code: output=d6a16c63dda54441 input=a870da39c80d7d68]*/ +/*[clinic end generated code: output=d6a16c63dda54441 input=155bc5695baafffd]*/ { self->entity = PyDict_New(); if (!self->entity) diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -383,7 +383,7 @@ /*[clinic input] _gdbm.gdbm.nextkey - key: str(types={'str', 'robuffer'}, length=True) + key: str(accept={str, robuffer}, length=True) / Returns the key that follows key in the traversal. @@ -400,7 +400,7 @@ static PyObject * _gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length) -/*[clinic end generated code: output=192ab892de6eb2f6 input=df8e8828201214a6]*/ +/*[clinic end generated code: output=192ab892de6eb2f6 input=1eb2ff9b4b0e6ffd]*/ { PyObject *v; datum dbm_key, nextkey; diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -100,9 +100,9 @@ file: object mode: str = "r" buffering: int = -1 - encoding: str(nullable=True) = NULL - errors: str(nullable=True) = NULL - newline: str(nullable=True) = NULL + encoding: str(accept={str, NoneType}) = NULL + errors: str(accept={str, NoneType}) = NULL + newline: str(accept={str, NoneType}) = NULL closefd: int(c_default="1") = True opener: object = None @@ -230,7 +230,7 @@ _io_open_impl(PyModuleDef *module, PyObject *file, const char *mode, int buffering, const char *encoding, const char *errors, const char *newline, int closefd, PyObject *opener) -/*[clinic end generated code: output=7615d0d746eb14d2 input=0541ce15691a82f2]*/ +/*[clinic end generated code: output=7615d0d746eb14d2 input=f4e1ca75223987bc]*/ { unsigned i; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -101,26 +101,26 @@ /*[clinic input] _io._BufferedIOBase.readinto - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer) -/*[clinic end generated code: output=8c8cda6684af8038 input=f8242a06c21763a0]*/ +/*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/ { return _bufferediobase_readinto_generic(self, buffer, 0); } /*[clinic input] _io._BufferedIOBase.readinto1 - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) -/*[clinic end generated code: output=358623e4fd2b69d3 input=2003e706c730bd21]*/ +/*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/ { return _bufferediobase_readinto_generic(self, buffer, 1); } @@ -1065,26 +1065,26 @@ /*[clinic input] _io._Buffered.readinto - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer) -/*[clinic end generated code: output=bcb376580b1d8170 input=962b7496eac38b3a]*/ +/*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/ { return _buffered_readinto_generic(self, buffer, 0); } /*[clinic input] _io._Buffered.readinto1 - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / [clinic start generated code]*/ static PyObject * _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer) -/*[clinic end generated code: output=6e5c6ac5868205d6 input=834614d93f0adeb5]*/ +/*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/ { return _buffered_readinto_generic(self, buffer, 1); } diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -541,7 +541,7 @@ /*[clinic input] _io.BytesIO.readinto - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / Read up to len(buffer) bytes into buffer. @@ -552,7 +552,7 @@ static PyObject * _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer) -/*[clinic end generated code: output=a5d407217dcf0639 input=d289da851c7c4159]*/ +/*[clinic end generated code: output=a5d407217dcf0639 input=71581f32635c3a31]*/ { Py_ssize_t len, n; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -603,7 +603,7 @@ /*[clinic input] _io.FileIO.readinto - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) / Same as RawIOBase.readinto(). @@ -611,7 +611,7 @@ static PyObject * _io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer) -/*[clinic end generated code: output=b01a5a22c8415cb4 input=5edd8327498d468c]*/ +/*[clinic end generated code: output=b01a5a22c8415cb4 input=4721d7b68b154eaf]*/ { Py_ssize_t n; int err; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -789,9 +789,9 @@ /*[clinic input] _io.TextIOWrapper.__init__ buffer: object - encoding: str(nullable=True) = NULL - errors: str(nullable=True) = NULL - newline: str(nullable=True) = NULL + encoding: str(accept={str, NoneType}) = NULL + errors: str(accept={str, NoneType}) = NULL + newline: str(accept={str, NoneType}) = NULL line_buffering: int(c_default="0") = False write_through: int(c_default="0") = False @@ -830,7 +830,7 @@ const char *encoding, const char *errors, const char *newline, int line_buffering, int write_through) -/*[clinic end generated code: output=56a83402ce2a8381 input=1f20decb8d54a4ec]*/ +/*[clinic end generated code: output=56a83402ce2a8381 input=3126cb3101a2c99b]*/ { PyObject *raw, *codec_info = NULL; _PyIO_State *state = NULL; diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1877,7 +1877,7 @@ _ssl._SSLSocket.read size as len: int [ - buffer: Py_buffer(types={'rwbuffer'}) + buffer: Py_buffer(accept={rwbuffer}) ] / @@ -1887,7 +1887,7 @@ static PyObject * _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, Py_buffer *buffer) -/*[clinic end generated code: output=00097776cec2a0af input=4a0bbd2859e817b0]*/ +/*[clinic end generated code: output=00097776cec2a0af input=ff157eb918d0905b]*/ { PyObject *dest = NULL; char *mem; @@ -3799,7 +3799,7 @@ /* helper routines for seeding the SSL PRNG */ /*[clinic input] _ssl.RAND_add - string as view: Py_buffer(types={'str', 'buffer'}) + string as view: Py_buffer(accept={str, buffer}) entropy: double / @@ -3811,7 +3811,7 @@ static PyObject * _ssl_RAND_add_impl(PyModuleDef *module, Py_buffer *view, double entropy) -/*[clinic end generated code: output=0f8d5c8cce328958 input=c98b11d606b354bc]*/ +/*[clinic end generated code: output=0f8d5c8cce328958 input=580c85e6a3a4fe29]*/ { const char *buf; Py_ssize_t len, written; diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -3101,7 +3101,7 @@ /*[clinic input] _tkinter.create - screenName: str(nullable=True) = NULL + screenName: str(accept={str, NoneType}) = NULL baseName: str = NULL className: str = "Tk" interactive: int(c_default="0") = False @@ -3110,7 +3110,7 @@ if false, then Tk_Init() doesn't get called sync: int(c_default="0") = False if true, then pass -sync to wish - use: str(nullable=True) = NULL + use: str(accept={str, NoneType}) = NULL if not None, then pass -use to wish / @@ -3121,7 +3121,7 @@ const char *baseName, const char *className, int interactive, int wantobjects, int wantTk, int sync, const char *use) -/*[clinic end generated code: output=b8847800fc3b27eb input=c133c59a99dd0086]*/ +/*[clinic end generated code: output=b8847800fc3b27eb input=0d522aad1cb0ca0e]*/ { /* XXX baseName is not used anymore; * try getting rid of it. */ diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1600,7 +1600,7 @@ /*[clinic input] array.array.fromstring - buffer: Py_buffer(types={'str', 'buffer'}) + buffer: Py_buffer(accept={str, buffer}) / Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method). @@ -1610,7 +1610,7 @@ static PyObject * array_array_fromstring_impl(arrayobject *self, Py_buffer *buffer) -/*[clinic end generated code: output=31c4baa779df84ce input=fdde1a56cbe2b05b]*/ +/*[clinic end generated code: output=31c4baa779df84ce input=a3341a512e11d773]*/ { if (PyErr_WarnEx(PyExc_DeprecationWarning, "fromstring() is deprecated. Use frombytes() instead.", 2) != 0) @@ -1929,7 +1929,7 @@ array._array_reconstructor arraytype: object(type="PyTypeObject *") - typecode: int(types={'str'}) + typecode: int(accept={str}) mformat_code: int(type="enum machine_format_code") items: object / @@ -1942,7 +1942,7 @@ int typecode, enum machine_format_code mformat_code, PyObject *items) -/*[clinic end generated code: output=6ecbf0e8e4d92ab9 input=a9ae223306d7b262]*/ +/*[clinic end generated code: output=6ecbf0e8e4d92ab9 input=2464dc8f4c7736b5]*/ { PyObject *converted_items; PyObject *result; diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -544,7 +544,7 @@ _multibytecodec.MultibyteCodec.encode input: object - errors: str(nullable=True) = NULL + errors: str(accept={str, NoneType}) = NULL Return an encoded string version of `input'. @@ -558,7 +558,7 @@ _multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, PyObject *input, const char *errors) -/*[clinic end generated code: output=7b26652045ba56a9 input=252e7ee695867b2d]*/ +/*[clinic end generated code: output=7b26652045ba56a9 input=05f6ced3c8dd0582]*/ { MultibyteCodec_State state; PyObject *errorcb, *r, *ucvt; @@ -613,7 +613,7 @@ _multibytecodec.MultibyteCodec.decode input: Py_buffer - errors: str(nullable=True) = NULL + errors: str(accept={str, NoneType}) = NULL Decodes 'input'. @@ -627,7 +627,7 @@ _multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, Py_buffer *input, const char *errors) -/*[clinic end generated code: output=ff419f65bad6cc77 input=37e1d9236e3ce8f3]*/ +/*[clinic end generated code: output=ff419f65bad6cc77 input=a7d45f87f75e5e02]*/ { MultibyteCodec_State state; MultibyteDecodeBuffer buf; diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -911,7 +911,7 @@ /*[clinic input] pyexpat.xmlparser.ExternalEntityParserCreate - context: str(nullable=True) + context: str(accept={str, NoneType}) encoding: str = NULL / @@ -922,7 +922,7 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding) -/*[clinic end generated code: output=535cda9d7a0fbcd6 input=283206575d960272]*/ +/*[clinic end generated code: output=535cda9d7a0fbcd6 input=b906714cc122c322]*/ { xmlparseobject *new_parser; int i; @@ -1546,8 +1546,8 @@ /*[clinic input] pyexpat.ParserCreate - encoding: str(nullable=True) = NULL - namespace_separator: str(nullable=True) = NULL + encoding: str(accept={str, NoneType}) = NULL + namespace_separator: str(accept={str, NoneType}) = NULL intern: object = NULL Return a new XML parser object. @@ -1556,7 +1556,7 @@ static PyObject * pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern) -/*[clinic end generated code: output=81fccd233e1743a8 input=71b9f471aa6f8f86]*/ +/*[clinic end generated code: output=81fccd233e1743a8 input=23d29704acad385d]*/ { PyObject *result; int intern_decref = 0; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -107,7 +107,7 @@ unicodedata.UCD.decimal self: self - chr: int(types={'str'}) + chr: int(accept={str}) default: object=NULL / @@ -121,7 +121,7 @@ static PyObject * unicodedata_UCD_decimal_impl(PyObject *self, int chr, PyObject *default_value) -/*[clinic end generated code: output=be23376e1a185231 input=3acf7f2238874a49]*/ +/*[clinic end generated code: output=be23376e1a185231 input=933f8107993f23d0]*/ { int have_old = 0; long rc; @@ -160,7 +160,7 @@ unicodedata.UCD.digit self: self - chr: int(types={'str'}) + chr: int(accept={str}) default: object=NULL / @@ -173,7 +173,7 @@ static PyObject * unicodedata_UCD_digit_impl(PyObject *self, int chr, PyObject *default_value) -/*[clinic end generated code: output=96e18c950171fd2f input=733f093b399f5ab6]*/ +/*[clinic end generated code: output=96e18c950171fd2f input=e27d6e4565cd29f2]*/ { long rc; Py_UCS4 c = (Py_UCS4)chr; @@ -195,7 +195,7 @@ unicodedata.UCD.numeric self: self - chr: int(types={'str'}) + chr: int(accept={str}) default: object=NULL / @@ -209,7 +209,7 @@ static PyObject * unicodedata_UCD_numeric_impl(PyObject *self, int chr, PyObject *default_value) -/*[clinic end generated code: output=53ce281fe85b10c4 input=c5875fa7cc768fb2]*/ +/*[clinic end generated code: output=53ce281fe85b10c4 input=fdf5871a5542893c]*/ { int have_old = 0; double rc; @@ -247,7 +247,7 @@ unicodedata.UCD.category self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the general category assigned to the character chr as string. @@ -255,7 +255,7 @@ static PyObject * unicodedata_UCD_category_impl(PyObject *self, int chr) -/*[clinic end generated code: output=8571539ee2e6783a input=f5edd6fd04bd455d]*/ +/*[clinic end generated code: output=8571539ee2e6783a input=27d6f3d85050bc06]*/ { int index; Py_UCS4 c = (Py_UCS4)chr; @@ -272,7 +272,7 @@ unicodedata.UCD.bidirectional self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the bidirectional class assigned to the character chr as string. @@ -282,7 +282,7 @@ static PyObject * unicodedata_UCD_bidirectional_impl(PyObject *self, int chr) -/*[clinic end generated code: output=d36310ce2039bb92 input=5ce2f877b35305b5]*/ +/*[clinic end generated code: output=d36310ce2039bb92 input=b3d8f42cebfcf475]*/ { int index; Py_UCS4 c = (Py_UCS4)chr; @@ -301,7 +301,7 @@ unicodedata.UCD.combining -> int self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the canonical combining class assigned to the character chr as integer. @@ -311,7 +311,7 @@ static int unicodedata_UCD_combining_impl(PyObject *self, int chr) -/*[clinic end generated code: output=cad056d0cb6a5920 input=9125ea7d50b319e7]*/ +/*[clinic end generated code: output=cad056d0cb6a5920 input=9f2d6b2a95d0a22a]*/ { int index; Py_UCS4 c = (Py_UCS4)chr; @@ -328,7 +328,7 @@ unicodedata.UCD.mirrored -> int self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the mirrored property assigned to the character chr as integer. @@ -339,7 +339,7 @@ static int unicodedata_UCD_mirrored_impl(PyObject *self, int chr) -/*[clinic end generated code: output=2532dbf8121b50e6 input=4e51e8aaf8d7e23e]*/ +/*[clinic end generated code: output=2532dbf8121b50e6 input=5dd400d351ae6f3b]*/ { int index; Py_UCS4 c = (Py_UCS4)chr; @@ -358,7 +358,7 @@ unicodedata.UCD.east_asian_width self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the east asian width assigned to the character chr as string. @@ -366,7 +366,7 @@ static PyObject * unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr) -/*[clinic end generated code: output=484e8537d9ee8197 input=f93c61f37276c8f0]*/ +/*[clinic end generated code: output=484e8537d9ee8197 input=c4854798aab026e0]*/ { int index; Py_UCS4 c = (Py_UCS4)chr; @@ -383,7 +383,7 @@ unicodedata.UCD.decomposition self: self - chr: int(types={'str'}) + chr: int(accept={str}) / Returns the character decomposition mapping assigned to the character chr as string. @@ -393,7 +393,7 @@ static PyObject * unicodedata_UCD_decomposition_impl(PyObject *self, int chr) -/*[clinic end generated code: output=7d699f3ec7565d27 input=7f2c0ee66d75468f]*/ +/*[clinic end generated code: output=7d699f3ec7565d27 input=e4c12459ad68507b]*/ { char decomp[256]; int code, index, count; @@ -1180,7 +1180,7 @@ unicodedata.UCD.name self: self - chr: int(types={'str'}) + chr: int(accept={str}) default: object=NULL / @@ -1192,7 +1192,7 @@ static PyObject * unicodedata_UCD_name_impl(PyObject *self, int chr, PyObject *default_value) -/*[clinic end generated code: output=6bbb37a326407707 input=51ee2f971c918113]*/ +/*[clinic end generated code: output=6bbb37a326407707 input=3e0367f534de56d9]*/ { char name[NAME_MAXLEN]; Py_UCS4 c = (Py_UCS4)chr; @@ -1215,7 +1215,7 @@ unicodedata.UCD.lookup self: self - name: str(types={'str', 'robuffer'}, length=True) + name: str(accept={str, robuffer}, length=True) / Look up character by name. @@ -1227,7 +1227,7 @@ static PyObject * unicodedata_UCD_lookup_impl(PyObject *self, const char *name, Py_ssize_clean_t name_length) -/*[clinic end generated code: output=765cb8186788e6be input=f2bf29706135a590]*/ +/*[clinic end generated code: output=765cb8186788e6be input=2dfe682c2491447a]*/ { Py_UCS4 code; unsigned int index; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -26,8 +26,12 @@ import tempfile import textwrap import traceback +import types import uuid +from types import * +NoneType = type(None) + # TODO: # # soon: @@ -2526,18 +2530,18 @@ if not bitwise: fail("Unsigned shorts must be bitwise (for now).") - at add_legacy_c_converter('C', types={'str'}) + at add_legacy_c_converter('C', accept={str}) class int_converter(CConverter): type = 'int' default_type = int format_unit = 'i' c_ignored_default = "0" - def converter_init(self, *, types={'int'}, type=None): - if types == {'str'}: + def converter_init(self, *, accept={int}, type=None): + if accept == {str}: self.format_unit = 'C' - elif types != {'int'}: - fail("int_converter: illegal 'types' argument " + repr(types)) + elif accept != {int}: + fail("int_converter: illegal 'accept' argument " + repr(accept)) if type != None: self.type = type @@ -2629,17 +2633,22 @@ # -# We define three string conventions for buffer types in the 'types' argument: -# 'buffer' : any object supporting the buffer interface -# 'rwbuffer': any object supporting the buffer interface, but must be writeable -# 'robuffer': any object supporting the buffer interface, but must not be writeable +# We define three conventions for buffer types in the 'accept' argument: # - - at add_legacy_c_converter('s#', types={"str", "robuffer"}, length=True) - at add_legacy_c_converter('y', types={"robuffer"}) - at add_legacy_c_converter('y#', types={"robuffer"}, length=True) - at add_legacy_c_converter('z', nullable=True) - at add_legacy_c_converter('z#', types={"str", "robuffer"}, nullable=True, length=True) +# buffer : any object supporting the buffer interface +# rwbuffer: any object supporting the buffer interface, but must be writeable +# robuffer: any object supporting the buffer interface, but must not be writeable +# + +class buffer: pass +class rwbuffer: pass +class robuffer: pass + + at add_legacy_c_converter('s#', accept={str, robuffer}, length=True) + at add_legacy_c_converter('y', accept={robuffer}) + at add_legacy_c_converter('y#', accept={robuffer}, length=True) + at add_legacy_c_converter('z', accept={str, NoneType}) + at add_legacy_c_converter('z#', accept={str, NoneType}, length=True) # add_legacy_c_converter not supported for es, es#, et, et# # because of their extra encoding argument class str_converter(CConverter): @@ -2647,45 +2656,47 @@ default_type = (str, Null, NoneType) format_unit = 's' - def converter_init(self, *, encoding=None, types={"str"}, - length=False, nullable=False, zeroes=False): + def converter_init(self, *, encoding=None, accept={str}, length=False, zeroes=False): self.length = bool(length) - is_b_or_ba = types == {"bytes", "bytearray"} - is_str = types == {"str"} - is_robuffer = types == {"robuffer"} - is_str_or_robuffer = types == {"str", "robuffer"} + is_b_or_ba = accept == {bytes, bytearray} + is_b_or_ba_or_none = accept == {bytes, bytearray, NoneType} + is_str = accept == {str} + is_str_or_none = accept == {str, NoneType} + is_robuffer = accept == {robuffer} + is_str_or_robuffer = accept == {str, robuffer} + is_str_or_robuffer_or_none = accept == {str, robuffer, NoneType} format_unit = None if encoding: self.encoding = encoding - if is_str and not length and not zeroes and not nullable: + if is_str and not length and not zeroes: format_unit = 'es' - elif is_str and length and zeroes and nullable: + elif is_str_or_none and length and zeroes: format_unit = 'es#' - elif is_b_or_ba and not length and not zeroes and not nullable: + elif is_b_or_ba and not length and not zeroes: format_unit = 'et' - elif is_b_or_ba and length and zeroes and nullable: + elif is_b_or_ba_or_none and length and zeroes: format_unit = 'et#' else: if zeroes: fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)") - if is_str and not length and not nullable: + if is_str and not length: format_unit = 's' - elif is_str and not length and nullable: + elif is_str_or_none and not length: format_unit = 'z' - elif is_robuffer and not length and not nullable: + elif is_robuffer and not length: format_unit = 'y' - elif is_robuffer and length and not nullable: + elif is_robuffer and length: format_unit = 'y#' - elif is_str_or_robuffer and length and not nullable: + elif is_str_or_robuffer and length: format_unit = 's#' - elif is_str_or_robuffer and length and nullable: + elif is_str_or_robuffer_or_none and length: format_unit = 'z#' if not format_unit: @@ -2696,12 +2707,12 @@ class PyBytesObject_converter(CConverter): type = 'PyBytesObject *' format_unit = 'S' - # types = {'bytes'} + # accept = {bytes} class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' - # types = {'bytearray'} + # accept = {bytearray} class unicode_converter(CConverter): type = 'PyObject *' @@ -2709,45 +2720,44 @@ format_unit = 'U' @add_legacy_c_converter('u#', length=True) - at add_legacy_c_converter('Z', nullable=True) - at add_legacy_c_converter('Z#', nullable=True, length=True) + at add_legacy_c_converter('Z', accept={str, NoneType}) + at add_legacy_c_converter('Z#', accept={str, NoneType}, length=True) class Py_UNICODE_converter(CConverter): type = 'Py_UNICODE *' default_type = (str, Null, NoneType) format_unit = 'u' - def converter_init(self, *, nullable=False, length=False): - format_unit = 'Z' if nullable else 'u' + def converter_init(self, *, accept={str}, length=False): + format_unit = 'Z' if accept=={str, NoneType} else 'u' if length: format_unit += '#' self.length = True self.format_unit = format_unit - at add_legacy_c_converter('s*', types={'str', 'buffer'}) - at add_legacy_c_converter('z*', types={'str', 'buffer'}, nullable=True) - at add_legacy_c_converter('w*', types={'rwbuffer'}) + at add_legacy_c_converter('s*', accept={str, buffer}) + at add_legacy_c_converter('z*', accept={str, buffer, NoneType}) + at add_legacy_c_converter('w*', accept={rwbuffer}) class Py_buffer_converter(CConverter): type = 'Py_buffer' format_unit = 'y*' impl_by_reference = True c_ignored_default = "{NULL, NULL}" - def converter_init(self, *, types={'buffer'}, nullable=False): + def converter_init(self, *, accept={buffer}): if self.default not in (unspecified, None): fail("The only legal default value for Py_buffer is None.") + self.c_default = self.c_ignored_default - format_unit = None - if types == {'str', 'buffer'}: - format_unit = 's*' if not nullable else 'z*' + if accept == {str, buffer, NoneType}: + format_unit = 'z*' + elif accept == {str, buffer}: + format_unit = 's*' + elif accept == {buffer}: + format_unit = 'y*' + elif accept == {rwbuffer}: + format_unit = 'w*' else: - if nullable: - fail('Py_buffer_converter: illegal combination of arguments (nullable=True)') - elif types == {'buffer'}: - format_unit = 'y*' - elif types == {'rwbuffer'}: - format_unit = 'w*' - if not format_unit: fail("Py_buffer_converter: illegal combination of arguments") self.format_unit = format_unit @@ -3030,6 +3040,24 @@ 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n') +def eval_ast_expr(node, globals, *, filename='-'): + """ + Takes an ast.Expr node. Compiles and evaluates it. + Returns the result of the expression. + + globals represents the globals dict the expression + should see. (There's no equivalent for "locals" here.) + """ + + if isinstance(node, ast.Expr): + node = node.value + + node = ast.Expression(node) + co = compile(node, filename, 'eval') + fn = types.FunctionType(co, globals) + return fn() + + class IndentStack: def __init__(self): self.indents = [] @@ -3617,7 +3645,7 @@ except SyntaxError: try: # the last = was probably inside a function call, like - # i: int(nullable=True) + # c: int(accept={str}) # so assume there was no actual default value. default = None ast_input = "def x({}): pass".format(line) @@ -3628,6 +3656,14 @@ fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line) function_args = module.body[0].args + + if len(function_args.args) > 1: + fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line) + if function_args.defaults or function_args.kw_defaults: + fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line) + if function_args.vararg or function_args.kwarg: + fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line) + parameter = function_args.args[0] parameter_name = parameter.arg @@ -3790,7 +3826,9 @@ fail("Annotations must be either a name, a function call, or a string.") name = annotation.func.id - kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords} + symbols = globals() + + kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords} return name, False, kwargs def parse_special_symbol(self, symbol): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 4 19:48:55 2015 From: python-checkins at python.org (eric.snow) Date: Mon, 04 May 2015 17:48:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323911=3A_Fix_mixe?= =?utf-8?q?d_bytes/strings=2E?= Message-ID: <20150504174852.76616.98433@psf.io> https://hg.python.org/cpython/rev/36b902bbc992 changeset: 95880:36b902bbc992 user: Eric Snow date: Mon May 04 11:48:39 2015 -0600 summary: Issue #23911: Fix mixed bytes/strings. files: Lib/test/test_site.py | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -356,9 +356,11 @@ self.assertEqual(proc.returncode, 0) os__file__, os__cached__ = stdout.splitlines()[:2] self.assertTrue(os.path.isabs(os__file__), - "expected absolute path, got {}".format(os__file__)) + "expected absolute path, got {}" + .format(os__file__.decode('ascii'))) self.assertTrue(os.path.isabs(os__cached__), - "expected absolute path, got {}".format(os__cached__)) + "expected absolute path, got {}" + .format(os__cached__.decode('ascii'))) def test_no_duplicate_paths(self): # No duplicate paths should exist in sys.path -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 4 23:52:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 04 May 2015 21:52:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_New_Abstract_sect?= =?utf-8?q?ion=3B_thanks_to_Elvis_Pranskevichus=2E?= Message-ID: <20150504215223.98673.54354@psf.io> https://hg.python.org/peps/rev/ee45e5e570cc changeset: 5817:ee45e5e570cc user: Yury Selivanov date: Mon May 04 17:52:20 2015 -0400 summary: pep-0492: New Abstract section; thanks to Elvis Pranskevichus. files: pep-0492.txt | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -14,10 +14,22 @@ Abstract ======== -This PEP introduces new syntax for coroutines, asynchronous ``with`` -statements and ``for`` loops. The main motivation behind this proposal -is to streamline writing and maintaining asynchronous code, as well as -to simplify previously hard to implement code patterns. +The growth of Internet and general connectivity has triggered the +proportionate need for responsive and scalable code. This proposal +aims to answer that need by making writing explicitly asynchronous, +concurrent Python code easier and more Pythonic. + +It is proposed to make *coroutines* a proper standalone concept in +Python, and introduce new supporting syntax. The ultimate goal +is to help establish a common, easily approachable, mental +model of asynchronous programming in Python and make it as close to +synchronous programming as possible. + +This PEP improves upon PEP 342, and, in a sense, supercedes it. We +believe that the changes proposed here will help keep Python +relevant and competitive in a quickly growing area of asynchronous +programming, as many other languages have adopted, or are planning to +adopt, similar features: [2]_, [5]_, [6]_, [7]_, [8]_, [10]_. Rationale and Goals -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 01:11:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 04 May 2015 23:11:00 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Minor_edits?= Message-ID: <20150504231100.84498.66887@psf.io> https://hg.python.org/peps/rev/4f4df783a1c1 changeset: 5818:4f4df783a1c1 user: Yury Selivanov date: Mon May 04 19:10:57 2015 -0400 summary: pep-0492: Minor edits files: pep-0492.txt | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -25,8 +25,7 @@ model of asynchronous programming in Python and make it as close to synchronous programming as possible. -This PEP improves upon PEP 342, and, in a sense, supercedes it. We -believe that the changes proposed here will help keep Python +We believe that the changes proposed here will help keep Python relevant and competitive in a quickly growing area of asynchronous programming, as many other languages have adopted, or are planning to adopt, similar features: [2]_, [5]_, [6]_, [7]_, [8]_, [10]_. @@ -691,7 +690,7 @@ * ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` can be used in ``await`` expression. See `Await Expression`_ for details. -* ``sys.set_coroutine_wrapper(wraper)`` allows to intercept creation of +* ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation of *coroutine objects*. ``wraper`` must be a callable that accepts one argument: a *coroutine object* or ``None``. ``None`` resets the wrapper. If called twice, the new wrapper replaces the previous one. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 01:19:55 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 04 May 2015 23:19:55 +0000 Subject: [Python-checkins] =?utf-8?b?cGVwczogcGVwLTA0OTI6IChzZXR8Z2V0KV9j?= =?utf-8?q?oroutine=5Fwrapper=28=29_is_now_thread-specific?= Message-ID: <20150504231955.98693.79550@psf.io> https://hg.python.org/peps/rev/861864601573 changeset: 5819:861864601573 user: Yury Selivanov date: Mon May 04 19:19:52 2015 -0400 summary: pep-0492: (set|get)_coroutine_wrapper() is now thread-specific files: pep-0492.txt | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -690,15 +690,16 @@ * ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` can be used in ``await`` expression. See `Await Expression`_ for details. -* ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation of - *coroutine objects*. ``wraper`` must be a callable that accepts one - argument: a *coroutine object* or ``None``. ``None`` resets the +* ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation + of *coroutine objects*. ``wraper`` must be a callable that accepts + one argument: a *coroutine object* or ``None``. ``None`` resets the wrapper. If called twice, the new wrapper replaces the previous one. - See `Debugging Features`_ for more details. + The function is thread-specific. See `Debugging Features`_ for more + details. * ``sys.get_coroutine_wrapper()`` returns the current wrapper object. - Returns ``None`` if no wrapper was set. See `Debugging Features`_ - for more details. + Returns ``None`` if no wrapper was set. The function is + thread-specific. See `Debugging Features`_ for more details. Glossary -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 01:32:41 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 04 May 2015 23:32:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_minor_spelling_mistake_in?= =?utf-8?q?_492=2E?= Message-ID: <20150504233240.84506.20973@psf.io> https://hg.python.org/peps/rev/720ebb895692 changeset: 5820:720ebb895692 user: Larry Hastings date: Mon May 04 16:32:37 2015 -0700 summary: Fix minor spelling mistake in 492. files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -691,7 +691,7 @@ in ``await`` expression. See `Await Expression`_ for details. * ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation - of *coroutine objects*. ``wraper`` must be a callable that accepts + of *coroutine objects*. ``wrapper`` must be a callable that accepts one argument: a *coroutine object* or ``None``. ``None`` resets the wrapper. If called twice, the new wrapper replaces the previous one. The function is thread-specific. See `Debugging Features`_ for more -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 01:35:39 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 04 May 2015 23:35:39 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Update_Rationale_?= =?utf-8?q?section?= Message-ID: <20150504233539.11942.10108@psf.io> https://hg.python.org/peps/rev/6d958eafdd28 changeset: 5821:6d958eafdd28 user: Yury Selivanov date: Mon May 04 19:35:36 2015 -0400 summary: pep-0492: Update Rationale section files: pep-0492.txt | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -38,15 +38,15 @@ 342), further enhanced by the ``yield from`` syntax introduced in PEP 380. This approach has a number of shortcomings: -* it is easy to confuse coroutines with regular generators, since they - share the same syntax; async libraries often attempt to alleviate - this by using decorators (e.g. ``@asyncio.coroutine`` [1]_); +* It is easy to confuse coroutines with regular generators, since they + share the same syntax; this is especially true for new developers. -* it is not possible to natively define a coroutine which has no - ``yield`` or ``yield from`` statements, again requiring the use of - decorators to fix potential refactoring issues; +* Whether or not a function is a coroutine is determined by a presence + of ``yield`` or ``yield from`` statements in its *body*, which can + lead to unobvious errors when such statements appear in or disappear + from function body during refactoring. -* support for asynchronous calls is limited to expressions where +* Support for asynchronous calls is limited to expressions where ``yield`` is allowed syntactically, limiting the usefulness of syntactic features, such as ``with`` and ``for`` statements. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 04:45:54 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 05 May 2015 02:45:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324113=3A__Remove_?= =?utf-8?q?unreachable_code_in_shlex=2E?= Message-ID: <20150505024551.14348.1793@psf.io> https://hg.python.org/cpython/rev/395e190ead36 changeset: 95881:395e190ead36 user: Raymond Hettinger date: Mon May 04 22:45:47 2015 -0400 summary: Issue #24113: Remove unreachable code in shlex. files: Lib/shlex.py | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Lib/shlex.py b/Lib/shlex.py --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -49,9 +49,6 @@ self.token = '' self.filestack = deque() self.source = None - if self.debug: - print('shlex: reading from %s, line %d' \ - % (self.instream, self.lineno)) def push_token(self, tok): "Push a token onto the stack popped by the get_token method" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 5 05:27:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 05 May 2015 03:27:20 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_We_always_raise_R?= =?utf-8?q?untimeWarning_for_non-awaited_coroutines?= Message-ID: <20150505032720.98677.7341@psf.io> https://hg.python.org/peps/rev/ae24829f1bf8 changeset: 5822:ae24829f1bf8 user: Yury Selivanov date: Mon May 04 23:27:16 2015 -0400 summary: pep-0492: We always raise RuntimeWarning for non-awaited coroutines files: pep-0492.txt | 37 +++++++++++-------------------------- 1 files changed, 11 insertions(+), 26 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -91,7 +91,7 @@ async def read_data(db): pass -Key properties of *native coroutines*: +Key properties of *coroutines*: * ``async def`` functions are always coroutines, even if they do not contain ``await`` expressions. @@ -117,6 +117,9 @@ and are replaced with a ``RuntimeError``. For regular generators such behavior requires a future import (see PEP 479). +* When a *coroutine* is garbage collected, a ``RuntimeWarning`` is + raised if it was never awaited on (see also `Debugging Features`_.) + * See also `Coroutine objects`_ section. @@ -648,31 +651,13 @@ no impact on ``@coroutine`` decorator's behavior. With this proposal, coroutines is a native, distinct from generators, -concept. New methods ``set_coroutine_wrapper`` and -``get_coroutine_wrapper`` are added to the ``sys`` module, with which -frameworks can provide advanced debugging facilities. - -It is also important to make coroutines as fast and efficient as -possible, therefore there are no debug features enabled by default. - -Example:: - - async def debug_me(): - await asyncio.sleep(1) - - def async_debug_wrap(generator): - return asyncio.CoroWrapper(generator) - - sys.set_coroutine_wrapper(async_debug_wrap) - - debug_me() # <- this line will likely GC the coroutine object and - # trigger asyncio.CoroWrapper's code. - - assert isinstance(debug_me(), asyncio.CoroWrapper) - - sys.set_coroutine_wrapper(None) # <- this unsets any - # previously set wrapper - assert not isinstance(debug_me(), asyncio.CoroWrapper) +concept. *In addition* to a ``RuntimeWarning`` being raised on +coroutines that were never awaited, it is proposed to add two new +functions to the ``sys`` module: ``set_coroutine_wrapper`` and +``get_coroutine_wrapper``. This is to enable advanced debugging +facilities in asyncio and other frameworks (such as displaying where +exactly coroutine was created, and a more detailed stack trace of where +it was garbage collected). New Standard Library Functions -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Tue May 5 10:36:22 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 05 May 2015 08:36:22 +0000 Subject: [Python-checkins] Daily reference leaks (395e190ead36): sum=3 Message-ID: <20150505083622.8946.28963@psf.io> results for 395e190ead36 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogaJjpzh', '--timeout', '7200'] From python-checkins at python.org Tue May 5 18:22:58 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 05 May 2015 16:22:58 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Update_Post-Histo?= =?utf-8?q?ry?= Message-ID: <20150505162257.14356.49194@psf.io> https://hg.python.org/peps/rev/66b3dd105cba changeset: 5823:66b3dd105cba user: Yury Selivanov date: Tue May 05 12:22:54 2015 -0400 summary: pep-0492: Update Post-History files: pep-0492.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,7 +8,8 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 -Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015 +Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, + 05-May-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 18:41:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 05 May 2015 16:41:24 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_terminology_a?= =?utf-8?q?round_coroutine_object?= Message-ID: <20150505164123.8956.23514@psf.io> https://hg.python.org/peps/rev/f156b272f860 changeset: 5824:f156b272f860 user: Yury Selivanov date: Tue May 05 12:41:20 2015 -0400 summary: pep-0492: Fix terminology around coroutine object files: pep-0492.txt | 45 ++++++++++++++++++++------------------- 1 files changed, 23 insertions(+), 22 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -112,7 +112,7 @@ ``CO_GENERATOR`` flags set. * Regular generators, when called, return a *generator object*; - similarly, coroutines return a *coroutine object*. + similarly, coroutines return a *coroutine* object. * ``StopIteration`` exceptions are not propagated out of coroutines, and are replaced with a ``RuntimeError``. For regular generators @@ -132,7 +132,7 @@ in asyncio and *native coroutines* introduced by this PEP. The function applies ``CO_COROUTINE`` flag to generator-function's code -object, making it return a *coroutine object*. +object, making it return a *coroutine* object. The function can be used as a decorator, since it modifies generator- functions in-place and returns them. @@ -160,10 +160,11 @@ validating its argument. ``await`` only accepts an *awaitable*, which can be one of: -* A *native coroutine object* returned from a *native coroutine*. +* A *native coroutine* object returned from a *native coroutine + function*. -* A *generator-based coroutine object* returned from a generator - decorated with ``types.coroutine()``. +* A *generator-based coroutine* object returned from a *generator + function* decorated with ``types.coroutine()``. * An object with an ``__await__`` method returning an iterator. @@ -590,15 +591,15 @@ Great effort has been made to make sure that coroutines and generators are treated as distinct concepts: -1. *Native coroutine objects* do not implement ``__iter__`` and +1. *Native coroutine* objects do not implement ``__iter__`` and ``__next__`` methods. Therefore, they cannot be iterated over or passed to ``iter()``, ``list()``, ``tuple()`` and other built-ins. They also cannot be used in a ``for..in`` loop. An attempt to use ``__iter__`` or ``__next__`` on a *native - coroutine object* will result in a ``TypeError``. + coroutine* object will result in a ``TypeError``. -2. *Plain generators* cannot ``yield from`` *native coroutine objects*: +2. *Plain generators* cannot ``yield from`` *native coroutines*: doing so will result in a ``TypeError``. 3. *generator-based coroutines* (for asyncio code must be decorated @@ -606,7 +607,7 @@ objects*. 4. ``inspect.isgenerator()`` and ``inspect.isgeneratorfunction()`` - return ``False`` for *native coroutine objects* and *native + return ``False`` for *native coroutine* objects and *native coroutine functions*. @@ -614,13 +615,13 @@ '''''''''''''''''''''''' Coroutines are based on generators internally, thus they share the -implementation. Similarly to generator objects, coroutine objects have +implementation. Similarly to generator objects, *coroutines* have ``throw()``, ``send()`` and ``close()`` methods. ``StopIteration`` and -``GeneratorExit`` play the same role for coroutine objects (although +``GeneratorExit`` play the same role for coroutines (although PEP 479 is enabled by default for coroutines). See PEP 342, PEP 380, and Python Documentation [11]_ for details. -``throw()``, ``send()`` methods for coroutine objects are used to push +``throw()``, ``send()`` methods for *coroutines* are used to push values and raise errors into *Future-like* objects. @@ -668,7 +669,7 @@ details. * ``inspect.iscoroutine(obj)`` returns ``True`` if ``obj`` is a - *coroutine object*. + *coroutine* object. * ``inspect.iscoroutinefunction(obj)`` returns ``True`` if ``obj`` is a *coroutine function*. @@ -677,8 +678,8 @@ in ``await`` expression. See `Await Expression`_ for details. * ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation - of *coroutine objects*. ``wrapper`` must be a callable that accepts - one argument: a *coroutine object* or ``None``. ``None`` resets the + of *coroutine* objects. ``wrapper`` must be a callable that accepts + one argument: a *coroutine* object or ``None``. ``None`` resets the wrapper. If called twice, the new wrapper replaces the previous one. The function is thread-specific. See `Debugging Features`_ for more details. @@ -691,28 +692,28 @@ Glossary ======== -:Native coroutine: +:Native coroutine function: A coroutine function is declared with ``async def``. It uses ``await`` and ``return value``; see `New Coroutine Declaration Syntax`_ for details. -:Native coroutine object: +:Native coroutine: Returned from a native coroutine function. See `Await Expression`_ for details. -:Generator-based coroutine: +:Generator-based coroutine function: Coroutines based on generator syntax. Most common example are functions decorated with ``@asyncio.coroutine``. -:Generator-based coroutine object: +:Generator-based coroutine: Returned from a generator-based coroutine function. :Coroutine: Either *native coroutine* or *generator-based coroutine*. :Coroutine object: - Either *native coroutine object* or *generator-based coroutine - object*. + Either *native coroutine* object or *generator-based coroutine* + object. :Future-like object: An object with an ``__await__`` method, or a C object with @@ -723,7 +724,7 @@ Expression`_ for details. :Awaitable: - A *Future-like* object or a *coroutine object*. See `Await + A *Future-like* object or a *coroutine* object. See `Await Expression`_ for details. :Asynchronous context manager: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 18:43:16 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 05 May 2015 16:43:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_Discussions-T?= =?utf-8?q?o_header_field?= Message-ID: <20150505164316.84488.49120@psf.io> https://hg.python.org/peps/rev/2d17fc29dc93 changeset: 5825:2d17fc29dc93 user: Yury Selivanov date: Tue May 05 12:43:13 2015 -0400 summary: pep-0492: Add Discussions-To header field files: pep-0492.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,6 +8,7 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 +Discussions-To: Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, 05-May-2015 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 5 21:03:47 2015 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 05 May 2015 19:03:47 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQwODg6?= =?utf-8?q?_Clarify_semantics_of_yield_expression=2E?= Message-ID: <20150505190346.84482.18338@psf.io> https://hg.python.org/cpython/rev/b87d96e0708e changeset: 95882:b87d96e0708e branch: 3.4 parent: 95873:71ec881d8347 user: Guido van Rossum date: Tue May 05 12:02:01 2015 -0700 summary: Issue 24088: Clarify semantics of yield expression. files: Doc/reference/expressions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -325,7 +325,7 @@ expression in a function's body causes that function to be a generator. When a generator function is called, it returns an iterator known as a -generator. That generator then controls the execution of a generator function. +generator. That generator then controls the execution of the generator function. The execution starts when one of the generator's methods is called. At that time, the execution proceeds to the first yield expression, where it is suspended again, returning the value of :token:`expression_list` to the generator's -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 5 21:04:47 2015 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 05 May 2015 19:04:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_24088=3A_Clarify_semantics_of_yield_expression_=28?= =?utf-8?q?merge_from_3=2E4=29=2E?= Message-ID: <20150505190441.76600.5932@psf.io> https://hg.python.org/cpython/rev/6e59d82d3d09 changeset: 95883:6e59d82d3d09 parent: 95881:395e190ead36 parent: 95882:b87d96e0708e user: Guido van Rossum date: Tue May 05 12:04:35 2015 -0700 summary: Issue 24088: Clarify semantics of yield expression (merge from 3.4). files: Doc/reference/expressions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -325,7 +325,7 @@ expression in a function's body causes that function to be a generator. When a generator function is called, it returns an iterator known as a -generator. That generator then controls the execution of a generator function. +generator. That generator then controls the execution of the generator function. The execution starts when one of the generator's methods is called. At that time, the execution proceeds to the first yield expression, where it is suspended again, returning the value of :token:`expression_list` to the generator's -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 00:31:53 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 05 May 2015 22:31:53 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_a_clarificati?= =?utf-8?q?on_on_event_loop_requirement=2E_By_Jim_J=2E_Jewett=2E?= Message-ID: <20150505223153.8952.26046@psf.io> https://hg.python.org/peps/rev/7ac132b24f1f changeset: 5826:7ac132b24f1f user: Yury Selivanov date: Tue May 05 18:31:49 2015 -0400 summary: pep-0492: Add a clarification on event loop requirement. By Jim J. Jewett. files: pep-0492.txt | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -27,6 +27,14 @@ model of asynchronous programming in Python and make it as close to synchronous programming as possible. +This PEP assumes that the asynchronous tasks are scheduled and +coordinated by an Event Loop similar to that of stdlib module +``asyncio.events.AbstractEventLoop``. While the PEP is not tied to any +specific Event Loop implementation, it is relevant only to the kind of +coroutine that uses "yield" as a signal to the scheduler, indicating +that the coroutine will be waiting until an event (such as IO) is +completed. + We believe that the changes proposed here will help keep Python relevant and competitive in a quickly growing area of asynchronous programming, as many other languages have adopted, or are planning to -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 01:13:41 2015 From: python-checkins at python.org (matthias.klose) Date: Tue, 05 May 2015 23:13:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIC0gSXNzdWUgIzI0?= =?utf-8?q?122=2C_fix_quoting_for_LIBPL?= Message-ID: <20150505231341.7820.50521@psf.io> https://hg.python.org/cpython/rev/29512e2015d9 changeset: 95884:29512e2015d9 branch: 3.4 parent: 95882:b87d96e0708e user: doko at ubuntu.com date: Wed May 06 01:13:02 2015 +0200 summary: - Issue #24122, fix quoting for LIBPL files: configure | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -14030,7 +14030,7 @@ $as_echo "$LDVERSION" >&6; } -LIBPL="${prefix}/lib/python${VERSION}/config-${LDVERSION}" +LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" # Check whether right shifting a negative integer extends the sign bit diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -4115,7 +4115,7 @@ dnl define LIBPL after ABIFLAGS and LDVERSION is defined. AC_SUBST(PY_ENABLE_SHARED) -LIBPL="${prefix}/lib/python${VERSION}/config-${LDVERSION}" +LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" AC_SUBST(LIBPL) # Check whether right shifting a negative integer extends the sign bit -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 01:13:41 2015 From: python-checkins at python.org (matthias.klose) Date: Tue, 05 May 2015 23:13:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIC0gbWVyZ2UgMy40?= Message-ID: <20150505231341.98681.96625@psf.io> https://hg.python.org/cpython/rev/ae63b105f897 changeset: 95885:ae63b105f897 parent: 95883:6e59d82d3d09 parent: 95884:29512e2015d9 user: doko at ubuntu.com date: Wed May 06 01:13:31 2015 +0200 summary: - merge 3.4 files: configure | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -14381,7 +14381,7 @@ $as_echo "$LDVERSION" >&6; } -LIBPL="${prefix}/lib/python${VERSION}/config-${LDVERSION}" +LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" # Check whether right shifting a negative integer extends the sign bit diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -4331,7 +4331,7 @@ dnl define LIBPL after ABIFLAGS and LDVERSION is defined. AC_SUBST(PY_ENABLE_SHARED) -LIBPL="${prefix}/lib/python${VERSION}/config-${LDVERSION}" +LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" AC_SUBST(LIBPL) # Check whether right shifting a negative integer extends the sign bit -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 02:16:52 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 06 May 2015 00:16:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_PEP_448=3A_additional_unpa?= =?utf-8?q?cking_generalizations_=28closes_=232292=29?= Message-ID: <20150506001652.98689.69856@psf.io> https://hg.python.org/cpython/rev/a65f685ba8c0 changeset: 95886:a65f685ba8c0 user: Benjamin Peterson date: Tue May 05 20:16:41 2015 -0400 summary: PEP 448: additional unpacking generalizations (closes #2292) Patch by Neil Girdhar. files: Grammar/Grammar | 24 +- Include/Python-ast.h | 18 +- Include/dictobject.h | 4 + Include/opcode.h | 5 + Lib/importlib/_bootstrap_external.py | 3 +- Lib/opcode.py | 6 + Lib/test/test_ast.py | 56 +- Lib/test/test_extcall.py | 22 + Lib/test/test_grammar.py | 6 +- Lib/test/test_parser.py | 12 + Lib/test/test_syntax.py | 16 +- Lib/test/test_unpack_ex.py | 183 +- Misc/ACKS | 1 + Misc/NEWS | 2 + Modules/parsermodule.c | 279 +- Objects/dictobject.c | 6 +- Parser/Python.asdl | 9 +- Python/Python-ast.c | 105 +- Python/ast.c | 340 +- Python/ceval.c | 164 +- Python/compile.c | 321 +- Python/graminit.c | 156 +- Python/importlib_external.h | 3003 ++++++------- Python/opcode_targets.h | 10 +- Python/symtable.c | 26 +- Tools/parser/unparse.py | 27 +- 26 files changed, 2675 insertions(+), 2129 deletions(-) diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -111,17 +111,29 @@ sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] -dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | - (test (comp_for | (',' test)* [','])) ) +dictorsetmaker: ( ((test ':' test | '**' expr) + (comp_for | (',' (test ':' test | '**' expr))* [','])) | + ((test | star_expr) + (comp_for | (',' (test | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite -arglist: (argument ',')* (argument [','] - |'*' test (',' argument)* [',' '**' test] - |'**' test) +arglist: argument (',' argument)* [','] + # The reason that keywords are test nodes instead of NAME is that using NAME # results in an ambiguity. ast.c makes sure it's a NAME. -argument: test [comp_for] | test '=' test # Really [keyword '='] test +# "test '=' test" is really "keyword '=' test", but we have no such token. +# These need to be in a single rule to avoid grammar that is ambiguous +# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, +# we explicitly match '*' here, too, to give it proper precedence. +# Illegal combinations and orderings are blocked in ast.c: +# multiple (test comp_for) arguements are blocked; keyword unpackings +# that precede iterable unpackings are blocked; etc. +argument: ( test [comp_for] | + test '=' test | + '**' expr | + star_expr ) + comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] comp_if: 'if' test_nocond [comp_iter] diff --git a/Include/Python-ast.h b/Include/Python-ast.h --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -84,8 +84,6 @@ identifier name; asdl_seq *bases; asdl_seq *keywords; - expr_ty starargs; - expr_ty kwargs; asdl_seq *body; asdl_seq *decorator_list; } ClassDef; @@ -263,8 +261,6 @@ expr_ty func; asdl_seq *args; asdl_seq *keywords; - expr_ty starargs; - expr_ty kwargs; } Call; struct { @@ -406,11 +402,10 @@ stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorator_list, expr_ty returns, int lineno, int col_offset, PyArena *arena); -#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) +#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, - expr_ty starargs, expr_ty kwargs, asdl_seq * body, - asdl_seq * decorator_list, int lineno, int col_offset, - PyArena *arena); + asdl_seq * body, asdl_seq * decorator_list, int lineno, + int col_offset, PyArena *arena); #define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); #define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3) @@ -504,10 +499,9 @@ #define Compare(a0, a1, a2, a3, a4, a5) _Py_Compare(a0, a1, a2, a3, a4, a5) expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno, int col_offset, PyArena *arena); -#define Call(a0, a1, a2, a3, a4, a5, a6, a7) _Py_Call(a0, a1, a2, a3, a4, a5, a6, a7) -expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty - starargs, expr_ty kwargs, int lineno, int col_offset, PyArena - *arena); +#define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5) +expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int + lineno, int col_offset, PyArena *arena); #define Num(a0, a1, a2, a3) _Py_Num(a0, a1, a2, a3) expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena); #define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3) diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -105,6 +105,10 @@ PyObject *other, int override); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other); +#endif + /* PyDict_MergeFromSeq2 updates/merges from an iterable object producing iterable objects of length 2. If override is true, the last occurrence of a key wins, else the first. The Python dict constructor dict(seq2) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -111,6 +111,11 @@ #define SET_ADD 146 #define MAP_ADD 147 #define LOAD_CLASSDEREF 148 +#define BUILD_LIST_UNPACK 149 +#define BUILD_MAP_UNPACK 150 +#define BUILD_MAP_UNPACK_WITH_CALL 151 +#define BUILD_TUPLE_UNPACK 152 +#define BUILD_SET_UNPACK 153 /* 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 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -220,12 +220,13 @@ # 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) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). -MAGIC_NUMBER = (3320).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3330).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 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -200,4 +200,10 @@ def_op('EXTENDED_ARG', 144) EXTENDED_ARG = 144 +def_op('BUILD_LIST_UNPACK', 149) +def_op('BUILD_MAP_UNPACK', 150) +def_op('BUILD_MAP_UNPACK_WITH_CALL', 151) +def_op('BUILD_TUPLE_UNPACK', 152) +def_op('BUILD_SET_UNPACK', 153) + del def_op, name_op, jrel_op, jabs_op diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -427,17 +427,17 @@ self.assertEqual(ast.dump(node), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], " - "keywords=[], starargs=None, kwargs=None))])" + "keywords=[]))])" ) self.assertEqual(ast.dump(node, annotate_fields=False), "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " - "Str('and cheese')], [], None, None))])" + "Str('and cheese')], []))])" ) self.assertEqual(ast.dump(node, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), " "lineno=1, col_offset=5), Str(s='and cheese', lineno=1, " - "col_offset=11)], keywords=[], starargs=None, kwargs=None, " + "col_offset=11)], keywords=[], " "lineno=1, col_offset=0), lineno=1, col_offset=0)])" ) @@ -453,16 +453,16 @@ def test_fix_missing_locations(self): src = ast.parse('write("spam")') src.body.append(ast.Expr(ast.Call(ast.Name('spam', ast.Load()), - [ast.Str('eggs')], [], None, None))) + [ast.Str('eggs')], []))) self.assertEqual(src, ast.fix_missing_locations(src)) self.assertEqual(ast.dump(src, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), " "lineno=1, col_offset=0), args=[Str(s='spam', lineno=1, " - "col_offset=6)], keywords=[], starargs=None, kwargs=None, " + "col_offset=6)], keywords=[], " "lineno=1, col_offset=0), lineno=1, col_offset=0), " "Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, " "col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], " - "keywords=[], starargs=None, kwargs=None, lineno=1, " + "keywords=[], lineno=1, " "col_offset=0), lineno=1, col_offset=0)])" ) @@ -487,8 +487,7 @@ node = ast.parse('foo()', mode='eval') d = dict(ast.iter_fields(node.body)) self.assertEqual(d.pop('func').id, 'foo') - self.assertEqual(d, {'keywords': [], 'kwargs': None, - 'args': [], 'starargs': None}) + self.assertEqual(d, {'keywords': [], 'args': []}) def test_iter_child_nodes(self): node = ast.parse("spam(23, 42, eggs='leek')", mode='eval') @@ -604,8 +603,7 @@ self._check_arguments(fac, self.stmt) def test_classdef(self): - def cls(bases=None, keywords=None, starargs=None, kwargs=None, - body=None, decorator_list=None): + def cls(bases=None, keywords=None, body=None, decorator_list=None): if bases is None: bases = [] if keywords is None: @@ -614,16 +612,12 @@ body = [ast.Pass()] if decorator_list is None: decorator_list = [] - return ast.ClassDef("myclass", bases, keywords, starargs, - kwargs, body, decorator_list) + return ast.ClassDef("myclass", bases, keywords, + body, decorator_list) self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), "must have Load context") - self.stmt(cls(starargs=ast.Name("x", ast.Store())), - "must have Load context") - self.stmt(cls(kwargs=ast.Name("x", ast.Store())), - "must have Load context") self.stmt(cls(body=[]), "empty body on ClassDef") self.stmt(cls(body=[None]), "None disallowed") self.stmt(cls(decorator_list=[ast.Name("x", ast.Store())]), @@ -854,20 +848,12 @@ func = ast.Name("x", ast.Load()) args = [ast.Name("y", ast.Load())] keywords = [ast.keyword("w", ast.Name("z", ast.Load()))] - stararg = ast.Name("p", ast.Load()) - kwarg = ast.Name("q", ast.Load()) - call = ast.Call(ast.Name("x", ast.Store()), args, keywords, stararg, - kwarg) + call = ast.Call(ast.Name("x", ast.Store()), args, keywords) self.expr(call, "must have Load context") - call = ast.Call(func, [None], keywords, stararg, kwarg) + call = ast.Call(func, [None], keywords) self.expr(call, "None disallowed") bad_keywords = [ast.keyword("w", ast.Name("z", ast.Store()))] - call = ast.Call(func, args, bad_keywords, stararg, kwarg) - self.expr(call, "must have Load context") - call = ast.Call(func, args, keywords, ast.Name("z", ast.Store()), kwarg) - self.expr(call, "must have Load context") - call = ast.Call(func, args, keywords, stararg, - ast.Name("w", ast.Store())) + call = ast.Call(func, args, bad_keywords) self.expr(call, "must have Load context") def test_num(self): @@ -957,8 +943,8 @@ ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Pass', (1, 58))], [], None)]), -('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))], [])]), -('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], None, None, [('Pass', (1, 17))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), @@ -968,7 +954,7 @@ ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]), -('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]), +('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]), ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), @@ -998,14 +984,14 @@ ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))), ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))), ('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], [], None, []), ('NameConstant', (1, 7), None))), -('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])), +('Expression', ('Dict', (1, 2), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])), ('Expression', ('Dict', (1, 0), [], [])), -('Expression', ('Set', (1, 0), [('NameConstant', (1, 1), None)])), -('Expression', ('Dict', (1, 0), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])), +('Expression', ('Set', (1, 1), [('NameConstant', (1, 1), None)])), +('Expression', ('Dict', (2, 6), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])), ('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('Compare', (1, 0), ('Num', (1, 0), 1), [('Lt',), ('Lt',)], [('Num', (1, 4), 2), ('Num', (1, 8), 3)])), -('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Num', (1, 2), 1), ('Num', (1, 4), 2)], [('keyword', 'c', ('Num', (1, 8), 3))], ('Name', (1, 11), 'd', ('Load',)), ('Name', (1, 15), 'e', ('Load',)))), +('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Num', (1, 2), 1), ('Num', (1, 4), 2), ('Starred', (1, 10), ('Name', (1, 11), 'd', ('Load',)), ('Load',))], [('keyword', 'c', ('Num', (1, 8), 3)), ('keyword', None, ('Name', (1, 15), 'e', ('Load',)))])), ('Expression', ('Num', (1, 0), 10)), ('Expression', ('Str', (1, 0), 'string')), ('Expression', ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',))), @@ -1016,6 +1002,6 @@ ('Expression', ('Tuple', (1, 0), [('Num', (1, 0), 1), ('Num', (1, 2), 2), ('Num', (1, 4), 3)], ('Load',))), ('Expression', ('Tuple', (1, 1), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), ('Expression', ('Tuple', (1, 0), [], ('Load',))), -('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Num', (1, 12), 1), ('Num', (1, 14), 2), None), ('Load',))], [], None, None)), +('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Num', (1, 12), 1), ('Num', (1, 14), 2), None), ('Load',))], [])), ] main() diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -34,17 +34,37 @@ (1, 2, 3, 4, 5) {} >>> f(1, 2, 3, *[4, 5]) (1, 2, 3, 4, 5) {} + >>> f(*[1, 2, 3], 4, 5) + (1, 2, 3, 4, 5) {} >>> f(1, 2, 3, *UserList([4, 5])) (1, 2, 3, 4, 5) {} + >>> f(1, 2, 3, *[4, 5], *[6, 7]) + (1, 2, 3, 4, 5, 6, 7) {} + >>> f(1, *[2, 3], 4, *[5, 6], 7) + (1, 2, 3, 4, 5, 6, 7) {} + >>> f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7])) + (1, 2, 3, 4, 5, 6, 7) {} Here we add keyword arguments >>> f(1, 2, 3, **{'a':4, 'b':5}) (1, 2, 3) {'a': 4, 'b': 5} + >>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6}) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'a' + >>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'a' >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7}) (1, 2, 3, 4, 5) {'a': 6, 'b': 7} >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9}) (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} + >>> f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7}) + (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8} + >>> f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9}) + (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7} >>> f(1, 2, 3, **UserDict(a=4, b=5)) (1, 2, 3) {'a': 4, 'b': 5} @@ -52,6 +72,8 @@ (1, 2, 3, 4, 5) {'a': 6, 'b': 7} >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9)) (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} + >>> f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9)) + (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7} Examples with invalid arguments (TypeErrors). We're also testing the function names in the exception messages. diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -296,8 +296,12 @@ return args, kwargs self.assertEqual(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), {'x':2, 'y':5})) - self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)") + self.assertEqual(f(1, *(2,3), 4), ((1, 2, 3, 4), {})) self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)") + self.assertEqual(f(**{'eggs':'scrambled', 'spam':'fried'}), + ((), {'eggs':'scrambled', 'spam':'fried'})) + self.assertEqual(f(spam='fried', **{'eggs':'scrambled'}), + ((), {'eggs':'scrambled', 'spam':'fried'})) # argument annotation tests def f(x) -> list: pass diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -313,7 +313,12 @@ "except Exception as e:\n" " raise ValueError from e\n") + def test_list_displays(self): + self.check_expr('[]') + self.check_expr('[*{2}, 3, *[4]]') + def test_set_displays(self): + self.check_expr('{*{2}, 3, *[4]}') self.check_expr('{2}') self.check_expr('{2,}') self.check_expr('{2, 3}') @@ -325,6 +330,13 @@ self.check_expr('{a:b,}') self.check_expr('{a:b, c:d}') self.check_expr('{a:b, c:d,}') + self.check_expr('{**{}}') + self.check_expr('{**{}, 3:4, **{5:6, 7:8}}') + + def test_argument_unpacking(self): + self.check_expr('f(a, *b, *c, *d)') + self.check_expr('f(**a, **b)') + self.check_expr('f(2, *a, *b, **b, **c, **d)') def test_set_comprehensions(self): self.check_expr('{x for x in seq}') diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -141,6 +141,9 @@ >>> f(x for x in L, 1) Traceback (most recent call last): SyntaxError: Generator expression must be parenthesized if not sole argument +>>> f(x for x in L, y for y in L) +Traceback (most recent call last): +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f((x for x in L), 1) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -582,7 +585,18 @@ subclass=IndentationError) def test_kwargs_last(self): - self._check_error("int(base=10, '2')", "non-keyword arg") + self._check_error("int(base=10, '2')", + "positional argument follows keyword argument") + + def test_kwargs_last2(self): + self._check_error("int(**{base: 10}, '2')", + "positional argument follows " + "keyword argument unpacking") + + def test_kwargs_last3(self): + self._check_error("int(**{base: 10}, *['2'])", + "iterable argument unpacking follows " + "keyword argument unpacking") def test_main(): support.run_unittest(SyntaxTestCase) diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -71,8 +71,185 @@ >>> a == 0 and b == [1, 2, 3] and c == 4 and d == [0, 1, 2, 3] and e == 4 True +Assignment unpacking + + >>> a, b, *c = range(5) + >>> a, b, c + (0, 1, [2, 3, 4]) + >>> *a, b, c = a, b, *c + >>> a, b, c + ([0, 1, 2], 3, 4) + +Set display element unpacking + + >>> a = [1, 2, 3] + >>> sorted({1, *a, 0, 4}) + [0, 1, 2, 3, 4] + + >>> {1, *1, 0, 4} + Traceback (most recent call last): + ... + TypeError: 'int' object is not iterable + +Dict display element unpacking + + >>> kwds = {'z': 0, 'w': 12} + >>> sorted({'x': 1, 'y': 2, **kwds}.items()) + [('w', 12), ('x', 1), ('y', 2), ('z', 0)] + + >>> sorted({**{'x': 1}, 'y': 2, **{'z': 3}}.items()) + [('x', 1), ('y', 2), ('z', 3)] + + >>> sorted({**{'x': 1}, 'y': 2, **{'x': 3}}.items()) + [('x', 3), ('y', 2)] + + >>> sorted({**{'x': 1}, **{'x': 3}, 'x': 4}.items()) + [('x', 4)] + + >>> {**{}} + {} + + >>> a = {} + >>> {**a}[0] = 1 + >>> a + {} + + >>> {**1} + Traceback (most recent call last): + ... + TypeError: 'int' object is not a mapping + + >>> {**[]} + Traceback (most recent call last): + ... + TypeError: 'list' object is not a mapping + + >>> len(eval("{" + ", ".join("**{{{}: {}}}".format(i, i) + ... for i in range(1000)) + "}")) + 1000 + +List comprehension element unpacking + + >>> a, b, c = [0, 1, 2], 3, 4 + >>> [*a, b, c] + [0, 1, 2, 3, 4] + + >>> l = [a, (3, 4), {5}, {6: None}, (i for i in range(7, 10))] + >>> [*item for item in l] + Traceback (most recent call last): + ... + SyntaxError: iterable unpacking cannot be used in comprehension + + >>> [*[0, 1] for i in range(10)] + Traceback (most recent call last): + ... + SyntaxError: iterable unpacking cannot be used in comprehension + + >>> [*'a' for i in range(10)] + Traceback (most recent call last): + ... + SyntaxError: iterable unpacking cannot be used in comprehension + + >>> [*[] for i in range(10)] + Traceback (most recent call last): + ... + SyntaxError: iterable unpacking cannot be used in comprehension + +Generator expression in function arguments + + >>> list(*x for x in (range(5) for i in range(3))) + Traceback (most recent call last): + ... + list(*x for x in (range(5) for i in range(3))) + ^ + SyntaxError: invalid syntax + + >>> dict(**x for x in [{1:2}]) + Traceback (most recent call last): + ... + dict(**x for x in [{1:2}]) + ^ + SyntaxError: invalid syntax + +Iterable argument unpacking + + >>> print(*[1], *[2], 3) + 1 2 3 + +Make sure that they don't corrupt the passed-in dicts. + + >>> def f(x, y): + ... print(x, y) + ... + >>> original_dict = {'x': 1} + >>> f(**original_dict, y=2) + 1 2 + >>> original_dict + {'x': 1} + Now for some failures +Make sure the raised errors are right for keyword argument unpackings + + >>> from collections.abc import MutableMapping + >>> class CrazyDict(MutableMapping): + ... def __init__(self): + ... self.d = {} + ... + ... def __iter__(self): + ... for x in self.d.__iter__(): + ... if x == 'c': + ... self.d['z'] = 10 + ... yield x + ... + ... def __getitem__(self, k): + ... return self.d[k] + ... + ... def __len__(self): + ... return len(self.d) + ... + ... def __setitem__(self, k, v): + ... self.d[k] = v + ... + ... def __delitem__(self, k): + ... del self.d[k] + ... + >>> d = CrazyDict() + >>> d.d = {chr(ord('a') + x): x for x in range(5)} + >>> e = {**d} + Traceback (most recent call last): + ... + RuntimeError: dictionary changed size during iteration + + >>> d.d = {chr(ord('a') + x): x for x in range(5)} + >>> def f(**kwargs): print(kwargs) + >>> f(**d) + Traceback (most recent call last): + ... + RuntimeError: dictionary changed size during iteration + +Overridden parameters + + >>> f(x=5, **{'x': 3}, y=2) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'x' + + >>> f(**{'x': 3}, x=5, y=2) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'x' + + >>> f(**{'x': 3}, **{'x': 5}, y=2) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'x' + + >>> f(**{1: 3}, **{1: 5}) + Traceback (most recent call last): + ... + TypeError: f() keywords must be strings + Unpacking non-sequence >>> a, *b = 7 @@ -138,17 +315,17 @@ >>> *a # doctest:+ELLIPSIS Traceback (most recent call last): ... - SyntaxError: can use starred expression only as assignment target + SyntaxError: can't use starred expression here >>> *1 # doctest:+ELLIPSIS Traceback (most recent call last): ... - SyntaxError: can use starred expression only as assignment target + SyntaxError: can't use starred expression here >>> x = *a # doctest:+ELLIPSIS Traceback (most recent call last): ... - SyntaxError: can use starred expression only as assignment target + SyntaxError: can't use starred expression here Some size constraints (all fail.) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -493,6 +493,7 @@ Michael Gilfix Julian Gindi Yannick Gingras +Neil Girdhar Matt Giuca Wim Glenn Michael Goderbauer diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #2292: PEP 448: Additional Unpacking Generalizations. + - Issue #24096: Make warnings.warn_explicit more robust against mutation of the warnings.filters list. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -23,6 +23,11 @@ * that lint detects are gone, but there are still warnings with * Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations * look like "NOTE(...)". + * + * To debug parser errors like + * "parser.ParserError: Expected node type 12, got 333." + * decode symbol numbers using the automatically-generated files + * Lib/symbol.h and Include/token.h. */ #include "Python.h" /* general Python API */ @@ -1087,30 +1092,56 @@ return (res); } - -/* X (',' X) [','] - */ +/* X (',' X) [','] */ static int -validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *), - const char *const name) +validate_repeating_list_variable(node *tree, + int list_node_type, + int (*validate_child_func_inc)(node *, int *), + int *pos, + const char *const list_node_type_name) { int nch = NCH(tree); - int res = (nch && validate_ntype(tree, ntype) - && vfunc(CHILD(tree, 0))); - - if (!res && !PyErr_Occurred()) - (void) validate_numnodes(tree, 1, name); + int res = (nch && validate_ntype(tree, list_node_type)); + + if (!res && !PyErr_Occurred()) { + /* Unconditionally raise. */ + (void) validate_numnodes(tree, 1, list_node_type_name); + } else { - if (is_even(nch)) - res = validate_comma(CHILD(tree, --nch)); - if (res && nch > 1) { - int pos = 1; - for ( ; res && pos < nch; pos += 2) - res = (validate_comma(CHILD(tree, pos)) - && vfunc(CHILD(tree, pos + 1))); + for ( ; res && *pos < nch; ) { + res = validate_child_func_inc(tree, pos); + if (!res || *pos >= nch) + break; + res = validate_comma(CHILD(tree, (*pos)++)); } } - return (res); + return res; +} + +/* X (',' X) [','] */ +static int +validate_repeating_list(node *tree, + int list_node_type, + int (*validate_child_func)(node *), + const char *const list_node_type_name) +{ + int nch = NCH(tree); + int res = (nch && validate_ntype(tree, list_node_type)); + int pos = 0; + + if (!res && !PyErr_Occurred()) { + /* Unconditionally raise. */ + (void) validate_numnodes(tree, 1, list_node_type_name); + } + else { + for ( ; res && pos < nch; ) { + res = validate_child_func(CHILD(tree, pos++)); + if (!res || pos >= nch) + break; + res = validate_comma(CHILD(tree, pos++)); + } + } + return res; } @@ -2451,9 +2482,9 @@ if (res && (nch == 3)) { if (TYPE(CHILD(tree, 1))==yield_expr) - res = validate_yield_expr(CHILD(tree, 1)); + res = validate_yield_expr(CHILD(tree, 1)); else - res = validate_testlist_comp(CHILD(tree, 1)); + res = validate_testlist_comp(CHILD(tree, 1)); } break; case LSQB: @@ -2493,39 +2524,28 @@ /* testlist_comp: - * test ( comp_for | (',' test)* [','] ) + * (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) */ static int validate_testlist_comp(node *tree) { int nch = NCH(tree); - int ok = nch; - - if (nch == 0) + int ok; + + if (nch == 0) { err_string("missing child nodes of testlist_comp"); + return 0; + } + + if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for) { + ok = (validate_test(CHILD(tree, 0)) + && validate_comp_for(CHILD(tree, 1))); + } else { - ok = validate_test_or_star_expr(CHILD(tree, 0)); - } - - /* - * comp_for | (',' test)* [','] - */ - if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for) - ok = validate_comp_for(CHILD(tree, 1)); - else { - /* (',' test)* [','] */ - int i = 1; - while (ok && nch - i >= 2) { - ok = (validate_comma(CHILD(tree, i)) - && validate_test_or_star_expr(CHILD(tree, i+1))); - i += 2; - } - if (ok && i == nch-1) - ok = validate_comma(CHILD(tree, i)); - else if (i != nch) { - ok = 0; - err_string("illegal trailing nodes for testlist_comp"); - } + ok = validate_repeating_list(tree, + testlist_comp, + validate_test_or_star_expr, + "testlist_comp"); } return ok; } @@ -2732,9 +2752,6 @@ } ok = 1; if (nch-i > 0) { - /* - * argument | '*' test [',' '**' test] | '**' test - */ int sym = TYPE(CHILD(tree, i)); if (sym == argument) { @@ -2745,30 +2762,7 @@ ok = 0; } } - else if (sym == STAR) { - ok = validate_star(CHILD(tree, i)); - if (ok && (nch-i == 2)) - ok = validate_test(CHILD(tree, i+1)); - else if (ok && (nch-i == 5)) - ok = (validate_test(CHILD(tree, i+1)) - && validate_comma(CHILD(tree, i+2)) - && validate_doublestar(CHILD(tree, i+3)) - && validate_test(CHILD(tree, i+4))); - else { - err_string("illegal use of '*' in arglist"); - ok = 0; - } - } - else if (sym == DOUBLESTAR) { - if (nch-i == 2) - ok = (validate_doublestar(CHILD(tree, i)) - && validate_test(CHILD(tree, i+1))); - else { - err_string("illegal use of '**' in arglist"); - ok = 0; - } - } - else { + else { err_string("illegal arglist specification"); ok = 0; } @@ -2778,9 +2772,10 @@ -/* argument: - * - * [test '='] test [comp_for] +/* argument: ( test [comp_for] | + * test '=' test | + * '**' expr | + * star_expr ) */ static int validate_argument(node *tree) @@ -2788,14 +2783,24 @@ int nch = NCH(tree); int res = (validate_ntype(tree, argument) && ((nch == 1) || (nch == 2) || (nch == 3))); - if (res) - res = validate_test(CHILD(tree, 0)); - if (res && (nch == 2)) - res = validate_comp_for(CHILD(tree, 1)); - else if (res && (nch == 3)) - res = (validate_equal(CHILD(tree, 1)) - && validate_test(CHILD(tree, 2))); - + + if (res) { + if (TYPE(CHILD(tree, 0)) == DOUBLESTAR) { + res = validate_expr(CHILD(tree, 1)); + } + else if (nch == 1) { + res = validate_test_or_star_expr(CHILD(tree, 0)); + } + else if (nch == 2) { + res = (validate_test(CHILD(tree, 0)) + && validate_comp_for(CHILD(tree, 1))); + } + else if (res && (nch == 3)) { + res = (validate_test(CHILD(tree, 0)) + && validate_equal(CHILD(tree, 1)) + && validate_test(CHILD(tree, 2))); + } + } return (res); } @@ -2948,11 +2953,44 @@ validate_expr_or_star_expr, "exprlist")); } +/* Incrementing validate functions returns nonzero iff success (like other + * validate functions, and advance *i by the length of the matched pattern. */ + +/* test ':' test */ +static int +validate_test_colon_test_inc(node *tree, int *i) +{ + return (validate_test(CHILD(tree, (*i)++)) + && validate_colon(CHILD(tree, (*i)++)) + && validate_test(CHILD(tree, (*i)++))); +} + +/* test ':' test | '**' expr */ +static int +validate_dict_element_inc(node *tree, int *i) +{ + int nch = NCH(tree); + int res = 0; + if (nch - *i >= 2) { + if (TYPE(CHILD(tree, *i+1)) == COLON) { + /* test ':' test */ + res = validate_test_colon_test_inc(tree, i); + } else { + /* '**' expr */ + res = (validate_doublestar(CHILD(tree, (*i)++)) + && validate_expr(CHILD(tree, (*i)++))); + } + } + return res; +} + /* * dictorsetmaker: * - * (test ':' test (comp_for | (',' test ':' test)* [','])) | - * (test (comp_for | (',' test)* [','])) + * ( ((test ':' test | '**' expr) + * (comp_for | (',' (test ':' test | '**' expr))* [','])) | + * ((test | '*' test) + * (comp_for | (',' (test | '*' test))* [','])) ) */ static int validate_dictorsetmaker(node *tree) @@ -2966,65 +3004,44 @@ return 0; if (nch - i < 1) { + /* Unconditionally raise. */ (void) validate_numnodes(tree, 1, "dictorsetmaker"); return 0; } - res = validate_test(CHILD(tree, i++)); - if (!res) - return 0; - - if (nch - i >= 2 && TYPE(CHILD(tree, i)) == COLON) { + if (nch - i >= 2 + && ((TYPE(CHILD(tree, i+1)) == COLON) || + (TYPE(CHILD(tree, i)) == DOUBLESTAR))) { /* Dictionary display or dictionary comprehension. */ - res = (validate_colon(CHILD(tree, i++)) - && validate_test(CHILD(tree, i++))); - if (!res) - return 0; - - if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) { + if (nch - i >= 4 && TYPE(CHILD(tree, i+3)) == comp_for) { /* Dictionary comprehension. */ - res = validate_comp_for(CHILD(tree, i++)); + res = (validate_test_colon_test_inc(tree, &i) + && validate_comp_for(CHILD(tree, i++))); if (!res) return 0; + } else { + /* Dictionary display. */ + return validate_repeating_list_variable( + tree, + dictorsetmaker, + validate_dict_element_inc, + &i, + "dictorsetmaker"); } - else { - /* Dictionary display. */ - while (nch - i >= 4) { - res = (validate_comma(CHILD(tree, i++)) - && validate_test(CHILD(tree, i++)) - && validate_colon(CHILD(tree, i++)) - && validate_test(CHILD(tree, i++))); - if (!res) - return 0; - } - if (nch - i == 1) { - res = validate_comma(CHILD(tree, i++)); - if (!res) - return 0; - } - } - } - else { + } else { /* Set display or set comprehension. */ - if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) { + if (nch - i >= 2 && TYPE(CHILD(tree, i + 1)) == comp_for) { /* Set comprehension. */ - res = validate_comp_for(CHILD(tree, i++)); + res = (validate_test(CHILD(tree, i++)) + && validate_comp_for(CHILD(tree, i++))); if (!res) return 0; - } - else { + } else { /* Set display. */ - while (nch - i >= 2) { - res = (validate_comma(CHILD(tree, i++)) - && validate_test(CHILD(tree, i++))); - if (!res) - return 0; - } - if (nch - i == 1) { - res = validate_comma(CHILD(tree, i++)); - if (!res) - return 0; - } + return validate_repeating_list(tree, + dictorsetmaker, + validate_test_or_star_expr, + "dictorsetmaker"); } } diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3412,8 +3412,8 @@ return result; } -static PyObject* -dictviews_and(PyObject* self, PyObject *other) +PyObject* +_PyDictView_Intersect(PyObject* self, PyObject *other) { PyObject *result = PySet_New(self); PyObject *tmp; @@ -3487,7 +3487,7 @@ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ - (binaryfunc)dictviews_and, /*nb_and*/ + (binaryfunc)_PyDictView_Intersect, /*nb_and*/ (binaryfunc)dictviews_xor, /*nb_xor*/ (binaryfunc)dictviews_or, /*nb_or*/ }; diff --git a/Parser/Python.asdl b/Parser/Python.asdl --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -14,8 +14,6 @@ | ClassDef(identifier name, expr* bases, keyword* keywords, - expr? starargs, - expr? kwargs, stmt* body, expr* decorator_list) | Return(expr? value) @@ -64,8 +62,7 @@ -- need sequences for compare to distinguish between -- x < 4 < 3 and (x < 4) < 3 | Compare(expr left, cmpop* ops, expr* comparators) - | Call(expr func, expr* args, keyword* keywords, - expr? starargs, expr? kwargs) + | Call(expr func, expr* args, keyword* keywords) | Num(object n) -- a number as a PyObject. | Str(string s) -- need to specify raw, unicode, etc? | Bytes(bytes s) @@ -109,8 +106,8 @@ arg = (identifier arg, expr? annotation) attributes (int lineno, int col_offset) - -- keyword arguments supplied to call - keyword = (identifier arg, expr value) + -- keyword arguments supplied to call (NULL identifier for **kwargs) + keyword = (identifier? arg, expr value) -- import name with optional 'as' alias. alias = (identifier name, identifier? asname) diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -48,14 +48,10 @@ static PyTypeObject *ClassDef_type; _Py_IDENTIFIER(bases); _Py_IDENTIFIER(keywords); -_Py_IDENTIFIER(starargs); -_Py_IDENTIFIER(kwargs); static char *ClassDef_fields[]={ "name", "bases", "keywords", - "starargs", - "kwargs", "body", "decorator_list", }; @@ -254,8 +250,6 @@ "func", "args", "keywords", - "starargs", - "kwargs", }; static PyTypeObject *Num_type; _Py_IDENTIFIER(n); @@ -812,7 +806,7 @@ FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, 5); if (!FunctionDef_type) return 0; - ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 7); + ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5); if (!ClassDef_type) return 0; Return_type = make_type("Return", stmt_type, Return_fields, 1); if (!Return_type) return 0; @@ -884,7 +878,7 @@ if (!YieldFrom_type) return 0; Compare_type = make_type("Compare", expr_type, Compare_fields, 3); if (!Compare_type) return 0; - Call_type = make_type("Call", expr_type, Call_fields, 5); + Call_type = make_type("Call", expr_type, Call_fields, 3); if (!Call_type) return 0; Num_type = make_type("Num", expr_type, Num_fields, 1); if (!Num_type) return 0; @@ -1207,9 +1201,9 @@ } stmt_ty -ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, expr_ty - starargs, expr_ty kwargs, asdl_seq * body, asdl_seq * decorator_list, - int lineno, int col_offset, PyArena *arena) +ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * + body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena + *arena) { stmt_ty p; if (!name) { @@ -1224,8 +1218,6 @@ p->v.ClassDef.name = name; p->v.ClassDef.bases = bases; p->v.ClassDef.keywords = keywords; - p->v.ClassDef.starargs = starargs; - p->v.ClassDef.kwargs = kwargs; p->v.ClassDef.body = body; p->v.ClassDef.decorator_list = decorator_list; p->lineno = lineno; @@ -1885,8 +1877,8 @@ } expr_ty -Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty starargs, - expr_ty kwargs, int lineno, int col_offset, PyArena *arena) +Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int lineno, int + col_offset, PyArena *arena) { expr_ty p; if (!func) { @@ -1901,8 +1893,6 @@ p->v.Call.func = func; p->v.Call.args = args; p->v.Call.keywords = keywords; - p->v.Call.starargs = starargs; - p->v.Call.kwargs = kwargs; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -2276,11 +2266,6 @@ keyword(identifier arg, expr_ty value, PyArena *arena) { keyword_ty p; - if (!arg) { - PyErr_SetString(PyExc_ValueError, - "field arg is required for keyword"); - return NULL; - } if (!value) { PyErr_SetString(PyExc_ValueError, "field value is required for keyword"); @@ -2442,16 +2427,6 @@ if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(o->v.ClassDef.starargs); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_starargs, value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.ClassDef.kwargs); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_kwargs, value) == -1) - goto failed; - Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt); if (!value) goto failed; if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) @@ -2964,16 +2939,6 @@ if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(o->v.Call.starargs); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_starargs, value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Call.kwargs); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_kwargs, value) == -1) - goto failed; - Py_DECREF(value); break; case Num_kind: result = PyType_GenericNew(Num_type, NULL, NULL); @@ -3875,8 +3840,6 @@ identifier name; asdl_seq* bases; asdl_seq* keywords; - expr_ty starargs; - expr_ty kwargs; asdl_seq* body; asdl_seq* decorator_list; @@ -3939,26 +3902,6 @@ PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from ClassDef"); return 1; } - if (exists_not_none(obj, &PyId_starargs)) { - int res; - tmp = _PyObject_GetAttrId(obj, &PyId_starargs); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &starargs, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } else { - starargs = NULL; - } - if (exists_not_none(obj, &PyId_kwargs)) { - int res; - tmp = _PyObject_GetAttrId(obj, &PyId_kwargs); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &kwargs, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } else { - kwargs = NULL; - } if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; @@ -4007,8 +3950,8 @@ PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from ClassDef"); return 1; } - *out = ClassDef(name, bases, keywords, starargs, kwargs, body, - decorator_list, lineno, col_offset, arena); + *out = ClassDef(name, bases, keywords, body, decorator_list, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -5506,8 +5449,6 @@ expr_ty func; asdl_seq* args; asdl_seq* keywords; - expr_ty starargs; - expr_ty kwargs; if (_PyObject_HasAttrId(obj, &PyId_func)) { int res; @@ -5568,28 +5509,7 @@ PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from Call"); return 1; } - if (exists_not_none(obj, &PyId_starargs)) { - int res; - tmp = _PyObject_GetAttrId(obj, &PyId_starargs); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &starargs, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } else { - starargs = NULL; - } - if (exists_not_none(obj, &PyId_kwargs)) { - int res; - tmp = _PyObject_GetAttrId(obj, &PyId_kwargs); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &kwargs, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } else { - kwargs = NULL; - } - *out = Call(func, args, keywords, starargs, kwargs, lineno, col_offset, - arena); + *out = Call(func, args, keywords, lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6737,7 +6657,7 @@ identifier arg; expr_ty value; - if (_PyObject_HasAttrId(obj, &PyId_arg)) { + if (exists_not_none(obj, &PyId_arg)) { int res; tmp = _PyObject_GetAttrId(obj, &PyId_arg); if (tmp == NULL) goto failed; @@ -6745,8 +6665,7 @@ if (res != 0) goto failed; Py_CLEAR(tmp); } else { - PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from keyword"); - return 1; + arg = NULL; } if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -235,9 +235,7 @@ case Call_kind: return validate_expr(exp->v.Call.func, Load) && validate_exprs(exp->v.Call.args, Load, 0) && - validate_keywords(exp->v.Call.keywords) && - (!exp->v.Call.starargs || validate_expr(exp->v.Call.starargs, Load)) && - (!exp->v.Call.kwargs || validate_expr(exp->v.Call.kwargs, Load)); + validate_keywords(exp->v.Call.keywords); case Num_kind: { PyObject *n = exp->v.Num.n; if (!PyLong_CheckExact(n) && !PyFloat_CheckExact(n) && @@ -322,9 +320,7 @@ return validate_body(stmt->v.ClassDef.body, "ClassDef") && validate_exprs(stmt->v.ClassDef.bases, Load, 0) && validate_keywords(stmt->v.ClassDef.keywords) && - validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0) && - (!stmt->v.ClassDef.starargs || validate_expr(stmt->v.ClassDef.starargs, Load)) && - (!stmt->v.ClassDef.kwargs || validate_expr(stmt->v.ClassDef.kwargs, Load)); + validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0); case Return_kind: return !stmt->v.Return.value || validate_expr(stmt->v.Return.value, Load); case Delete_kind: @@ -848,7 +844,8 @@ }; static int -forbidden_name(struct compiling *c, identifier name, const node *n, int full_checks) +forbidden_name(struct compiling *c, identifier name, const node *n, + int full_checks) { assert(PyUnicode_Check(name)); if (PyUnicode_CompareWithASCIIString(name, "__debug__") == 0) { @@ -1445,7 +1442,7 @@ name_expr = NULL; } else if (NCH(n) == 5) { /* Call with no arguments */ - d = Call(name_expr, NULL, NULL, NULL, NULL, LINENO(n), + d = Call(name_expr, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); if (!d) return NULL; @@ -1735,16 +1732,22 @@ static expr_ty ast_for_itercomp(struct compiling *c, const node *n, int type) { - /* testlist_comp: test ( comp_for | (',' test)* [','] ) - argument: [test '='] test [comp_for] # Really [keyword '='] test */ + /* testlist_comp: (test|star_expr) + * ( comp_for | (',' (test|star_expr))* [','] ) */ expr_ty elt; asdl_seq *comps; + node *ch; assert(NCH(n) > 1); - elt = ast_for_expr(c, CHILD(n, 0)); + ch = CHILD(n, 0); + elt = ast_for_expr(c, ch); if (!elt) return NULL; + if (elt->kind == Starred_kind) { + ast_error(c, ch, "iterable unpacking cannot be used in comprehension"); + return NULL; + } comps = ast_for_comprehension(c, CHILD(n, 1)); if (!comps) @@ -1761,23 +1764,59 @@ return NULL; } +/* Fills in the key, value pair corresponding to the dict element. In case + * of an unpacking, key is NULL. *i is advanced by the number of ast + * elements. Iff successful, nonzero is returned. + */ +static int +ast_for_dictelement(struct compiling *c, const node *n, int *i, + expr_ty *key, expr_ty *value) +{ + expr_ty expression; + if (TYPE(CHILD(n, *i)) == DOUBLESTAR) { + assert(NCH(n) - *i >= 2); + + expression = ast_for_expr(c, CHILD(n, *i + 1)); + if (!expression) + return 0; + *key = NULL; + *value = expression; + + *i += 2; + } + else { + assert(NCH(n) - *i >= 3); + + expression = ast_for_expr(c, CHILD(n, *i)); + if (!expression) + return 0; + *key = expression; + + REQ(CHILD(n, *i + 1), COLON); + + expression = ast_for_expr(c, CHILD(n, *i + 2)); + if (!expression) + return 0; + *value = expression; + + *i += 3; + } + return 1; +} + static expr_ty ast_for_dictcomp(struct compiling *c, const node *n) { expr_ty key, value; asdl_seq *comps; - - assert(NCH(n) > 3); - REQ(CHILD(n, 1), COLON); - - key = ast_for_expr(c, CHILD(n, 0)); - if (!key) + int i = 0; + + if (!ast_for_dictelement(c, n, &i, &key, &value)) return NULL; - value = ast_for_expr(c, CHILD(n, 2)); - if (!value) - return NULL; - - comps = ast_for_comprehension(c, CHILD(n, 3)); + assert(key); + assert(NCH(n) - i >= 1); + + comps = ast_for_comprehension(c, CHILD(n, i)); if (!comps) return NULL; @@ -1785,6 +1824,39 @@ } static expr_ty +ast_for_dictdisplay(struct compiling *c, const node *n) +{ + int i; + int j; + int size; + asdl_seq *keys, *values; + + size = (NCH(n) + 1) / 3; /* +1 in case no trailing comma */ + keys = _Py_asdl_seq_new(size, c->c_arena); + if (!keys) + return NULL; + + values = _Py_asdl_seq_new(size, c->c_arena); + if (!values) + return NULL; + + j = 0; + for (i = 0; i < NCH(n); i++) { + expr_ty key, value; + + if (!ast_for_dictelement(c, n, &i, &key, &value)) + return NULL; + asdl_seq_SET(keys, j, key); + asdl_seq_SET(values, j, value); + + j++; + } + keys->size = j; + values->size = j; + return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); +} + +static expr_ty ast_for_genexp(struct compiling *c, const node *n) { assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument)); @@ -1805,6 +1877,27 @@ return ast_for_itercomp(c, n, COMP_SETCOMP); } +static expr_ty +ast_for_setdisplay(struct compiling *c, const node *n) +{ + int i; + int size; + asdl_seq *elts; + + assert(TYPE(n) == (dictorsetmaker)); + size = (NCH(n) + 1) / 2; /* +1 in case no trailing comma */ + elts = _Py_asdl_seq_new(size, c->c_arena); + if (!elts) + return NULL; + for (i = 0; i < NCH(n); i += 2) { + expr_ty expression; + expression = ast_for_expr(c, CHILD(n, i)); + if (!expression) + return NULL; + asdl_seq_SET(elts, i / 2, expression); + } + return Set(elts, LINENO(n), n->n_col_offset, c->c_arena); +} static expr_ty ast_for_atom(struct compiling *c, const node *n) @@ -1915,62 +2008,42 @@ else return ast_for_listcomp(c, ch); case LBRACE: { - /* dictorsetmaker: test ':' test (',' test ':' test)* [','] | - * test (gen_for | (',' test)* [',']) */ - int i, size; - asdl_seq *keys, *values; - + /* dictorsetmaker: ( ((test ':' test | '**' test) + * (comp_for | (',' (test ':' test | '**' test))* [','])) | + * ((test | '*' test) + * (comp_for | (',' (test | '*' test))* [','])) ) */ ch = CHILD(n, 1); if (TYPE(ch) == RBRACE) { - /* it's an empty dict */ + /* It's an empty dict. */ return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { - /* it's a simple set */ - asdl_seq *elts; - size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */ - elts = _Py_asdl_seq_new(size, c->c_arena); - if (!elts) - return NULL; - for (i = 0; i < NCH(ch); i += 2) { - expr_ty expression; - expression = ast_for_expr(c, CHILD(ch, i)); - if (!expression) + } + else { + int is_dict = (TYPE(CHILD(ch, 0)) == DOUBLESTAR); + if (NCH(ch) == 1 || + (NCH(ch) > 1 && + TYPE(CHILD(ch, 1)) == COMMA)) { + /* It's a set display. */ + return ast_for_setdisplay(c, ch); + } + else if (NCH(ch) > 1 && + TYPE(CHILD(ch, 1)) == comp_for) { + /* It's a set comprehension. */ + return ast_for_setcomp(c, ch); + } + else if (NCH(ch) > 3 - is_dict && + TYPE(CHILD(ch, 3 - is_dict)) == comp_for) { + /* It's a dictionary comprehension. */ + if (is_dict) { + ast_error(c, n, "dict unpacking cannot be used in " + "dict comprehension"); return NULL; - asdl_seq_SET(elts, i / 2, expression); + } + return ast_for_dictcomp(c, ch); } - return Set(elts, LINENO(n), n->n_col_offset, c->c_arena); - } else if (TYPE(CHILD(ch, 1)) == comp_for) { - /* it's a set comprehension */ - return ast_for_setcomp(c, ch); - } else if (NCH(ch) > 3 && TYPE(CHILD(ch, 3)) == comp_for) { - return ast_for_dictcomp(c, ch); - } else { - /* it's a dict */ - size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ - keys = _Py_asdl_seq_new(size, c->c_arena); - if (!keys) - return NULL; - - values = _Py_asdl_seq_new(size, c->c_arena); - if (!values) - return NULL; - - for (i = 0; i < NCH(ch); i += 4) { - expr_ty expression; - - expression = ast_for_expr(c, CHILD(ch, i)); - if (!expression) - return NULL; - - asdl_seq_SET(keys, i / 4, expression); - - expression = ast_for_expr(c, CHILD(ch, i + 2)); - if (!expression) - return NULL; - - asdl_seq_SET(values, i / 4, expression); + else { + /* It's a dictionary display. */ + return ast_for_dictdisplay(c, ch); } - return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); } } default: @@ -2106,7 +2179,7 @@ REQ(n, trailer); if (TYPE(CHILD(n, 0)) == LPAR) { if (NCH(n) == 2) - return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n), + return Call(left_expr, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); else return ast_for_call(c, CHILD(n, 1), left_expr); @@ -2415,15 +2488,14 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) { /* - arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] - | '**' test) - argument: [test '='] (test) [comp_for] # Really [keyword '='] test + arglist: argument (',' argument)* [','] + argument: ( test [comp_for] | '*' test | test '=' test | '**' test ) */ int i, nargs, nkeywords, ngens; + int ndoublestars; asdl_seq *args; asdl_seq *keywords; - expr_ty vararg = NULL, kwarg = NULL; REQ(n, arglist); @@ -2437,7 +2509,10 @@ nargs++; else if (TYPE(CHILD(ch, 1)) == comp_for) ngens++; + else if (TYPE(CHILD(ch, 0)) == STAR) + nargs++; else + /* TYPE(CHILD(ch, 0)) == DOUBLESTAR or keyword argument */ nkeywords++; } } @@ -2458,41 +2533,82 @@ keywords = _Py_asdl_seq_new(nkeywords, c->c_arena); if (!keywords) return NULL; - nargs = 0; - nkeywords = 0; + + nargs = 0; /* positional arguments + iterable argument unpackings */ + nkeywords = 0; /* keyword arguments + keyword argument unpackings */ + ndoublestars = 0; /* just keyword argument unpackings */ for (i = 0; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) == argument) { expr_ty e; + node *chch = CHILD(ch, 0); if (NCH(ch) == 1) { - if (nkeywords) { - ast_error(c, CHILD(ch, 0), - "non-keyword arg after keyword arg"); - return NULL; + if (TYPE(chch) == star_expr) { + /* an iterable argument unpacking */ + expr_ty starred; + if (ndoublestars) { + ast_error(c, chch, + "iterable argument unpacking follows " + "keyword argument unpacking"); + return NULL; + } + e = ast_for_expr(c, CHILD(chch, 1)); + if (!e) + return NULL; + starred = Starred(e, Load, LINENO(chch), + chch->n_col_offset, + c->c_arena); + if (!starred) + return NULL; + asdl_seq_SET(args, nargs++, starred); } - if (vararg) { - ast_error(c, CHILD(ch, 0), - "only named arguments may follow *expression"); - return NULL; + else { + /* a positional argument */ + if (nkeywords) { + if (ndoublestars) { + ast_error(c, chch, + "positional argument follows " + "keyword argument unpacking"); + } + else { + ast_error(c, chch, + "positional argument follows " + "keyword argument"); + } + return NULL; + } + e = ast_for_expr(c, chch); + if (!e) + return NULL; + asdl_seq_SET(args, nargs++, e); } - e = ast_for_expr(c, CHILD(ch, 0)); + } + else if (TYPE(chch) == DOUBLESTAR) { + /* a keyword argument unpacking */ + keyword_ty kw; + i++; + e = ast_for_expr(c, CHILD(ch, 1)); if (!e) return NULL; - asdl_seq_SET(args, nargs++, e); + kw = keyword(NULL, e, c->c_arena); + asdl_seq_SET(keywords, nkeywords++, kw); + ndoublestars++; } else if (TYPE(CHILD(ch, 1)) == comp_for) { + /* the lone generator expression */ e = ast_for_genexp(c, ch); if (!e) return NULL; asdl_seq_SET(args, nargs++, e); } else { + /* a keyword argument */ keyword_ty kw; identifier key, tmp; int k; - /* CHILD(ch, 0) is test, but must be an identifier? */ - e = ast_for_expr(c, CHILD(ch, 0)); + /* chch is test, but must be an identifier? */ + e = ast_for_expr(c, chch); if (!e) return NULL; /* f(lambda x: x[0] = 3) ends up getting parsed with @@ -2501,19 +2617,24 @@ * then is very confusing. */ if (e->kind == Lambda_kind) { - ast_error(c, CHILD(ch, 0), "lambda cannot contain assignment"); + ast_error(c, chch, + "lambda cannot contain assignment"); return NULL; - } else if (e->kind != Name_kind) { - ast_error(c, CHILD(ch, 0), "keyword can't be an expression"); + } + else if (e->kind != Name_kind) { + ast_error(c, chch, + "keyword can't be an expression"); return NULL; - } else if (forbidden_name(c, e->v.Name.id, ch, 1)) { + } + else if (forbidden_name(c, e->v.Name.id, ch, 1)) { return NULL; } key = e->v.Name.id; for (k = 0; k < nkeywords; k++) { tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg; - if (!PyUnicode_Compare(tmp, key)) { - ast_error(c, CHILD(ch, 0), "keyword argument repeated"); + if (tmp && !PyUnicode_Compare(tmp, key)) { + ast_error(c, chch, + "keyword argument repeated"); return NULL; } } @@ -2526,21 +2647,9 @@ asdl_seq_SET(keywords, nkeywords++, kw); } } - else if (TYPE(ch) == STAR) { - vararg = ast_for_expr(c, CHILD(n, i+1)); - if (!vararg) - return NULL; - i++; - } - else if (TYPE(ch) == DOUBLESTAR) { - kwarg = ast_for_expr(c, CHILD(n, i+1)); - if (!kwarg) - return NULL; - i++; - } } - return Call(func, args, keywords, vararg, kwarg, func->lineno, func->col_offset, c->c_arena); + return Call(func, args, keywords, func->lineno, func->col_offset, c->c_arena); } static expr_ty @@ -3520,8 +3629,8 @@ return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, - LINENO(n), n->n_col_offset, c->c_arena); + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), + n->n_col_offset, c->c_arena); } if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */ @@ -3533,8 +3642,8 @@ return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, - LINENO(n), n->n_col_offset, c->c_arena); + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), + n->n_col_offset, c->c_arena); } /* class NAME '(' arglist ')' ':' suite */ @@ -3559,8 +3668,7 @@ if (forbidden_name(c, classname, CHILD(n, 1), 0)) return NULL; - return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, - call->v.Call.starargs, call->v.Call.kwargs, s, + return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -12,8 +12,10 @@ #include "Python.h" #include "code.h" +#include "dictobject.h" #include "frameobject.h" #include "opcode.h" +#include "setobject.h" #include "structmember.h" #include @@ -2379,6 +2381,43 @@ DISPATCH(); } + TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack) + TARGET(BUILD_LIST_UNPACK) + _build_list_unpack: { + int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; + int i; + PyObject *sum = PyList_New(0); + PyObject *return_value; + if (sum == NULL) + goto error; + + for (i = oparg; i > 0; i--) { + PyObject *none_val; + + none_val = _PyList_Extend((PyListObject *)sum, PEEK(i)); + if (none_val == NULL) { + Py_DECREF(sum); + goto error; + } + Py_DECREF(none_val); + } + + if (convert_to_tuple) { + return_value = PyList_AsTuple(sum); + Py_DECREF(sum); + if (return_value == NULL) + goto error; + } + else { + return_value = sum; + } + + while (oparg--) + Py_DECREF(POP()); + PUSH(return_value); + DISPATCH(); + } + TARGET(BUILD_SET) { PyObject *set = PySet_New(NULL); int err = 0; @@ -2398,14 +2437,127 @@ DISPATCH(); } + TARGET(BUILD_SET_UNPACK) { + int i; + PyObject *sum = PySet_New(NULL); + if (sum == NULL) + goto error; + + for (i = oparg; i > 0; i--) { + if (_PySet_Update(sum, PEEK(i)) < 0) { + Py_DECREF(sum); + goto error; + } + } + + while (oparg--) + Py_DECREF(POP()); + PUSH(sum); + DISPATCH(); + } + TARGET(BUILD_MAP) { PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); if (map == NULL) goto error; + while (--oparg >= 0) { + int err; + PyObject *key = TOP(); + PyObject *value = SECOND(); + STACKADJ(-2); + err = PyDict_SetItem(map, key, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) { + Py_DECREF(map); + goto error; + } + } PUSH(map); DISPATCH(); } + TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack) + TARGET(BUILD_MAP_UNPACK) + _build_map_unpack: { + int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; + int num_maps; + int function_location; + int i; + PyObject *sum = PyDict_New(); + if (sum == NULL) + goto error; + if (with_call) { + num_maps = oparg & 0xff; + function_location = (oparg>>8) & 0xff; + } + else { + num_maps = oparg; + } + + for (i = num_maps; i > 0; i--) { + PyObject *arg = PEEK(i); + if (with_call) { + PyObject *intersection = _PyDictView_Intersect(sum, arg); + + if (intersection == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyObject *func = ( + PEEK(function_location + num_maps)); + PyErr_Format(PyExc_TypeError, + "%.200s%.200s argument after ** " + "must be a mapping, not %.200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + arg->ob_type->tp_name); + } + Py_DECREF(sum); + goto error; + } + + if (PySet_GET_SIZE(intersection)) { + Py_ssize_t idx = 0; + PyObject *key; + PyObject *func = PEEK(function_location + num_maps); + Py_hash_t hash; + _PySet_NextEntry(intersection, &idx, &key, &hash); + if (!PyUnicode_Check(key)) { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s keywords must be strings", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func)); + } else { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s got multiple " + "values for keyword argument '%U'", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + key); + } + Py_DECREF(intersection); + Py_DECREF(sum); + goto error; + } + Py_DECREF(intersection); + } + + if (PyDict_Update(sum, arg) < 0) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not a mapping", + arg->ob_type->tp_name); + } + Py_DECREF(sum); + goto error; + } + } + + while (num_maps--) + Py_DECREF(POP()); + PUSH(sum); + DISPATCH(); + } + TARGET(STORE_MAP) { PyObject *key = TOP(); PyObject *value = SECOND(); @@ -3050,6 +3202,7 @@ goto dispatch_opcode; } + #if USE_COMPUTED_GOTOS _unknown_opcode: #endif @@ -4557,6 +4710,12 @@ kwdict = d; } } + if (nk > 0) { + kwdict = update_keyword_args(kwdict, nk, pp_stack, func); + if (kwdict == NULL) + goto ext_call_fail; + } + if (flags & CALL_FLAG_VAR) { stararg = EXT_POP(*pp_stack); if (!PyTuple_Check(stararg)) { @@ -4578,11 +4737,6 @@ } nstar = PyTuple_GET_SIZE(stararg); } - if (nk > 0) { - kwdict = update_keyword_args(kwdict, nk, pp_stack, func); - if (kwdict == NULL) - goto ext_call_fail; - } callargs = update_star_args(na, nstar, stararg, pp_stack); if (callargs == NULL) goto ext_call_fail; diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -195,9 +195,7 @@ static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_call_helper(struct compiler *c, Py_ssize_t n, asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs); + asdl_seq *keywords); static int compiler_try_except(struct compiler *, stmt_ty); static int compiler_set_qualname(struct compiler *); @@ -672,7 +670,8 @@ PyObject *mangled, *capsule; capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + parent = (struct compiler_unit *)PyCapsule_GetPointer( + capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); assert(parent); if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { @@ -973,6 +972,13 @@ case BUILD_LIST: case BUILD_SET: return 1-oparg; + case BUILD_LIST_UNPACK: + case BUILD_TUPLE_UNPACK: + case BUILD_SET_UNPACK: + case BUILD_MAP_UNPACK: + return 1 - oparg; + case BUILD_MAP_UNPACK_WITH_CALL: + return 1 - (oparg & 0xFF); case BUILD_MAP: return 1; case LOAD_ATTR: @@ -1821,9 +1827,7 @@ /* 5. generate the rest of the code for the call */ if (!compiler_call_helper(c, 2, s->v.ClassDef.bases, - s->v.ClassDef.keywords, - s->v.ClassDef.starargs, - s->v.ClassDef.kwargs)) + s->v.ClassDef.keywords)) return 0; /* 6. apply decorators */ @@ -2871,67 +2875,145 @@ } static int +starunpack_helper(struct compiler *c, asdl_seq *elts, + int single_op, int inner_op, int outer_op) +{ + Py_ssize_t n = asdl_seq_LEN(elts); + Py_ssize_t i, nsubitems = 0, nseen = 0; + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(elts, i); + if (elt->kind == Starred_kind) { + if (nseen) { + ADDOP_I(c, inner_op, nseen); + nseen = 0; + nsubitems++; + } + VISIT(c, expr, elt->v.Starred.value); + nsubitems++; + } + else { + VISIT(c, expr, elt); + nseen++; + } + } + if (nsubitems) { + if (nseen) { + ADDOP_I(c, inner_op, nseen); + nsubitems++; + } + ADDOP_I(c, outer_op, nsubitems); + } + else + ADDOP_I(c, single_op, nseen); + return 1; +} + +static int +assignment_helper(struct compiler *c, asdl_seq *elts) +{ + Py_ssize_t n = asdl_seq_LEN(elts); + Py_ssize_t i; + int seen_star = 0; + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(elts, i); + if (elt->kind == Starred_kind && !seen_star) { + if ((i >= (1 << 8)) || + (n-i-1 >= (INT_MAX >> 8))) + return compiler_error(c, + "too many expressions in " + "star-unpacking assignment"); + ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); + seen_star = 1; + asdl_seq_SET(elts, i, elt->v.Starred.value); + } + else if (elt->kind == Starred_kind) { + return compiler_error(c, + "two starred expressions in assignment"); + } + } + if (!seen_star) { + ADDOP_I(c, UNPACK_SEQUENCE, n); + } + VISIT_SEQ(c, expr, elts); + return 1; +} + +static int compiler_list(struct compiler *c, expr_ty e) { - Py_ssize_t n = asdl_seq_LEN(e->v.List.elts); + asdl_seq *elts = e->v.List.elts; if (e->v.List.ctx == Store) { - int i, seen_star = 0; - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(e->v.List.elts, i); - if (elt->kind == Starred_kind && !seen_star) { - if ((i >= (1 << 8)) || - (n-i-1 >= (INT_MAX >> 8))) - return compiler_error(c, - "too many expressions in " - "star-unpacking assignment"); - ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); - seen_star = 1; - asdl_seq_SET(e->v.List.elts, i, elt->v.Starred.value); - } else if (elt->kind == Starred_kind) { - return compiler_error(c, - "two starred expressions in assignment"); - } - } - if (!seen_star) { - ADDOP_I(c, UNPACK_SEQUENCE, n); - } + return assignment_helper(c, elts); } - VISIT_SEQ(c, expr, e->v.List.elts); - if (e->v.List.ctx == Load) { - ADDOP_I(c, BUILD_LIST, n); + else if (e->v.List.ctx == Load) { + return starunpack_helper(c, elts, + BUILD_LIST, BUILD_TUPLE, BUILD_LIST_UNPACK); } + else + VISIT_SEQ(c, expr, elts); return 1; } static int compiler_tuple(struct compiler *c, expr_ty e) { - Py_ssize_t n = asdl_seq_LEN(e->v.Tuple.elts); + asdl_seq *elts = e->v.Tuple.elts; if (e->v.Tuple.ctx == Store) { - int i, seen_star = 0; - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(e->v.Tuple.elts, i); - if (elt->kind == Starred_kind && !seen_star) { - if ((i >= (1 << 8)) || - (n-i-1 >= (INT_MAX >> 8))) - return compiler_error(c, - "too many expressions in " - "star-unpacking assignment"); - ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); - seen_star = 1; - asdl_seq_SET(e->v.Tuple.elts, i, elt->v.Starred.value); - } else if (elt->kind == Starred_kind) { - return compiler_error(c, - "two starred expressions in assignment"); - } + return assignment_helper(c, elts); + } + else if (e->v.Tuple.ctx == Load) { + return starunpack_helper(c, elts, + BUILD_TUPLE, BUILD_TUPLE, BUILD_TUPLE_UNPACK); + } + else + VISIT_SEQ(c, expr, elts); + return 1; +} + +static int +compiler_set(struct compiler *c, expr_ty e) +{ + return starunpack_helper(c, e->v.Set.elts, BUILD_SET, + BUILD_SET, BUILD_SET_UNPACK); +} + +static int +compiler_dict(struct compiler *c, expr_ty e) +{ + Py_ssize_t i, n, containers, elements; + int is_unpacking = 0; + n = asdl_seq_LEN(e->v.Dict.values); + containers = 0; + elements = 0; + for (i = 0; i < n; i++) { + is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL; + if (elements == 0xFFFF || (elements && is_unpacking)) { + ADDOP_I(c, BUILD_MAP, elements); + containers++; + elements = 0; } - if (!seen_star) { - ADDOP_I(c, UNPACK_SEQUENCE, n); + if (is_unpacking) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + containers++; + } + else { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + elements++; } } - VISIT_SEQ(c, expr, e->v.Tuple.elts); - if (e->v.Tuple.ctx == Load) { - ADDOP_I(c, BUILD_TUPLE, n); + if (elements || containers == 0) { + ADDOP_I(c, BUILD_MAP, elements); + containers++; + } + /* If there is more than one dict, they need to be merged into a new + * dict. If there is one dict and it's an unpacking, then it needs + * to be copied into a new dict." */ + while (containers > 1 || is_unpacking) { + int oparg = containers < 255 ? containers : 255; + ADDOP_I(c, BUILD_MAP_UNPACK, oparg); + containers -= (oparg - 1); + is_unpacking = 0; } return 1; } @@ -2987,9 +3069,7 @@ VISIT(c, expr, e->v.Call.func); return compiler_call_helper(c, 0, e->v.Call.args, - e->v.Call.keywords, - e->v.Call.starargs, - e->v.Call.kwargs); + e->v.Call.keywords); } /* shared code between compiler_call and compiler_class */ @@ -2997,26 +3077,102 @@ compiler_call_helper(struct compiler *c, Py_ssize_t n, /* Args already pushed */ asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs) + asdl_seq *keywords) { int code = 0; - - n += asdl_seq_LEN(args); - VISIT_SEQ(c, expr, args); - if (keywords) { - VISIT_SEQ(c, keyword, keywords); - n |= asdl_seq_LEN(keywords) << 8; + Py_ssize_t nelts, i, nseen, nkw; + + /* the number of tuples and dictionaries on the stack */ + Py_ssize_t nsubargs = 0, nsubkwargs = 0; + + nkw = 0; + nseen = 0; /* the number of positional arguments on the stack */ + nelts = asdl_seq_LEN(args); + for (i = 0; i < nelts; i++) { + expr_ty elt = asdl_seq_GET(args, i); + if (elt->kind == Starred_kind) { + /* A star-arg. If we've seen positional arguments, + pack the positional arguments into a + tuple. */ + if (nseen) { + ADDOP_I(c, BUILD_TUPLE, nseen); + nseen = 0; + nsubargs++; + } + VISIT(c, expr, elt->v.Starred.value); + nsubargs++; + } + else if (nsubargs) { + /* We've seen star-args already, so we + count towards items-to-pack-into-tuple. */ + VISIT(c, expr, elt); + nseen++; + } + else { + /* Positional arguments before star-arguments + are left on the stack. */ + VISIT(c, expr, elt); + n++; + } } - if (starargs) { - VISIT(c, expr, starargs); + if (nseen) { + /* Pack up any trailing positional arguments. */ + ADDOP_I(c, BUILD_TUPLE, nseen); + nsubargs++; + } + if (nsubargs) { code |= 1; + if (nsubargs > 1) { + /* If we ended up with more than one stararg, we need + to concatenate them into a single sequence. */ + ADDOP_I(c, BUILD_LIST_UNPACK, nsubargs); + } } - if (kwargs) { - VISIT(c, expr, kwargs); + + /* Same dance again for keyword arguments */ + nseen = 0; /* the number of keyword arguments on the stack following */ + nelts = asdl_seq_LEN(keywords); + for (i = 0; i < nelts; i++) { + keyword_ty kw = asdl_seq_GET(keywords, i); + if (kw->arg == NULL) { + /* A keyword argument unpacking. */ + if (nseen) { + ADDOP_I(c, BUILD_MAP, nseen); + nseen = 0; + nsubkwargs++; + } + VISIT(c, expr, kw->value); + nsubkwargs++; + } + else if (nsubkwargs) { + /* A keyword argument and we already have a dict. */ + VISIT(c, expr, kw->value); + ADDOP_O(c, LOAD_CONST, kw->arg, consts); + nseen++; + } + else { + /* keyword argument */ + VISIT(c, keyword, kw) + nkw++; + } + } + if (nseen) { + /* Pack up any trailing keyword arguments. */ + ADDOP_I(c, BUILD_MAP, nseen); + nsubkwargs++; + } + if (nsubkwargs) { code |= 2; + if (nsubkwargs > 1) { + /* Pack it all up */ + int function_pos = n + (code & 1) + nkw + 1; + ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs | (function_pos << 8)); + } } + assert(n < 1<<8); + assert(nkw < 1<<24); + n |= nkw << 8; + switch (code) { case 0: ADDOP_I(c, CALL_FUNCTION, n); @@ -3141,8 +3297,9 @@ } static int -compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, - asdl_seq *generators, expr_ty elt, expr_ty val) +compiler_comprehension(struct compiler *c, expr_ty e, int type, + identifier name, asdl_seq *generators, expr_ty elt, + expr_ty val) { PyCodeObject *co = NULL; expr_ty outermost_iter; @@ -3399,8 +3556,6 @@ static int compiler_visit_expr(struct compiler *c, expr_ty e) { - Py_ssize_t i, n; - /* If expr e has a different line number than the last expr/stmt, set a new line number for the next instruction. */ @@ -3427,23 +3582,9 @@ case IfExp_kind: return compiler_ifexp(c, e); case Dict_kind: - n = asdl_seq_LEN(e->v.Dict.values); - /* BUILD_MAP parameter is only used to preallocate the dictionary, - it doesn't need to be exact */ - ADDOP_I(c, BUILD_MAP, (n>0xFFFF ? 0xFFFF : n)); - for (i = 0; i < n; i++) { - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); - ADDOP(c, STORE_MAP); - } - break; + return compiler_dict(c, e); case Set_kind: - n = asdl_seq_LEN(e->v.Set.elts); - VISIT_SEQ(c, expr, e->v.Set.elts); - ADDOP_I(c, BUILD_SET, n); - break; + return compiler_set(c, e); case GeneratorExp_kind: return compiler_genexp(c, e); case ListComp_kind: @@ -3554,7 +3695,7 @@ "starred assignment target must be in a list or tuple"); default: return compiler_error(c, - "can use starred expression only as assignment target"); + "can't use starred expression here"); } break; case Name_kind: diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1569,60 +1569,78 @@ {2, arcs_71_1}, {2, arcs_71_2}, }; -static arc arcs_72_0[1] = { +static arc arcs_72_0[3] = { {24, 1}, + {32, 2}, + {48, 3}, }; static arc arcs_72_1[4] = { - {25, 2}, - {159, 3}, - {30, 4}, + {25, 4}, + {159, 5}, + {30, 6}, {0, 1}, }; static arc arcs_72_2[1] = { - {24, 5}, + {104, 7}, }; -static arc arcs_72_3[1] = { +static arc arcs_72_3[3] = { + {159, 5}, + {30, 6}, {0, 3}, }; -static arc arcs_72_4[2] = { - {24, 6}, - {0, 4}, +static arc arcs_72_4[1] = { + {24, 7}, }; -static arc arcs_72_5[3] = { - {159, 3}, - {30, 7}, +static arc arcs_72_5[1] = { {0, 5}, }; -static arc arcs_72_6[2] = { - {30, 4}, +static arc arcs_72_6[3] = { + {24, 8}, + {48, 8}, {0, 6}, }; -static arc arcs_72_7[2] = { - {24, 8}, +static arc arcs_72_7[3] = { + {159, 5}, + {30, 9}, {0, 7}, }; -static arc arcs_72_8[1] = { - {25, 9}, +static arc arcs_72_8[2] = { + {30, 6}, + {0, 8}, }; -static arc arcs_72_9[1] = { +static arc arcs_72_9[3] = { {24, 10}, + {32, 11}, + {0, 9}, }; -static arc arcs_72_10[2] = { - {30, 7}, - {0, 10}, +static arc arcs_72_10[1] = { + {25, 12}, }; -static state states_72[11] = { - {1, arcs_72_0}, +static arc arcs_72_11[1] = { + {104, 13}, +}; +static arc arcs_72_12[1] = { + {24, 13}, +}; +static arc arcs_72_13[2] = { + {30, 9}, + {0, 13}, +}; +static state states_72[14] = { + {3, arcs_72_0}, {4, arcs_72_1}, {1, arcs_72_2}, - {1, arcs_72_3}, - {2, arcs_72_4}, - {3, arcs_72_5}, - {2, arcs_72_6}, - {2, arcs_72_7}, - {1, arcs_72_8}, - {1, arcs_72_9}, - {2, arcs_72_10}, + {3, arcs_72_3}, + {1, arcs_72_4}, + {1, arcs_72_5}, + {3, arcs_72_6}, + {3, arcs_72_7}, + {2, arcs_72_8}, + {3, arcs_72_9}, + {1, arcs_72_10}, + {1, arcs_72_11}, + {1, arcs_72_12}, + {2, arcs_72_13}, }; static arc arcs_73_0[1] = { {163, 1}, @@ -1660,67 +1678,47 @@ {1, arcs_73_6}, {1, arcs_73_7}, }; -static arc arcs_74_0[3] = { +static arc arcs_74_0[1] = { {164, 1}, - {31, 2}, - {32, 3}, }; static arc arcs_74_1[2] = { - {30, 4}, + {30, 2}, {0, 1}, }; -static arc arcs_74_2[1] = { - {24, 5}, +static arc arcs_74_2[2] = { + {164, 1}, + {0, 2}, }; -static arc arcs_74_3[1] = { - {24, 6}, +static state states_74[3] = { + {1, arcs_74_0}, + {2, arcs_74_1}, + {2, arcs_74_2}, }; -static arc arcs_74_4[4] = { - {164, 1}, - {31, 2}, - {32, 3}, - {0, 4}, -}; -static arc arcs_74_5[2] = { - {30, 7}, - {0, 5}, -}; -static arc arcs_74_6[1] = { - {0, 6}, -}; -static arc arcs_74_7[2] = { - {164, 5}, - {32, 3}, -}; -static state states_74[8] = { - {3, arcs_74_0}, - {2, arcs_74_1}, - {1, arcs_74_2}, - {1, arcs_74_3}, - {4, arcs_74_4}, - {2, arcs_74_5}, - {1, arcs_74_6}, - {2, arcs_74_7}, -}; -static arc arcs_75_0[1] = { +static arc arcs_75_0[3] = { {24, 1}, + {32, 2}, + {48, 3}, }; static arc arcs_75_1[3] = { - {159, 2}, - {29, 3}, + {159, 3}, + {29, 4}, {0, 1}, }; static arc arcs_75_2[1] = { - {0, 2}, + {104, 3}, }; static arc arcs_75_3[1] = { - {24, 2}, + {0, 3}, }; -static state states_75[4] = { - {1, arcs_75_0}, +static arc arcs_75_4[1] = { + {24, 3}, +}; +static state states_75[5] = { + {3, arcs_75_0}, {3, arcs_75_1}, {1, arcs_75_2}, {1, arcs_75_3}, + {1, arcs_75_4}, }; static arc arcs_76_0[2] = { {159, 1}, @@ -1964,14 +1962,14 @@ "\000\040\040\200\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, {327, "testlist", 0, 3, states_71, "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {328, "dictorsetmaker", 0, 11, states_72, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, + {328, "dictorsetmaker", 0, 14, states_72, + "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, {329, "classdef", 0, 8, states_73, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000"}, - {330, "arglist", 0, 8, states_74, + {330, "arglist", 0, 3, states_74, "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {331, "argument", 0, 4, states_75, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, + {331, "argument", 0, 5, states_75, + "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, {332, "comp_iter", 0, 2, states_76, "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"}, {333, "comp_for", 0, 6, states_77, diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -261,7 +261,7 @@ 5,0,0,0,218,13,95,119,114,105,116,101,95,97,116,111, 109,105,99,99,0,0,0,115,26,0,0,0,0,5,24,1, 9,1,33,1,3,3,21,1,19,1,20,1,13,1,3,1, - 17,1,13,1,5,1,114,55,0,0,0,105,248,12,0,0, + 17,1,13,1,5,1,114,55,0,0,0,105,2,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, @@ -371,7 +371,7 @@ 90,15,97,108,109,111,115,116,95,102,105,108,101,110,97,109, 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,17,99,97,99,104,101,95,102,114,111,109,95,115,111,117, - 114,99,101,240,0,0,0,115,46,0,0,0,0,18,12,1, + 114,99,101,241,0,0,0,115,46,0,0,0,0,18,12,1, 9,1,7,1,12,1,6,1,12,1,18,1,18,1,24,1, 12,1,12,1,12,1,36,1,12,1,18,1,9,2,12,1, 12,1,12,1,12,1,21,1,21,1,114,79,0,0,0,99, @@ -450,7 +450,7 @@ 118,101,108,90,13,98,97,115,101,95,102,105,108,101,110,97, 109,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, 0,218,17,115,111,117,114,99,101,95,102,114,111,109,95,99, - 97,99,104,101,28,1,0,0,115,44,0,0,0,0,9,18, + 97,99,104,101,29,1,0,0,115,44,0,0,0,0,9,18, 1,12,1,18,1,18,1,12,1,9,1,15,1,15,1,12, 1,9,1,15,1,12,1,22,1,15,1,9,1,12,1,22, 1,12,1,9,1,12,1,19,1,114,85,0,0,0,99,1, @@ -487,7 +487,7 @@ 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,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,218,15,95, - 103,101,116,95,115,111,117,114,99,101,102,105,108,101,61,1, + 103,101,116,95,115,111,117,114,99,101,102,105,108,101,62,1, 0,0,115,20,0,0,0,0,7,18,1,4,1,24,1,35, 1,4,1,3,1,16,1,19,1,21,1,114,91,0,0,0, 99,1,0,0,0,0,0,0,0,1,0,0,0,11,0,0, @@ -502,7 +502,7 @@ 0,114,79,0,0,0,114,66,0,0,0,114,74,0,0,0, 41,1,218,8,102,105,108,101,110,97,109,101,114,4,0,0, 0,114,4,0,0,0,114,5,0,0,0,218,11,95,103,101, - 116,95,99,97,99,104,101,100,80,1,0,0,115,16,0,0, + 116,95,99,97,99,104,101,100,81,1,0,0,115,16,0,0, 0,0,1,21,1,3,1,14,1,13,1,8,1,21,1,4, 2,114,95,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,60,0,0,0, @@ -517,7 +517,7 @@ 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,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,10,95,99,97,108,99, - 95,109,111,100,101,92,1,0,0,115,12,0,0,0,0,2, + 95,109,111,100,101,93,1,0,0,115,12,0,0,0,0,2, 3,1,19,1,13,1,11,3,10,1,114,97,0,0,0,218, 9,118,101,114,98,111,115,105,116,121,114,29,0,0,0,99, 1,0,0,0,1,0,0,0,3,0,0,0,4,0,0,0, @@ -538,7 +538,7 @@ 116,100,101,114,114,41,3,114,75,0,0,0,114,98,0,0, 0,218,4,97,114,103,115,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,16,95,118,101,114,98,111,115,101, - 95,109,101,115,115,97,103,101,104,1,0,0,115,8,0,0, + 95,109,101,115,115,97,103,101,105,1,0,0,115,8,0,0, 0,0,2,18,1,15,1,10,1,114,105,0,0,0,99,1, 0,0,0,0,0,0,0,3,0,0,0,11,0,0,0,3, 0,0,0,115,84,0,0,0,100,1,0,135,0,0,102,1, @@ -577,7 +577,7 @@ 6,107,119,97,114,103,115,41,1,218,6,109,101,116,104,111, 100,114,4,0,0,0,114,5,0,0,0,218,19,95,99,104, 101,99,107,95,110,97,109,101,95,119,114,97,112,112,101,114, - 120,1,0,0,115,10,0,0,0,0,1,12,1,12,1,15, + 121,1,0,0,115,10,0,0,0,0,1,12,1,12,1,15, 1,22,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, @@ -596,7 +596,7 @@ 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,52, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,5,95,119,114,97,112,130,1,0,0,115,8,0, + 0,0,218,5,95,119,114,97,112,131,1,0,0,115,8,0, 0,0,0,1,25,1,15,1,29,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,3,218,10,95,98,111,111,116,115, @@ -604,7 +604,7 @@ 114,114,111,114,41,3,114,109,0,0,0,114,110,0,0,0, 114,120,0,0,0,114,4,0,0,0,41,1,114,109,0,0, 0,114,5,0,0,0,218,11,95,99,104,101,99,107,95,110, - 97,109,101,112,1,0,0,115,14,0,0,0,0,8,21,6, + 97,109,101,113,1,0,0,115,14,0,0,0,0,8,21,6, 3,1,13,1,13,2,17,5,13,1,114,123,0,0,0,99, 2,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, 67,0,0,0,115,84,0,0,0,124,0,0,106,0,0,124, @@ -633,7 +633,7 @@ 97,109,101,218,6,108,111,97,100,101,114,218,8,112,111,114, 116,105,111,110,115,218,3,109,115,103,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,17,95,102,105,110,100, - 95,109,111,100,117,108,101,95,115,104,105,109,139,1,0,0, + 95,109,111,100,117,108,101,95,115,104,105,109,140,1,0,0, 115,10,0,0,0,0,10,21,1,24,1,6,1,29,1,114, 130,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,87,0,0,0,116,0, @@ -657,7 +657,7 @@ 4,114,108,0,0,0,114,126,0,0,0,218,4,115,112,101, 99,218,6,109,111,100,117,108,101,114,4,0,0,0,114,4, 0,0,0,114,5,0,0,0,218,17,95,108,111,97,100,95, - 109,111,100,117,108,101,95,115,104,105,109,157,1,0,0,115, + 109,111,100,117,108,101,95,115,104,105,109,158,1,0,0,115, 12,0,0,0,0,6,15,1,15,1,13,1,16,1,11,2, 114,135,0,0,0,99,4,0,0,0,0,0,0,0,11,0, 0,0,19,0,0,0,67,0,0,0,115,228,1,0,0,105, @@ -742,7 +742,7 @@ 115,111,117,114,99,101,95,115,105,122,101,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,25,95,118,97,108, 105,100,97,116,101,95,98,121,116,101,99,111,100,101,95,104, - 101,97,100,101,114,172,1,0,0,115,76,0,0,0,0,11, + 101,97,100,101,114,173,1,0,0,115,76,0,0,0,0,11, 6,1,12,1,13,3,6,1,12,1,10,1,16,1,16,1, 16,1,12,1,18,1,10,1,18,1,18,1,15,1,10,1, 15,1,18,1,15,1,10,1,12,1,12,1,3,1,20,1, @@ -773,7 +773,7 @@ 0,114,89,0,0,0,114,90,0,0,0,218,4,99,111,100, 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,17,95,99,111,109,112,105,108,101,95,98,121,116,101,99, - 111,100,101,227,1,0,0,115,16,0,0,0,0,2,15,1, + 111,100,101,228,1,0,0,115,16,0,0,0,0,2,15,1, 15,1,13,1,12,1,16,1,4,2,18,1,114,152,0,0, 0,114,59,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,76,0,0,0, @@ -793,7 +793,7 @@ 0,0,114,138,0,0,0,114,145,0,0,0,114,53,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,17,95,99,111,100,101,95,116,111,95,98,121,116,101,99, - 111,100,101,239,1,0,0,115,10,0,0,0,0,3,12,1, + 111,100,101,240,1,0,0,115,10,0,0,0,0,3,12,1, 19,1,19,1,22,1,114,155,0,0,0,99,1,0,0,0, 0,0,0,0,5,0,0,0,4,0,0,0,67,0,0,0, 115,89,0,0,0,100,1,0,100,2,0,108,0,0,125,1, @@ -821,7 +821,7 @@ 97,100,108,105,110,101,218,8,101,110,99,111,100,105,110,103, 90,15,110,101,119,108,105,110,101,95,100,101,99,111,100,101, 114,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,13,100,101,99,111,100,101,95,115,111,117,114,99,101,249, + 218,13,100,101,99,111,100,101,95,115,111,117,114,99,101,250, 1,0,0,115,10,0,0,0,0,5,12,1,18,1,15,1, 18,1,114,160,0,0,0,218,6,111,114,105,103,105,110,218, 10,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, @@ -852,7 +852,7 @@ 101,83,112,101,99,41,5,114,106,0,0,0,114,127,0,0, 0,114,161,0,0,0,114,162,0,0,0,90,6,115,101,97, 114,99,104,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,131,0,0,0,7,2,0,0,115,28,0,0,0, + 0,0,114,131,0,0,0,8,2,0,0,115,28,0,0,0, 0,2,15,1,12,1,16,1,18,1,15,1,7,2,12,1, 15,1,3,1,19,1,13,1,14,3,6,2,114,131,0,0, 0,114,127,0,0,0,114,164,0,0,0,99,2,0,0,0, @@ -914,7 +914,7 @@ 100,101,114,95,99,108,97,115,115,218,8,115,117,102,102,105, 120,101,115,114,162,0,0,0,90,7,100,105,114,110,97,109, 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,165,0,0,0,32,2,0,0,115,60,0,0,0,0,12, + 114,165,0,0,0,33,2,0,0,115,60,0,0,0,0,12, 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, @@ -954,7 +954,7 @@ 79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,3, 99,108,115,218,3,107,101,121,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, - 101,103,105,115,116,114,121,110,2,0,0,115,8,0,0,0, + 101,103,105,115,116,114,121,111,2,0,0,115,8,0,0,0, 0,2,3,1,23,1,13,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, @@ -981,7 +981,7 @@ 0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,112, 97,116,104,114,4,0,0,0,114,4,0,0,0,114,5,0, 0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,105, - 115,116,114,121,117,2,0,0,115,22,0,0,0,0,2,9, + 115,116,114,121,118,2,0,0,115,22,0,0,0,0,2,9, 1,12,2,9,1,15,1,22,1,3,1,18,1,28,1,13, 1,9,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, @@ -1004,7 +1004,7 @@ 6,116,97,114,103,101,116,114,181,0,0,0,114,127,0,0, 0,114,171,0,0,0,114,133,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,9,102,105,110,100, - 95,115,112,101,99,132,2,0,0,115,24,0,0,0,0,2, + 95,115,112,101,99,133,2,0,0,115,24,0,0,0,0,2, 15,1,12,1,4,1,3,1,14,1,13,1,9,1,22,1, 21,1,21,1,9,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, @@ -1023,7 +1023,7 @@ 2,114,184,0,0,0,114,127,0,0,0,41,4,114,174,0, 0,0,114,126,0,0,0,114,35,0,0,0,114,133,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,11,102,105,110,100,95,109,111,100,117,108,101,147,2,0, + 218,11,102,105,110,100,95,109,111,100,117,108,101,148,2,0, 0,115,8,0,0,0,0,7,18,1,12,1,7,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, @@ -1033,7 +1033,7 @@ 104,111,100,114,176,0,0,0,114,182,0,0,0,114,184,0, 0,0,114,185,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,4,0,0,0,114,5,0,0,0,114,172,0,0,0, - 98,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, + 99,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, 2,6,2,18,7,18,15,3,1,21,14,3,1,114,172,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,64,0,0,0,101,0,0,90, @@ -1070,7 +1070,7 @@ 114,126,0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,162,0,0,0,166,2,0,0,115,8,0,0, + 0,0,0,114,162,0,0,0,167,2,0,0,115,8,0,0, 0,0,3,25,1,22,1,19,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, @@ -1080,7 +1080,7 @@ 111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,78, 114,4,0,0,0,41,2,114,108,0,0,0,114,133,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,174, + 218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,175, 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, @@ -1102,14 +1102,14 @@ 0,0,0,41,3,114,108,0,0,0,114,134,0,0,0,114, 151,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,101, - 177,2,0,0,115,10,0,0,0,0,2,18,1,12,1,9, + 178,2,0,0,115,10,0,0,0,0,2,18,1,12,1,9, 1,15,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,78,41, 9,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, 114,114,0,0,0,114,162,0,0,0,114,189,0,0,0,114, 193,0,0,0,114,135,0,0,0,218,11,108,111,97,100,95, 109,111,100,117,108,101,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,187,0,0,0,161, + 114,4,0,0,0,114,5,0,0,0,114,187,0,0,0,162, 2,0,0,115,10,0,0,0,12,3,6,2,12,8,12,3, 12,8,114,187,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,106,0,0, @@ -1137,1091 +1137,1153 @@ 32,32,32,32,32,78,41,1,218,7,73,79,69,114,114,111, 114,41,2,114,108,0,0,0,114,35,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,218,10,112,97, - 116,104,95,109,116,105,109,101,190,2,0,0,115,2,0,0, + 116,104,95,109,116,105,109,101,191,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,3,0,0,0,67,0,0, - 0,115,20,0,0,0,105,1,0,124,0,0,106,0,0,124, - 1,0,131,1,0,100,1,0,54,83,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,73,79,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,138,0,0,0, - 41,1,114,197,0,0,0,41,2,114,108,0,0,0,114,35, + 0,115,19,0,0,0,124,0,0,106,0,0,124,1,0,131, + 1,0,100,1,0,105,1,0,83,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,73,79,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,138,0,0,0,41, + 1,114,197,0,0,0,41,2,114,108,0,0,0,114,35,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,10,112,97,116,104,95,115,116,97,116,115,199,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,3,0, + 0,0,67,0,0,0,115,16,0,0,0,124,0,0,106,0, + 0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99,97,99, + 104,101,95,112,97,116,104,114,53,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,15,95,99,97, + 99,104,101,95,98,121,116,101,99,111,100,101,212,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,0,83,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,4, + 0,0,0,41,3,114,108,0,0,0,114,35,0,0,0,114, + 53,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,199,0,0,0,222,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,16,0,0,0,67,0,0,0,115,105,0, + 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, + 0,121,19,0,124,0,0,106,1,0,124,2,0,131,1,0, + 125,3,0,87,110,58,0,4,116,2,0,107,10,0,114,94, + 0,1,125,4,0,1,122,26,0,116,3,0,100,1,0,100, + 2,0,124,1,0,131,1,1,124,4,0,130,2,0,87,89, + 100,3,0,100,3,0,125,4,0,126,4,0,88,110,1,0, + 88,116,4,0,124,3,0,131,1,0,83,41,4,122,52,67, + 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,73,110,115,112,101,99, + 116,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, + 99,101,46,122,39,115,111,117,114,99,101,32,110,111,116,32, + 97,118,97,105,108,97,98,108,101,32,116,104,114,111,117,103, + 104,32,103,101,116,95,100,97,116,97,40,41,114,106,0,0, + 0,78,41,5,114,163,0,0,0,218,8,103,101,116,95,100, + 97,116,97,114,40,0,0,0,114,107,0,0,0,114,160,0, + 0,0,41,5,114,108,0,0,0,114,126,0,0,0,114,35, + 0,0,0,114,158,0,0,0,218,3,101,120,99,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,10,103,101, + 116,95,115,111,117,114,99,101,229,2,0,0,115,14,0,0, + 0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105,109, + 105,122,101,114,29,0,0,0,99,3,0,0,0,1,0,0, + 0,4,0,0,0,9,0,0,0,67,0,0,0,115,34,0, + 0,0,116,0,0,106,1,0,116,2,0,124,1,0,124,2, + 0,100,1,0,100,2,0,100,3,0,100,4,0,124,3,0, + 131,4,2,83,41,5,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,192,0,0,0,218, + 12,100,111,110,116,95,105,110,104,101,114,105,116,84,114,68, + 0,0,0,41,3,114,121,0,0,0,114,191,0,0,0,218, + 7,99,111,109,112,105,108,101,41,4,114,108,0,0,0,114, + 53,0,0,0,114,35,0,0,0,114,204,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,14,115, + 111,117,114,99,101,95,116,111,95,99,111,100,101,239,2,0, + 0,115,4,0,0,0,0,5,21,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, + 10,0,0,0,43,0,0,0,67,0,0,0,115,174,1,0, + 0,124,0,0,106,0,0,124,1,0,131,1,0,125,2,0, + 100,1,0,125,3,0,121,16,0,116,1,0,124,2,0,131, + 1,0,125,4,0,87,110,24,0,4,116,2,0,107,10,0, + 114,63,0,1,1,1,100,1,0,125,4,0,89,110,202,0, + 88,121,19,0,124,0,0,106,3,0,124,2,0,131,1,0, + 125,5,0,87,110,18,0,4,116,4,0,107,10,0,114,103, + 0,1,1,1,89,110,162,0,88,116,5,0,124,5,0,100, + 2,0,25,131,1,0,125,3,0,121,19,0,124,0,0,106, + 6,0,124,4,0,131,1,0,125,6,0,87,110,18,0,4, + 116,7,0,107,10,0,114,159,0,1,1,1,89,110,106,0, + 88,121,34,0,116,8,0,124,6,0,100,3,0,124,5,0, + 100,4,0,124,1,0,100,5,0,124,4,0,131,1,3,125, + 7,0,87,110,24,0,4,116,9,0,116,10,0,102,2,0, + 107,10,0,114,220,0,1,1,1,89,110,45,0,88,116,11, + 0,100,6,0,124,4,0,124,2,0,131,3,0,1,116,12, + 0,124,7,0,100,4,0,124,1,0,100,7,0,124,4,0, + 100,8,0,124,2,0,131,1,3,83,124,0,0,106,6,0, + 124,2,0,131,1,0,125,8,0,124,0,0,106,13,0,124, + 8,0,124,2,0,131,2,0,125,9,0,116,11,0,100,9, + 0,124,2,0,131,2,0,1,116,14,0,106,15,0,12,114, + 170,1,124,4,0,100,1,0,107,9,0,114,170,1,124,3, + 0,100,1,0,107,9,0,114,170,1,116,16,0,124,9,0, + 124,3,0,116,17,0,124,8,0,131,1,0,131,3,0,125, + 6,0,121,36,0,124,0,0,106,18,0,124,2,0,124,4, + 0,124,6,0,131,3,0,1,116,11,0,100,10,0,124,4, + 0,131,2,0,1,87,110,18,0,4,116,2,0,107,10,0, + 114,169,1,1,1,1,89,110,1,0,88,124,9,0,83,41, + 11,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,114,138,0,0,0,114,143,0,0,0,114,106,0,0, + 0,114,35,0,0,0,122,13,123,125,32,109,97,116,99,104, + 101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66,0,0, + 0,114,198,0,0,0,114,196,0,0,0,114,14,0,0,0, + 114,201,0,0,0,114,40,0,0,0,114,146,0,0,0,114, + 107,0,0,0,114,141,0,0,0,114,105,0,0,0,114,152, + 0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200,0,0, + 0,41,10,114,108,0,0,0,114,126,0,0,0,114,90,0, + 0,0,114,144,0,0,0,114,89,0,0,0,218,2,115,116, + 114,53,0,0,0,218,10,98,121,116,101,115,95,100,97,116, + 97,114,158,0,0,0,90,11,99,111,100,101,95,111,98,106, + 101,99,116,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,190,0,0,0,247,2,0,0,115,78,0,0,0, + 0,7,15,1,6,1,3,1,16,1,13,1,11,2,3,1, + 19,1,13,1,5,2,16,1,3,1,19,1,13,1,5,2, + 3,1,9,1,12,1,13,1,19,1,5,2,9,1,7,1, + 15,1,6,1,7,1,15,1,18,1,13,1,22,1,12,1, + 9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112,0, + 0,0,114,111,0,0,0,114,113,0,0,0,114,197,0,0, + 0,114,198,0,0,0,114,200,0,0,0,114,199,0,0,0, + 114,203,0,0,0,114,207,0,0,0,114,190,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,195,0,0,0,189,2,0,0,115,14,0,0, + 0,12,2,12,8,12,13,12,10,12,7,12,10,18,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,112,0,0,0,101,0, + 0,90,1,0,100,0,0,90,2,0,100,1,0,90,3,0, + 100,2,0,100,3,0,132,0,0,90,4,0,100,4,0,100, + 5,0,132,0,0,90,5,0,100,6,0,100,7,0,132,0, + 0,90,6,0,101,7,0,135,0,0,102,1,0,100,8,0, + 100,9,0,134,0,0,131,1,0,90,8,0,101,7,0,100, + 10,0,100,11,0,132,0,0,131,1,0,90,9,0,100,12, + 0,100,13,0,132,0,0,90,10,0,135,0,0,83,41,14, + 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,22,0,0,0,124, + 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, + 0,100,1,0,83,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,106,0,0,0,114,35,0,0, + 0,41,3,114,108,0,0,0,114,126,0,0,0,114,35,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,188,0,0,0,48,3,0,0,115,4,0,0,0,0, + 3,9,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,34,0, + 0,0,124,0,0,106,0,0,124,1,0,106,0,0,107,2, + 0,111,33,0,124,0,0,106,1,0,124,1,0,106,1,0, + 107,2,0,83,41,1,78,41,2,218,9,95,95,99,108,97, + 115,115,95,95,114,118,0,0,0,41,2,114,108,0,0,0, + 218,5,111,116,104,101,114,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,6,95,95,101,113,95,95,54,3, + 0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1, + 0,131,1,0,116,0,0,124,0,0,106,2,0,131,1,0, + 65,83,41,1,78,41,3,218,4,104,97,115,104,114,106,0, + 0,0,114,35,0,0,0,41,1,114,108,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,95, + 95,104,97,115,104,95,95,58,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,22,0,0, + 0,116,0,0,116,1,0,124,0,0,131,2,0,106,2,0, + 124,1,0,131,1,0,83,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,211,0,0,0,114,194,0, + 0,0,41,2,114,108,0,0,0,114,126,0,0,0,41,1, + 114,212,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 194,0,0,0,61,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,7,0,0, + 0,124,0,0,106,0,0,83,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, + 108,0,0,0,114,126,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,163,0,0,0,73,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,8,0, + 0,0,67,0,0,0,115,41,0,0,0,116,0,0,106,1, + 0,124,1,0,100,1,0,131,2,0,143,17,0,125,2,0, + 124,2,0,106,2,0,131,0,0,83,87,100,2,0,81,88, + 100,2,0,83,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,49,0,0,0,114,50,0,0,0,90, + 4,114,101,97,100,41,3,114,108,0,0,0,114,35,0,0, + 0,114,54,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,201,0,0,0,78,3,0,0,115,4, + 0,0,0,0,2,21,1,122,19,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,100,97,116,97,41,11,114,112, + 0,0,0,114,111,0,0,0,114,113,0,0,0,114,114,0, + 0,0,114,188,0,0,0,114,214,0,0,0,114,216,0,0, + 0,114,123,0,0,0,114,194,0,0,0,114,163,0,0,0, + 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,41, + 1,114,212,0,0,0,114,5,0,0,0,114,211,0,0,0, + 43,3,0,0,115,14,0,0,0,12,3,6,2,12,6,12, + 4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100,0,0,90, + 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, + 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, + 100,6,0,100,7,0,100,8,0,100,9,0,132,0,1,90, + 6,0,100,10,0,83,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,5,0,0,0,67,0,0,0,115, + 34,0,0,0,116,0,0,124,1,0,131,1,0,125,2,0, + 124,2,0,106,1,0,100,1,0,124,2,0,106,2,0,100, + 2,0,105,2,0,83,41,3,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,114,138,0,0,0, + 114,139,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,108,0,0,0,114,35,0,0,0,114,209,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 198,0,0,0,88,3,0,0,115,4,0,0,0,0,2,12, + 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,34,0,0,0,116,0,0,124,1,0,131,1, + 0,125,4,0,124,0,0,106,1,0,124,2,0,124,3,0, + 100,1,0,124,4,0,131,2,1,83,41,2,78,218,5,95, + 109,111,100,101,41,2,114,97,0,0,0,114,199,0,0,0, + 41,5,114,108,0,0,0,114,90,0,0,0,114,89,0,0, + 0,114,53,0,0,0,114,42,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,200,0,0,0,93, + 3,0,0,115,4,0,0,0,0,2,12,1,122,32,83,111, + 117,114,99,101,70,105,108,101,76,111,97,100,101,114,46,95, + 99,97,99,104,101,95,98,121,116,101,99,111,100,101,114,221, + 0,0,0,105,182,1,0,0,99,3,0,0,0,1,0,0, + 0,9,0,0,0,17,0,0,0,67,0,0,0,115,53,1, + 0,0,116,0,0,124,1,0,131,1,0,92,2,0,125,4, + 0,125,5,0,103,0,0,125,6,0,120,54,0,124,4,0, + 114,80,0,116,1,0,124,4,0,131,1,0,12,114,80,0, + 116,0,0,124,4,0,131,1,0,92,2,0,125,4,0,125, + 7,0,124,6,0,106,2,0,124,7,0,131,1,0,1,113, + 27,0,87,120,132,0,116,3,0,124,6,0,131,1,0,68, + 93,118,0,125,7,0,116,4,0,124,4,0,124,7,0,131, + 2,0,125,4,0,121,17,0,116,5,0,106,6,0,124,4, + 0,131,1,0,1,87,113,94,0,4,116,7,0,107,10,0, + 114,155,0,1,1,1,119,94,0,89,113,94,0,4,116,8, + 0,107,10,0,114,211,0,1,125,8,0,1,122,25,0,116, + 9,0,100,1,0,124,4,0,124,8,0,131,3,0,1,100, + 2,0,83,87,89,100,2,0,100,2,0,125,8,0,126,8, + 0,88,113,94,0,88,113,94,0,87,121,33,0,116,10,0, + 124,1,0,124,2,0,124,3,0,131,3,0,1,116,9,0, + 100,3,0,124,1,0,131,2,0,1,87,110,53,0,4,116, + 8,0,107,10,0,114,48,1,1,125,8,0,1,122,21,0, + 116,9,0,100,1,0,124,1,0,124,8,0,131,3,0,1, + 87,89,100,2,0,100,2,0,125,8,0,126,8,0,88,110, + 1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0,0,114,169, + 0,0,0,114,33,0,0,0,114,28,0,0,0,114,3,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, + 105,0,0,0,114,55,0,0,0,41,9,114,108,0,0,0, + 114,35,0,0,0,114,53,0,0,0,114,221,0,0,0,218, + 6,112,97,114,101,110,116,114,94,0,0,0,114,27,0,0, + 0,114,23,0,0,0,114,202,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,199,0,0,0,98, + 3,0,0,115,38,0,0,0,0,2,18,1,6,2,22,1, + 18,1,17,2,19,1,15,1,3,1,17,1,13,2,7,1, + 18,3,16,1,27,1,3,1,16,1,17,1,18,2,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,112,0,0, + 0,114,111,0,0,0,114,113,0,0,0,114,114,0,0,0, + 114,198,0,0,0,114,200,0,0,0,114,199,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,219,0,0,0,84,3,0,0,115,8,0,0, + 0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,100,2,0,100,3,0, + 132,0,0,90,4,0,100,4,0,100,5,0,132,0,0,90, + 5,0,100,6,0,83,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,6,0,0,0,67,0, + 0,0,115,76,0,0,0,124,0,0,106,0,0,124,1,0, + 131,1,0,125,2,0,124,0,0,106,1,0,124,2,0,131, + 1,0,125,3,0,116,2,0,124,3,0,100,1,0,124,1, + 0,100,2,0,124,2,0,131,1,2,125,4,0,116,3,0, + 124,4,0,100,1,0,124,1,0,100,3,0,124,2,0,131, + 1,2,83,41,4,78,114,106,0,0,0,114,35,0,0,0, + 114,89,0,0,0,41,4,114,163,0,0,0,114,201,0,0, + 0,114,146,0,0,0,114,152,0,0,0,41,5,114,108,0, + 0,0,114,126,0,0,0,114,35,0,0,0,114,53,0,0, + 0,114,210,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,190,0,0,0,131,3,0,0,115,8, + 0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0, + 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,203,0,0,0,137,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,112,0,0,0,114,111,0, + 0,0,114,113,0,0,0,114,114,0,0,0,114,190,0,0, + 0,114,203,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,224,0,0,0,127, + 3,0,0,115,6,0,0,0,12,2,6,2,12,6,114,224, + 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,130,0,0,0,101,0,0, + 90,1,0,100,0,0,90,2,0,100,1,0,90,3,0,100, + 2,0,100,3,0,132,0,0,90,4,0,100,4,0,100,5, + 0,132,0,0,90,5,0,100,6,0,100,7,0,132,0,0, + 90,6,0,101,7,0,100,8,0,100,9,0,132,0,0,131, + 1,0,90,8,0,100,10,0,100,11,0,132,0,0,90,9, + 0,100,12,0,100,13,0,132,0,0,90,10,0,100,14,0, + 100,15,0,132,0,0,90,11,0,101,7,0,100,16,0,100, + 17,0,132,0,0,131,1,0,90,12,0,100,18,0,83,41, + 19,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,22,0,0,0,124, + 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, + 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, + 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, + 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,188,0,0,0,154,3,0,0,115,4,0, + 0,0,0,1,9,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,34,0,0,0,124,0, + 0,106,0,0,124,1,0,106,0,0,107,2,0,111,33,0, + 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, + 41,1,78,41,2,114,212,0,0,0,114,118,0,0,0,41, + 2,114,108,0,0,0,114,213,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,214,0,0,0,158, + 3,0,0,115,4,0,0,0,0,1,18,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,26,0, + 0,0,116,0,0,124,0,0,106,1,0,131,1,0,116,0, + 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, + 3,114,215,0,0,0,114,106,0,0,0,114,35,0,0,0, + 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,216,0,0,0,162,3,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,4,0,0, + 0,11,0,0,0,67,0,0,0,115,183,0,0,0,116,0, + 0,106,1,0,124,1,0,131,1,0,143,32,0,1,116,0, + 0,106,2,0,116,3,0,106,4,0,124,1,0,124,0,0, + 106,5,0,131,3,0,125,2,0,87,100,1,0,81,88,116, + 6,0,100,2,0,124,0,0,106,5,0,131,2,0,1,124, + 0,0,106,7,0,124,1,0,131,1,0,125,3,0,124,3, + 0,114,127,0,116,8,0,124,2,0,100,3,0,131,2,0, + 12,114,127,0,116,9,0,124,0,0,106,5,0,131,1,0, + 100,4,0,25,103,1,0,124,2,0,95,10,0,124,0,0, + 124,2,0,95,11,0,124,2,0,106,12,0,124,2,0,95, + 13,0,124,3,0,115,179,0,124,2,0,106,13,0,106,14, + 0,100,5,0,131,1,0,100,4,0,25,124,2,0,95,13, + 0,124,2,0,83,41,6,122,25,76,111,97,100,32,97,110, + 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,46,78,122,33,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,32,108,111,97,100,101,100,32,102,114,111, + 109,32,123,33,114,125,218,8,95,95,112,97,116,104,95,95, + 114,59,0,0,0,114,58,0,0,0,41,15,114,121,0,0, + 0,90,13,95,77,97,110,97,103,101,82,101,108,111,97,100, + 114,191,0,0,0,114,150,0,0,0,90,12,108,111,97,100, + 95,100,121,110,97,109,105,99,114,35,0,0,0,114,105,0, + 0,0,114,162,0,0,0,114,115,0,0,0,114,38,0,0, + 0,114,226,0,0,0,218,10,95,95,108,111,97,100,101,114, + 95,95,114,112,0,0,0,218,11,95,95,112,97,99,107,97, + 103,101,95,95,114,32,0,0,0,41,4,114,108,0,0,0, + 114,126,0,0,0,114,134,0,0,0,114,162,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,194, + 0,0,0,165,3,0,0,115,24,0,0,0,0,5,16,1, + 12,1,21,1,16,1,15,1,22,1,25,1,9,1,12,1, + 6,1,25,1,122,31,69,120,116,101,110,115,105,111,110,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,4,0,0,0,3,0,0,0,115,48,0,0,0,116, + 0,0,124,0,0,106,1,0,131,1,0,100,1,0,25,137, + 0,0,116,2,0,135,0,0,102,1,0,100,2,0,100,3, + 0,134,0,0,116,3,0,68,131,1,0,131,1,0,83,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,31, + 0,0,0,124,0,0,93,21,0,125,1,0,136,0,0,100, + 0,0,124,1,0,23,107,2,0,86,1,113,3,0,100,1, + 0,83,41,2,114,188,0,0,0,78,114,4,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,4,0,0,0, + 114,5,0,0,0,250,9,60,103,101,110,101,120,112,114,62, + 186,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0,0,0,114, + 4,0,0,0,41,1,114,230,0,0,0,114,5,0,0,0, + 114,162,0,0,0,183,3,0,0,115,6,0,0,0,0,2, + 19,1,18,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, + 0,83,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,4,0,0,0,41,2,114,108,0, + 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,190,0,0,0,189,3,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, + 0,83,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,4,0,0, + 0,41,2,114,108,0,0,0,114,126,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,203,0,0, + 0,193,3,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,7,0,0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,163,0, + 0,0,197,3,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,13,114,112,0,0,0,114,111,0,0,0,114,113,0,0, + 0,114,114,0,0,0,114,188,0,0,0,114,214,0,0,0, + 114,216,0,0,0,114,123,0,0,0,114,194,0,0,0,114, + 162,0,0,0,114,190,0,0,0,114,203,0,0,0,114,163, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,225,0,0,0,146,3,0,0, + 115,18,0,0,0,12,6,6,2,12,4,12,4,12,3,18, + 18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0,100,0,0,90, + 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, + 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, + 100,6,0,100,7,0,132,0,0,90,6,0,100,8,0,100, + 9,0,132,0,0,90,7,0,100,10,0,100,11,0,132,0, + 0,90,8,0,100,12,0,100,13,0,132,0,0,90,9,0, + 100,14,0,100,15,0,132,0,0,90,10,0,100,16,0,100, + 17,0,132,0,0,90,11,0,100,18,0,100,19,0,132,0, + 0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0,0,0,124, + 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, + 0,116,2,0,124,0,0,106,3,0,131,0,0,131,1,0, + 124,0,0,95,4,0,124,3,0,124,0,0,95,5,0,100, + 0,0,83,41,1,78,41,6,218,5,95,110,97,109,101,218, + 5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0,0,0,218, + 11,112,97,116,104,95,102,105,110,100,101,114,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,188,0,0,0, + 210,3,0,0,115,8,0,0,0,0,1,9,1,9,1,21, + 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, + 53,0,0,0,124,0,0,106,0,0,106,1,0,100,1,0, + 131,1,0,92,3,0,125,1,0,125,2,0,125,3,0,124, + 2,0,100,2,0,107,2,0,114,43,0,100,6,0,83,124, + 1,0,100,5,0,102,2,0,83,41,7,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,58,0,0,0, + 114,30,0,0,0,114,7,0,0,0,114,35,0,0,0,114, + 226,0,0,0,41,2,122,3,115,121,115,122,4,112,97,116, + 104,41,2,114,235,0,0,0,114,32,0,0,0,41,4,114, + 108,0,0,0,114,223,0,0,0,218,3,100,111,116,90,2, + 109,101,114,4,0,0,0,114,4,0,0,0,114,5,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,216,3,0,0,115,8, + 0,0,0,0,2,27,1,12,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,38,0,0,0,124,0,0, + 106,0,0,131,0,0,92,2,0,125,1,0,125,2,0,116, + 1,0,116,2,0,106,3,0,124,1,0,25,124,2,0,131, + 2,0,83,41,1,78,41,4,114,242,0,0,0,114,117,0, + 0,0,114,7,0,0,0,114,132,0,0,0,41,3,114,108, + 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,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,237,0,0,0,226,3,0,0,115, + 4,0,0,0,0,1,18,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,3,0,0,0,67,0,0,0,115,118, + 0,0,0,116,0,0,124,0,0,106,1,0,131,0,0,131, + 1,0,125,1,0,124,1,0,124,0,0,106,2,0,107,3, + 0,114,111,0,124,0,0,106,3,0,124,0,0,106,4,0, + 124,1,0,131,2,0,125,2,0,124,2,0,100,0,0,107, + 9,0,114,102,0,124,2,0,106,5,0,100,0,0,107,8, + 0,114,102,0,124,2,0,106,6,0,114,102,0,124,2,0, + 106,6,0,124,0,0,95,7,0,124,1,0,124,0,0,95, + 2,0,124,0,0,106,7,0,83,41,1,78,41,8,114,93, + 0,0,0,114,237,0,0,0,114,238,0,0,0,114,239,0, + 0,0,114,235,0,0,0,114,127,0,0,0,114,164,0,0, + 0,114,236,0,0,0,41,3,114,108,0,0,0,90,11,112, + 97,114,101,110,116,95,112,97,116,104,114,133,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, + 95,114,101,99,97,108,99,117,108,97,116,101,230,3,0,0, + 115,16,0,0,0,0,2,18,1,15,1,21,3,27,1,9, + 1,12,1,9,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,2, + 0,0,0,67,0,0,0,115,16,0,0,0,116,0,0,124, + 0,0,106,1,0,131,0,0,131,1,0,83,41,1,78,41, + 2,218,4,105,116,101,114,114,243,0,0,0,41,1,114,108, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,10,112,97,116,104,95,115,116,97,116,115,198,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,3, - 0,0,0,67,0,0,0,115,16,0,0,0,124,0,0,106, - 0,0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99,97, - 99,104,101,95,112,97,116,104,114,53,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,15,95,99, - 97,99,104,101,95,98,121,116,101,99,111,100,101,211,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,0,83,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, - 4,0,0,0,41,3,114,108,0,0,0,114,35,0,0,0, - 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,199,0,0,0,221,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,16,0,0,0,67,0,0,0,115,105, - 0,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, - 2,0,121,19,0,124,0,0,106,1,0,124,2,0,131,1, - 0,125,3,0,87,110,58,0,4,116,2,0,107,10,0,114, - 94,0,1,125,4,0,1,122,26,0,116,3,0,100,1,0, - 100,2,0,124,1,0,131,1,1,124,4,0,130,2,0,87, - 89,100,3,0,100,3,0,125,4,0,126,4,0,88,110,1, - 0,88,116,4,0,124,3,0,131,1,0,83,41,4,122,52, - 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, - 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, - 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, - 103,104,32,103,101,116,95,100,97,116,97,40,41,114,106,0, - 0,0,78,41,5,114,163,0,0,0,218,8,103,101,116,95, - 100,97,116,97,114,40,0,0,0,114,107,0,0,0,114,160, - 0,0,0,41,5,114,108,0,0,0,114,126,0,0,0,114, - 35,0,0,0,114,158,0,0,0,218,3,101,120,99,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,103, - 101,116,95,115,111,117,114,99,101,228,2,0,0,115,14,0, - 0,0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105, - 109,105,122,101,114,29,0,0,0,99,3,0,0,0,1,0, - 0,0,4,0,0,0,9,0,0,0,67,0,0,0,115,34, - 0,0,0,116,0,0,106,1,0,116,2,0,124,1,0,124, - 2,0,100,1,0,100,2,0,100,3,0,100,4,0,124,3, - 0,131,4,2,83,41,5,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,192,0,0,0, - 218,12,100,111,110,116,95,105,110,104,101,114,105,116,84,114, - 68,0,0,0,41,3,114,121,0,0,0,114,191,0,0,0, - 218,7,99,111,109,112,105,108,101,41,4,114,108,0,0,0, - 114,53,0,0,0,114,35,0,0,0,114,204,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,14, - 115,111,117,114,99,101,95,116,111,95,99,111,100,101,238,2, - 0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174,1, - 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, - 0,100,1,0,125,3,0,121,16,0,116,1,0,124,2,0, - 131,1,0,125,4,0,87,110,24,0,4,116,2,0,107,10, - 0,114,63,0,1,1,1,100,1,0,125,4,0,89,110,202, - 0,88,121,19,0,124,0,0,106,3,0,124,2,0,131,1, - 0,125,5,0,87,110,18,0,4,116,4,0,107,10,0,114, - 103,0,1,1,1,89,110,162,0,88,116,5,0,124,5,0, - 100,2,0,25,131,1,0,125,3,0,121,19,0,124,0,0, - 106,6,0,124,4,0,131,1,0,125,6,0,87,110,18,0, - 4,116,7,0,107,10,0,114,159,0,1,1,1,89,110,106, - 0,88,121,34,0,116,8,0,124,6,0,100,3,0,124,5, - 0,100,4,0,124,1,0,100,5,0,124,4,0,131,1,3, - 125,7,0,87,110,24,0,4,116,9,0,116,10,0,102,2, - 0,107,10,0,114,220,0,1,1,1,89,110,45,0,88,116, - 11,0,100,6,0,124,4,0,124,2,0,131,3,0,1,116, - 12,0,124,7,0,100,4,0,124,1,0,100,7,0,124,4, - 0,100,8,0,124,2,0,131,1,3,83,124,0,0,106,6, - 0,124,2,0,131,1,0,125,8,0,124,0,0,106,13,0, - 124,8,0,124,2,0,131,2,0,125,9,0,116,11,0,100, - 9,0,124,2,0,131,2,0,1,116,14,0,106,15,0,12, - 114,170,1,124,4,0,100,1,0,107,9,0,114,170,1,124, - 3,0,100,1,0,107,9,0,114,170,1,116,16,0,124,9, - 0,124,3,0,116,17,0,124,8,0,131,1,0,131,3,0, - 125,6,0,121,36,0,124,0,0,106,18,0,124,2,0,124, - 4,0,124,6,0,131,3,0,1,116,11,0,100,10,0,124, - 4,0,131,2,0,1,87,110,18,0,4,116,2,0,107,10, - 0,114,169,1,1,1,1,89,110,1,0,88,124,9,0,83, - 41,11,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,114,138,0,0,0,114,143,0,0,0,114,106,0, - 0,0,114,35,0,0,0,122,13,123,125,32,109,97,116,99, - 104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66,0, - 0,0,114,198,0,0,0,114,196,0,0,0,114,14,0,0, - 0,114,201,0,0,0,114,40,0,0,0,114,146,0,0,0, - 114,107,0,0,0,114,141,0,0,0,114,105,0,0,0,114, - 152,0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200,0, - 0,0,41,10,114,108,0,0,0,114,126,0,0,0,114,90, - 0,0,0,114,144,0,0,0,114,89,0,0,0,218,2,115, - 116,114,53,0,0,0,218,10,98,121,116,101,115,95,100,97, - 116,97,114,158,0,0,0,90,11,99,111,100,101,95,111,98, - 106,101,99,116,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,190,0,0,0,246,2,0,0,115,78,0,0, - 0,0,7,15,1,6,1,3,1,16,1,13,1,11,2,3, - 1,19,1,13,1,5,2,16,1,3,1,19,1,13,1,5, - 2,3,1,9,1,12,1,13,1,19,1,5,2,9,1,7, - 1,15,1,6,1,7,1,15,1,18,1,13,1,22,1,12, - 1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112, - 0,0,0,114,111,0,0,0,114,113,0,0,0,114,197,0, - 0,0,114,198,0,0,0,114,200,0,0,0,114,199,0,0, - 0,114,203,0,0,0,114,207,0,0,0,114,190,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,195,0,0,0,188,2,0,0,115,14,0, - 0,0,12,2,12,8,12,13,12,10,12,7,12,10,18,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,112,0,0,0,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, - 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, - 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, - 0,0,90,6,0,101,7,0,135,0,0,102,1,0,100,8, - 0,100,9,0,134,0,0,131,1,0,90,8,0,101,7,0, - 100,10,0,100,11,0,132,0,0,131,1,0,90,9,0,100, - 12,0,100,13,0,132,0,0,90,10,0,135,0,0,83,41, - 14,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,22,0,0,0, - 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, - 1,0,100,1,0,83,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,106,0,0,0,114,35,0, - 0,0,41,3,114,108,0,0,0,114,126,0,0,0,114,35, + 0,0,218,8,95,95,105,116,101,114,95,95,243,3,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,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0, + 0,67,0,0,0,115,16,0,0,0,116,0,0,124,0,0, + 106,1,0,131,0,0,131,1,0,83,41,1,78,41,2,114, + 31,0,0,0,114,243,0,0,0,41,1,114,108,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 7,95,95,108,101,110,95,95,246,3,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,2,0,0,0,67,0,0,0, + 115,16,0,0,0,100,1,0,106,0,0,124,0,0,106,1, + 0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1,114,108,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,8,95,95,114,101,112,114,95,95,249,3,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,2,0,0,0,67, + 0,0,0,115,16,0,0,0,124,1,0,124,0,0,106,0, + 0,131,0,0,107,6,0,83,41,1,78,41,1,114,243,0, + 0,0,41,2,114,108,0,0,0,218,4,105,116,101,109,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, + 95,95,99,111,110,116,97,105,110,115,95,95,252,3,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,2,0,0,0,67,0,0,0,115,20,0,0,0,124,0, + 0,106,0,0,106,1,0,124,1,0,131,1,0,1,100,0, + 0,83,41,1,78,41,2,114,236,0,0,0,114,169,0,0, + 0,41,2,114,108,0,0,0,114,248,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,169,0,0, + 0,255,3,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,13,114,112,0,0,0,114,111,0,0,0, + 114,113,0,0,0,114,114,0,0,0,114,188,0,0,0,114, + 242,0,0,0,114,237,0,0,0,114,243,0,0,0,114,245, + 0,0,0,114,246,0,0,0,114,247,0,0,0,114,249,0, + 0,0,114,169,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,234,0,0,0, + 203,3,0,0,115,20,0,0,0,12,5,6,2,12,6,12, + 10,12,4,12,13,12,3,12,3,12,3,12,3,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,118,0,0,0,101,0,0,90, + 1,0,100,0,0,90,2,0,100,1,0,100,2,0,132,0, + 0,90,3,0,101,4,0,100,3,0,100,4,0,132,0,0, + 131,1,0,90,5,0,100,5,0,100,6,0,132,0,0,90, + 6,0,100,7,0,100,8,0,132,0,0,90,7,0,100,9, + 0,100,10,0,132,0,0,90,8,0,100,11,0,100,12,0, + 132,0,0,90,9,0,100,13,0,100,14,0,132,0,0,90, + 10,0,100,15,0,100,16,0,132,0,0,90,11,0,100,17, + 0,83,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,25,0,0,0, + 116,0,0,124,1,0,124,2,0,124,3,0,131,3,0,124, + 0,0,95,1,0,100,0,0,83,41,1,78,41,2,114,234, + 0,0,0,114,236,0,0,0,41,4,114,108,0,0,0,114, + 106,0,0,0,114,35,0,0,0,114,240,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,188,0, + 0,0,5,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,2,0,0,0,67,0,0,0,115,16,0, + 0,0,100,1,0,106,0,0,124,1,0,106,1,0,131,1, + 0,83,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,47,0,0,0,114,112,0,0,0, + 41,2,114,174,0,0,0,114,134,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,11,109,111,100, + 117,108,101,95,114,101,112,114,8,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,0,83,41, + 2,78,84,114,4,0,0,0,41,2,114,108,0,0,0,114, + 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,162,0,0,0,17,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,0,83,41,2, + 78,114,30,0,0,0,114,4,0,0,0,41,2,114,108,0, + 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,203,0,0,0,20,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,22,0,0,0,116,0,0, + 100,1,0,100,2,0,100,3,0,100,4,0,100,5,0,131, + 3,1,83,41,6,78,114,30,0,0,0,122,8,60,115,116, + 114,105,110,103,62,114,192,0,0,0,114,205,0,0,0,84, + 41,1,114,206,0,0,0,41,2,114,108,0,0,0,114,126, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,188,0,0,0,47,3,0,0,115,4,0,0,0, - 0,3,9,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,34, - 0,0,0,124,0,0,106,0,0,124,1,0,106,0,0,107, - 2,0,111,33,0,124,0,0,106,1,0,124,1,0,106,1, - 0,107,2,0,83,41,1,78,41,2,218,9,95,95,99,108, - 97,115,115,95,95,114,118,0,0,0,41,2,114,108,0,0, - 0,218,5,111,116,104,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,6,95,95,101,113,95,95,53, - 3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106, - 1,0,131,1,0,116,0,0,124,0,0,106,2,0,131,1, - 0,65,83,41,1,78,41,3,218,4,104,97,115,104,114,106, - 0,0,0,114,35,0,0,0,41,1,114,108,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,8, - 95,95,104,97,115,104,95,95,57,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,22,0, - 0,0,116,0,0,116,1,0,124,0,0,131,2,0,106,2, - 0,124,1,0,131,1,0,83,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,211,0,0,0,114,194, - 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,41, - 1,114,212,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,194,0,0,0,60,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,7,0, - 0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,163,0,0,0,72,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,8, - 0,0,0,67,0,0,0,115,41,0,0,0,116,0,0,106, - 1,0,124,1,0,100,1,0,131,2,0,143,17,0,125,2, - 0,124,2,0,106,2,0,131,0,0,83,87,100,2,0,81, - 88,100,2,0,83,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,49,0,0,0,114,50,0,0,0, - 90,4,114,101,97,100,41,3,114,108,0,0,0,114,35,0, - 0,0,114,54,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,201,0,0,0,77,3,0,0,115, - 4,0,0,0,0,2,21,1,122,19,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,100,97,116,97,41,11,114, - 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, - 0,0,0,114,188,0,0,0,114,214,0,0,0,114,216,0, - 0,0,114,123,0,0,0,114,194,0,0,0,114,163,0,0, - 0,114,201,0,0,0,114,4,0,0,0,114,4,0,0,0, - 41,1,114,212,0,0,0,114,5,0,0,0,114,211,0,0, - 0,42,3,0,0,115,14,0,0,0,12,3,6,2,12,6, - 12,4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100,0,0, - 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, - 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, - 0,100,6,0,100,7,0,100,8,0,100,9,0,132,0,1, - 90,6,0,100,10,0,83,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,36,0,0,0,116,0,0,124,1,0,131,1,0,125,2, - 0,105,2,0,124,2,0,106,1,0,100,1,0,54,124,2, - 0,106,2,0,100,2,0,54,83,41,3,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,114,138, - 0,0,0,114,139,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,108,0,0,0,114,35,0,0,0,114,209, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,198,0,0,0,87,3,0,0,115,4,0,0,0, - 0,2,12,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,34,0,0,0,116,0,0,124,1, - 0,131,1,0,125,4,0,124,0,0,106,1,0,124,2,0, - 124,3,0,100,1,0,124,4,0,131,2,1,83,41,2,78, - 218,5,95,109,111,100,101,41,2,114,97,0,0,0,114,199, - 0,0,0,41,5,114,108,0,0,0,114,90,0,0,0,114, - 89,0,0,0,114,53,0,0,0,114,42,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,200,0, - 0,0,92,3,0,0,115,4,0,0,0,0,2,12,1,122, - 32,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, - 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, - 101,114,221,0,0,0,105,182,1,0,0,99,3,0,0,0, - 1,0,0,0,9,0,0,0,17,0,0,0,67,0,0,0, - 115,53,1,0,0,116,0,0,124,1,0,131,1,0,92,2, - 0,125,4,0,125,5,0,103,0,0,125,6,0,120,54,0, - 124,4,0,114,80,0,116,1,0,124,4,0,131,1,0,12, - 114,80,0,116,0,0,124,4,0,131,1,0,92,2,0,125, - 4,0,125,7,0,124,6,0,106,2,0,124,7,0,131,1, - 0,1,113,27,0,87,120,132,0,116,3,0,124,6,0,131, - 1,0,68,93,118,0,125,7,0,116,4,0,124,4,0,124, - 7,0,131,2,0,125,4,0,121,17,0,116,5,0,106,6, - 0,124,4,0,131,1,0,1,87,113,94,0,4,116,7,0, - 107,10,0,114,155,0,1,1,1,119,94,0,89,113,94,0, - 4,116,8,0,107,10,0,114,211,0,1,125,8,0,1,122, - 25,0,116,9,0,100,1,0,124,4,0,124,8,0,131,3, - 0,1,100,2,0,83,87,89,100,2,0,100,2,0,125,8, - 0,126,8,0,88,113,94,0,88,113,94,0,87,121,33,0, - 116,10,0,124,1,0,124,2,0,124,3,0,131,3,0,1, - 116,9,0,100,3,0,124,1,0,131,2,0,1,87,110,53, - 0,4,116,8,0,107,10,0,114,48,1,1,125,8,0,1, - 122,21,0,116,9,0,100,1,0,124,1,0,124,8,0,131, - 3,0,1,87,89,100,2,0,100,2,0,125,8,0,126,8, - 0,88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0, - 0,114,169,0,0,0,114,33,0,0,0,114,28,0,0,0, - 114,3,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,105,0,0,0,114,55,0,0,0,41,9,114,108, - 0,0,0,114,35,0,0,0,114,53,0,0,0,114,221,0, - 0,0,218,6,112,97,114,101,110,116,114,94,0,0,0,114, - 27,0,0,0,114,23,0,0,0,114,202,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,199,0, - 0,0,97,3,0,0,115,38,0,0,0,0,2,18,1,6, - 2,22,1,18,1,17,2,19,1,15,1,3,1,17,1,13, - 2,7,1,18,3,16,1,27,1,3,1,16,1,17,1,18, - 2,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, - 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, - 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,219,0,0,0,83,3,0,0,115, - 8,0,0,0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1, - 0,100,0,0,90,2,0,100,1,0,90,3,0,100,2,0, - 100,3,0,132,0,0,90,4,0,100,4,0,100,5,0,132, - 0,0,90,5,0,100,6,0,83,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,6,0,0, - 0,67,0,0,0,115,76,0,0,0,124,0,0,106,0,0, - 124,1,0,131,1,0,125,2,0,124,0,0,106,1,0,124, - 2,0,131,1,0,125,3,0,116,2,0,124,3,0,100,1, - 0,124,1,0,100,2,0,124,2,0,131,1,2,125,4,0, - 116,3,0,124,4,0,100,1,0,124,1,0,100,3,0,124, - 2,0,131,1,2,83,41,4,78,114,106,0,0,0,114,35, - 0,0,0,114,89,0,0,0,41,4,114,163,0,0,0,114, - 201,0,0,0,114,146,0,0,0,114,152,0,0,0,41,5, - 114,108,0,0,0,114,126,0,0,0,114,35,0,0,0,114, - 53,0,0,0,114,210,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,190,0,0,0,130,3,0, - 0,115,8,0,0,0,0,1,15,1,15,1,24,1,122,29, - 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, + 0,0,114,190,0,0,0,23,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,0,83,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,4,0,0,0,41,2,114,108, - 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,203,0,0,0,136,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,112,0,0,0, - 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, - 190,0,0,0,114,203,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,224,0, - 0,0,126,3,0,0,115,6,0,0,0,12,2,6,2,12, - 6,114,224,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,130,0,0,0, + 0,0,115,4,0,0,0,100,1,0,83,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,4,0,0,0,41, + 2,114,108,0,0,0,114,133,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,189,0,0,0,26, + 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,0,83,41,1,78,114,4,0,0,0,41,2, + 114,108,0,0,0,114,134,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,193,0,0,0,29,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,3,0,0,0,67,0,0,0,115,29,0,0, + 0,116,0,0,100,1,0,124,0,0,106,1,0,131,2,0, + 1,116,2,0,124,0,0,124,1,0,131,2,0,83,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,3,114,105, + 0,0,0,114,236,0,0,0,114,135,0,0,0,41,2,114, + 108,0,0,0,114,126,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,194,0,0,0,32,4,0, + 0,115,4,0,0,0,0,7,16,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,112,0,0,0, + 114,111,0,0,0,114,113,0,0,0,114,188,0,0,0,114, + 186,0,0,0,114,251,0,0,0,114,162,0,0,0,114,203, + 0,0,0,114,190,0,0,0,114,189,0,0,0,114,193,0, + 0,0,114,194,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,250,0,0,0, + 4,4,0,0,115,16,0,0,0,12,1,12,3,18,9,12, + 3,12,3,12,3,12,3,12,3,114,250,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,64, + 0,0,0,115,160,0,0,0,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,101,4,0,100,2,0, + 100,3,0,132,0,0,131,1,0,90,5,0,101,4,0,100, + 4,0,100,5,0,132,0,0,131,1,0,90,6,0,101,4, + 0,100,6,0,100,7,0,132,0,0,131,1,0,90,7,0, + 101,4,0,100,8,0,100,9,0,132,0,0,131,1,0,90, + 8,0,101,4,0,100,10,0,100,11,0,100,12,0,132,1, + 0,131,1,0,90,9,0,101,4,0,100,10,0,100,10,0, + 100,13,0,100,14,0,132,2,0,131,1,0,90,10,0,101, + 4,0,100,10,0,100,15,0,100,16,0,132,1,0,131,1, + 0,90,11,0,100,10,0,83,41,17,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,55,0,0,0, + 120,48,0,116,0,0,106,1,0,106,2,0,131,0,0,68, + 93,31,0,125,1,0,116,3,0,124,1,0,100,1,0,131, + 2,0,114,16,0,124,1,0,106,4,0,131,0,0,1,113, + 16,0,87,100,2,0,83,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,7, + 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,115,0,0,0,114,253,0,0,0,41,2,114,174,0,0, + 0,218,6,102,105,110,100,101,114,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,253,0,0,0,49,4,0, + 0,115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67,0,0,0,115, + 107,0,0,0,116,0,0,106,1,0,100,1,0,107,9,0, + 114,41,0,116,0,0,106,1,0,12,114,41,0,116,2,0, + 106,3,0,100,2,0,116,4,0,131,2,0,1,120,59,0, + 116,0,0,106,1,0,68,93,44,0,125,2,0,121,14,0, + 124,2,0,124,1,0,131,1,0,83,87,113,51,0,4,116, + 5,0,107,10,0,114,94,0,1,1,1,119,51,0,89,113, + 51,0,88,113,51,0,87,100,1,0,83,100,1,0,83,41, + 3,122,113,83,101,97,114,99,104,32,115,101,113,117,101,110, + 99,101,32,111,102,32,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,10,10,32,32,32,32,32,32,32,32,73,102, + 32,39,104,111,111,107,115,39,32,105,115,32,102,97,108,115, + 101,32,116,104,101,110,32,117,115,101,32,115,121,115,46,112, + 97,116,104,95,104,111,111,107,115,46,10,10,32,32,32,32, + 32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95,104,111,111,107, + 115,114,60,0,0,0,114,61,0,0,0,114,125,0,0,0, + 114,107,0,0,0,41,3,114,174,0,0,0,114,35,0,0, + 0,90,4,104,111,111,107,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,11,95,112,97,116,104,95,104,111, + 111,107,115,57,4,0,0,115,16,0,0,0,0,7,25,1, + 16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0,0,0,124,1, + 0,100,1,0,107,2,0,114,53,0,121,16,0,116,0,0, + 106,1,0,131,0,0,125,1,0,87,110,22,0,4,116,2, + 0,107,10,0,114,52,0,1,1,1,100,2,0,83,89,110, + 1,0,88,121,17,0,116,3,0,106,4,0,124,1,0,25, + 125,2,0,87,110,46,0,4,116,5,0,107,10,0,114,118, + 0,1,1,1,124,0,0,106,6,0,124,1,0,131,1,0, + 125,2,0,124,2,0,116,3,0,106,4,0,124,1,0,60, + 89,110,1,0,88,124,2,0,83,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,3,0,0,0,114,45,0,0, + 0,218,17,70,105,108,101,78,111,116,70,111,117,110,100,69, + 114,114,111,114,114,7,0,0,0,114,254,0,0,0,114,142, + 0,0,0,114,2,1,0,0,41,3,114,174,0,0,0,114, + 35,0,0,0,114,0,1,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,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,74,4, + 0,0,115,22,0,0,0,0,8,12,1,3,1,16,1,13, + 3,9,1,3,1,17,1,13,1,15,1,18,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,3,0,0,0,67, + 0,0,0,115,116,0,0,0,116,0,0,124,2,0,100,1, + 0,131,2,0,114,39,0,124,2,0,106,1,0,124,1,0, + 131,1,0,92,2,0,125,3,0,125,4,0,110,21,0,124, + 2,0,106,2,0,124,1,0,131,1,0,125,3,0,103,0, + 0,125,4,0,124,3,0,100,0,0,107,9,0,114,85,0, + 116,3,0,124,1,0,124,3,0,131,2,0,83,116,4,0, + 106,5,0,124,1,0,100,0,0,131,2,0,125,5,0,124, + 4,0,124,5,0,95,6,0,124,5,0,83,41,2,78,114, + 124,0,0,0,41,7,114,115,0,0,0,114,124,0,0,0, + 114,185,0,0,0,114,131,0,0,0,114,121,0,0,0,114, + 166,0,0,0,114,164,0,0,0,41,6,114,174,0,0,0, + 114,126,0,0,0,114,0,1,0,0,114,127,0,0,0,114, + 128,0,0,0,114,133,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,16,95,108,101,103,97,99, + 121,95,103,101,116,95,115,112,101,99,96,4,0,0,115,18, + 0,0,0,0,4,15,1,24,2,15,1,6,1,12,1,13, + 1,18,1,9,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,243,0,0,0,103,0,0, + 125,4,0,120,230,0,124,2,0,68,93,191,0,125,5,0, + 116,0,0,124,5,0,116,1,0,116,2,0,102,2,0,131, + 2,0,115,43,0,113,13,0,124,0,0,106,3,0,124,5, + 0,131,1,0,125,6,0,124,6,0,100,1,0,107,9,0, + 114,13,0,116,4,0,124,6,0,100,2,0,131,2,0,114, + 106,0,124,6,0,106,5,0,124,1,0,124,3,0,131,2, + 0,125,7,0,110,18,0,124,0,0,106,6,0,124,1,0, + 124,6,0,131,2,0,125,7,0,124,7,0,100,1,0,107, + 8,0,114,139,0,113,13,0,124,7,0,106,7,0,100,1, + 0,107,9,0,114,158,0,124,7,0,83,124,7,0,106,8, + 0,125,8,0,124,8,0,100,1,0,107,8,0,114,191,0, + 116,9,0,100,3,0,131,1,0,130,1,0,124,4,0,106, + 10,0,124,8,0,131,1,0,1,113,13,0,87,116,11,0, + 106,12,0,124,1,0,100,1,0,131,2,0,125,7,0,124, + 4,0,124,7,0,95,8,0,124,7,0,83,100,1,0,83, + 41,4,122,63,70,105,110,100,32,116,104,101,32,108,111,97, + 100,101,114,32,111,114,32,110,97,109,101,115,112,97,99,101, + 95,112,97,116,104,32,102,111,114,32,116,104,105,115,32,109, + 111,100,117,108,101,47,112,97,99,107,97,103,101,32,110,97, + 109,101,46,78,114,184,0,0,0,122,19,115,112,101,99,32, + 109,105,115,115,105,110,103,32,108,111,97,100,101,114,41,13, + 114,148,0,0,0,114,69,0,0,0,218,5,98,121,116,101, + 115,114,4,1,0,0,114,115,0,0,0,114,184,0,0,0, + 114,5,1,0,0,114,127,0,0,0,114,164,0,0,0,114, + 107,0,0,0,114,154,0,0,0,114,121,0,0,0,114,166, + 0,0,0,41,9,114,174,0,0,0,114,126,0,0,0,114, + 35,0,0,0,114,183,0,0,0,218,14,110,97,109,101,115, + 112,97,99,101,95,112,97,116,104,90,5,101,110,116,114,121, + 114,0,1,0,0,114,133,0,0,0,114,128,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,9, + 95,103,101,116,95,115,112,101,99,111,4,0,0,115,40,0, + 0,0,0,5,6,1,13,1,21,1,3,1,15,1,12,1, + 15,1,21,2,18,1,12,1,3,1,15,1,4,1,9,1, + 12,1,12,5,17,2,18,1,9,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,4,0,0, + 0,67,0,0,0,115,140,0,0,0,124,2,0,100,1,0, + 107,8,0,114,21,0,116,0,0,106,1,0,125,2,0,124, + 0,0,106,2,0,124,1,0,124,2,0,124,3,0,131,3, + 0,125,4,0,124,4,0,100,1,0,107,8,0,114,58,0, + 100,1,0,83,124,4,0,106,3,0,100,1,0,107,8,0, + 114,132,0,124,4,0,106,4,0,125,5,0,124,5,0,114, + 125,0,100,2,0,124,4,0,95,5,0,116,6,0,124,1, + 0,124,5,0,124,0,0,106,2,0,131,3,0,124,4,0, + 95,4,0,124,4,0,83,100,1,0,83,110,4,0,124,4, + 0,83,100,1,0,83,41,3,122,98,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,78,90,9,110, + 97,109,101,115,112,97,99,101,41,7,114,7,0,0,0,114, + 35,0,0,0,114,8,1,0,0,114,127,0,0,0,114,164, + 0,0,0,114,161,0,0,0,114,234,0,0,0,41,6,114, + 174,0,0,0,114,126,0,0,0,114,35,0,0,0,114,183, + 0,0,0,114,133,0,0,0,114,7,1,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,184,0,0, + 0,143,4,0,0,115,26,0,0,0,0,4,12,1,9,1, + 21,1,12,1,4,1,15,1,9,1,6,3,9,1,24,1, + 4,2,7,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, + 41,0,0,0,124,0,0,106,0,0,124,1,0,124,2,0, + 131,2,0,125,3,0,124,3,0,100,1,0,107,8,0,114, + 34,0,100,1,0,83,124,3,0,106,1,0,83,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,184, + 0,0,0,114,127,0,0,0,41,4,114,174,0,0,0,114, + 126,0,0,0,114,35,0,0,0,114,133,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,185,0, + 0,0,165,4,0,0,115,8,0,0,0,0,8,18,1,12, + 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,12,114,112,0, + 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, + 0,114,186,0,0,0,114,253,0,0,0,114,2,1,0,0, + 114,4,1,0,0,114,5,1,0,0,114,8,1,0,0,114, + 184,0,0,0,114,185,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,252,0, + 0,0,45,4,0,0,115,22,0,0,0,12,2,6,2,18, + 8,18,17,18,22,18,15,3,1,18,31,3,1,21,21,3, + 1,114,252,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,133,0,0,0, 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, - 132,0,0,90,6,0,101,7,0,100,8,0,100,9,0,132, - 0,0,131,1,0,90,8,0,100,10,0,100,11,0,132,0, - 0,90,9,0,100,12,0,100,13,0,132,0,0,90,10,0, - 100,14,0,100,15,0,132,0,0,90,11,0,101,7,0,100, - 16,0,100,17,0,132,0,0,131,1,0,90,12,0,100,18, - 0,83,41,19,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,22,0, - 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, - 0,95,1,0,100,0,0,83,41,1,78,41,2,114,106,0, - 0,0,114,35,0,0,0,41,3,114,108,0,0,0,114,106, - 0,0,0,114,35,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,188,0,0,0,153,3,0,0, - 115,4,0,0,0,0,1,9,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,34,0,0, - 0,124,0,0,106,0,0,124,1,0,106,0,0,107,2,0, - 111,33,0,124,0,0,106,1,0,124,1,0,106,1,0,107, - 2,0,83,41,1,78,41,2,114,212,0,0,0,114,118,0, - 0,0,41,2,114,108,0,0,0,114,213,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,214,0, - 0,0,157,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1,0,131,1, - 0,116,0,0,124,0,0,106,2,0,131,1,0,65,83,41, - 1,78,41,3,114,215,0,0,0,114,106,0,0,0,114,35, - 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,216,0,0,0,161,3, - 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, - 4,0,0,0,11,0,0,0,67,0,0,0,115,183,0,0, - 0,116,0,0,106,1,0,124,1,0,131,1,0,143,32,0, - 1,116,0,0,106,2,0,116,3,0,106,4,0,124,1,0, - 124,0,0,106,5,0,131,3,0,125,2,0,87,100,1,0, - 81,88,116,6,0,100,2,0,124,0,0,106,5,0,131,2, - 0,1,124,0,0,106,7,0,124,1,0,131,1,0,125,3, - 0,124,3,0,114,127,0,116,8,0,124,2,0,100,3,0, - 131,2,0,12,114,127,0,116,9,0,124,0,0,106,5,0, - 131,1,0,100,4,0,25,103,1,0,124,2,0,95,10,0, - 124,0,0,124,2,0,95,11,0,124,2,0,106,12,0,124, - 2,0,95,13,0,124,3,0,115,179,0,124,2,0,106,13, - 0,106,14,0,100,5,0,131,1,0,100,4,0,25,124,2, - 0,95,13,0,124,2,0,83,41,6,122,25,76,111,97,100, - 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,46,78,122,33,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,32,108,111,97,100,101,100,32, - 102,114,111,109,32,123,33,114,125,218,8,95,95,112,97,116, - 104,95,95,114,59,0,0,0,114,58,0,0,0,41,15,114, - 121,0,0,0,90,13,95,77,97,110,97,103,101,82,101,108, - 111,97,100,114,191,0,0,0,114,150,0,0,0,90,12,108, - 111,97,100,95,100,121,110,97,109,105,99,114,35,0,0,0, - 114,105,0,0,0,114,162,0,0,0,114,115,0,0,0,114, - 38,0,0,0,114,226,0,0,0,218,10,95,95,108,111,97, - 100,101,114,95,95,114,112,0,0,0,218,11,95,95,112,97, - 99,107,97,103,101,95,95,114,32,0,0,0,41,4,114,108, - 0,0,0,114,126,0,0,0,114,134,0,0,0,114,162,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,194,0,0,0,164,3,0,0,115,24,0,0,0,0, - 5,16,1,12,1,21,1,16,1,15,1,22,1,25,1,9, - 1,12,1,6,1,25,1,122,31,69,120,116,101,110,115,105, - 111,110,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,4,0,0,0,3,0,0,0,115,48,0, - 0,0,116,0,0,124,0,0,106,1,0,131,1,0,100,1, - 0,25,137,0,0,116,2,0,135,0,0,102,1,0,100,2, - 0,100,3,0,134,0,0,116,3,0,68,131,1,0,131,1, - 0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0,136, - 0,0,100,0,0,124,1,0,23,107,2,0,86,1,113,3, - 0,100,1,0,83,41,2,114,188,0,0,0,78,114,4,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,4, - 0,0,0,114,5,0,0,0,250,9,60,103,101,110,101,120, - 112,114,62,185,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0, - 0,0,114,4,0,0,0,41,1,114,230,0,0,0,114,5, - 0,0,0,114,162,0,0,0,182,3,0,0,115,6,0,0, - 0,0,2,19,1,18,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,0,83,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,4,0,0,0,41,2, - 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,190,0,0,0,188,3, - 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,0,83,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, - 4,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, + 0,100,5,0,132,0,0,90,5,0,101,6,0,90,7,0, + 100,6,0,100,7,0,132,0,0,90,8,0,100,8,0,100, + 9,0,132,0,0,90,9,0,100,10,0,100,11,0,100,12, + 0,132,1,0,90,10,0,100,13,0,100,14,0,132,0,0, + 90,11,0,101,12,0,100,15,0,100,16,0,132,0,0,131, + 1,0,90,13,0,100,17,0,100,18,0,132,0,0,90,14, + 0,100,10,0,83,41,19,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,122,0,0,0,103,0,0,125,3, + 0,120,52,0,124,2,0,68,93,44,0,92,2,0,137,0, + 0,125,4,0,124,3,0,106,0,0,135,0,0,102,1,0, + 100,1,0,100,2,0,134,0,0,124,4,0,68,131,1,0, + 131,1,0,1,113,13,0,87,124,3,0,124,0,0,95,1, + 0,124,1,0,112,79,0,100,3,0,124,0,0,95,2,0, + 100,6,0,124,0,0,95,3,0,116,4,0,131,0,0,124, + 0,0,95,5,0,116,4,0,131,0,0,124,0,0,95,6, + 0,100,5,0,83,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,27,0,0,0,124,0,0, + 93,17,0,125,1,0,124,1,0,136,0,0,102,2,0,86, + 1,113,3,0,100,0,0,83,41,1,78,114,4,0,0,0, + 41,2,114,22,0,0,0,114,229,0,0,0,41,1,114,127, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,231,0, + 0,0,194,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0,0,78, + 114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0,0,0,41,1, + 114,127,0,0,0,114,5,0,0,0,114,188,0,0,0,188, + 4,0,0,115,16,0,0,0,0,4,6,1,19,1,36,1, + 9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0,0,95,0,0, + 100,2,0,83,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,29,0,0,0,78,114,87,0, + 0,0,41,1,114,11,1,0,0,41,1,114,108,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 203,0,0,0,192,3,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,7,0,0,0,124,0,0,106,0,0,83, - 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,108,0,0,0,114,126,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,163,0,0,0,196,3,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,13,114,112,0,0,0,114,111,0,0,0,114, - 113,0,0,0,114,114,0,0,0,114,188,0,0,0,114,214, - 0,0,0,114,216,0,0,0,114,123,0,0,0,114,194,0, - 0,0,114,162,0,0,0,114,190,0,0,0,114,203,0,0, - 0,114,163,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,225,0,0,0,145, - 3,0,0,115,18,0,0,0,12,6,6,2,12,4,12,4, - 12,3,18,18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0,100, - 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, - 0,132,0,0,90,4,0,100,4,0,100,5,0,132,0,0, - 90,5,0,100,6,0,100,7,0,132,0,0,90,6,0,100, - 8,0,100,9,0,132,0,0,90,7,0,100,10,0,100,11, - 0,132,0,0,90,8,0,100,12,0,100,13,0,132,0,0, - 90,9,0,100,14,0,100,15,0,132,0,0,90,10,0,100, - 16,0,100,17,0,132,0,0,90,11,0,100,18,0,100,19, - 0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0, - 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, - 0,95,1,0,116,2,0,124,0,0,106,3,0,131,0,0, - 131,1,0,124,0,0,95,4,0,124,3,0,124,0,0,95, - 5,0,100,0,0,83,41,1,78,41,6,218,5,95,110,97, - 109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0, - 0,0,218,11,112,97,116,104,95,102,105,110,100,101,114,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,188, - 0,0,0,209,3,0,0,115,8,0,0,0,0,1,9,1, - 9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1,0, - 100,1,0,131,1,0,92,3,0,125,1,0,125,2,0,125, - 3,0,124,2,0,100,2,0,107,2,0,114,43,0,100,6, - 0,83,124,1,0,100,5,0,102,2,0,83,41,7,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,58, - 0,0,0,114,30,0,0,0,114,7,0,0,0,114,35,0, - 0,0,114,226,0,0,0,41,2,122,3,115,121,115,122,4, - 112,97,116,104,41,2,114,235,0,0,0,114,32,0,0,0, - 41,4,114,108,0,0,0,114,223,0,0,0,218,3,100,111, - 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, - 5,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,215,3,0, - 0,115,8,0,0,0,0,2,27,1,12,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,38,0,0,0, - 124,0,0,106,0,0,131,0,0,92,2,0,125,1,0,125, - 2,0,116,1,0,116,2,0,106,3,0,124,1,0,25,124, - 2,0,131,2,0,83,41,1,78,41,4,114,242,0,0,0, - 114,117,0,0,0,114,7,0,0,0,114,132,0,0,0,41, - 3,114,108,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,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,237,0,0,0,225,3, - 0,0,115,4,0,0,0,0,1,18,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,3,0,0,0,67,0,0, - 0,115,118,0,0,0,116,0,0,124,0,0,106,1,0,131, - 0,0,131,1,0,125,1,0,124,1,0,124,0,0,106,2, - 0,107,3,0,114,111,0,124,0,0,106,3,0,124,0,0, - 106,4,0,124,1,0,131,2,0,125,2,0,124,2,0,100, - 0,0,107,9,0,114,102,0,124,2,0,106,5,0,100,0, - 0,107,8,0,114,102,0,124,2,0,106,6,0,114,102,0, - 124,2,0,106,6,0,124,0,0,95,7,0,124,1,0,124, - 0,0,95,2,0,124,0,0,106,7,0,83,41,1,78,41, - 8,114,93,0,0,0,114,237,0,0,0,114,238,0,0,0, - 114,239,0,0,0,114,235,0,0,0,114,127,0,0,0,114, - 164,0,0,0,114,236,0,0,0,41,3,114,108,0,0,0, - 90,11,112,97,114,101,110,116,95,112,97,116,104,114,133,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,12,95,114,101,99,97,108,99,117,108,97,116,101,229, - 3,0,0,115,16,0,0,0,0,2,18,1,15,1,21,3, - 27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16,0,0,0,116, - 0,0,124,0,0,106,1,0,131,0,0,131,1,0,83,41, - 1,78,41,2,218,4,105,116,101,114,114,243,0,0,0,41, - 1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,8,95,95,105,116,101,114,95,95,242, - 3,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,1,0,0,0,0,0,0,0,1,0,0,0, - 2,0,0,0,67,0,0,0,115,16,0,0,0,116,0,0, - 124,0,0,106,1,0,131,0,0,131,1,0,83,41,1,78, - 41,2,114,31,0,0,0,114,243,0,0,0,41,1,114,108, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,7,95,95,108,101,110,95,95,245,3,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,2,0,0,0,67, - 0,0,0,115,16,0,0,0,100,1,0,106,0,0,124,0, - 0,106,1,0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1,114, - 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,8,95,95,114,101,112,114,95,95,248,3,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,2,0, - 0,0,67,0,0,0,115,16,0,0,0,124,1,0,124,0, - 0,106,0,0,131,0,0,107,6,0,83,41,1,78,41,1, - 114,243,0,0,0,41,2,114,108,0,0,0,218,4,105,116, - 101,109,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,12,95,95,99,111,110,116,97,105,110,115,95,95,251, - 3,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,2,0,0,0,67,0,0,0,115,20,0,0, - 0,124,0,0,106,0,0,106,1,0,124,1,0,131,1,0, - 1,100,0,0,83,41,1,78,41,2,114,236,0,0,0,114, - 169,0,0,0,41,2,114,108,0,0,0,114,248,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 169,0,0,0,254,3,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,13,114,112,0,0,0,114,111, - 0,0,0,114,113,0,0,0,114,114,0,0,0,114,188,0, - 0,0,114,242,0,0,0,114,237,0,0,0,114,243,0,0, - 0,114,245,0,0,0,114,246,0,0,0,114,247,0,0,0, - 114,249,0,0,0,114,169,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,234, - 0,0,0,202,3,0,0,115,20,0,0,0,12,5,6,2, - 12,6,12,10,12,4,12,13,12,3,12,3,12,3,12,3, - 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,118,0,0,0,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,100,2, - 0,132,0,0,90,3,0,101,4,0,100,3,0,100,4,0, - 132,0,0,131,1,0,90,5,0,100,5,0,100,6,0,132, - 0,0,90,6,0,100,7,0,100,8,0,132,0,0,90,7, - 0,100,9,0,100,10,0,132,0,0,90,8,0,100,11,0, - 100,12,0,132,0,0,90,9,0,100,13,0,100,14,0,132, - 0,0,90,10,0,100,15,0,100,16,0,132,0,0,90,11, - 0,100,17,0,83,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,25, - 0,0,0,116,0,0,124,1,0,124,2,0,124,3,0,131, - 3,0,124,0,0,95,1,0,100,0,0,83,41,1,78,41, - 2,114,234,0,0,0,114,236,0,0,0,41,4,114,108,0, - 0,0,114,106,0,0,0,114,35,0,0,0,114,240,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,188,0,0,0,4,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,2,0,0,0,67,0,0,0, - 115,16,0,0,0,100,1,0,106,0,0,124,1,0,106,1, - 0,131,1,0,83,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,47,0,0,0,114,112, - 0,0,0,41,2,114,174,0,0,0,114,134,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, - 109,111,100,117,108,101,95,114,101,112,114,7,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, - 0,83,41,2,78,84,114,4,0,0,0,41,2,114,108,0, - 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,162,0,0,0,16,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,0, - 83,41,2,78,114,30,0,0,0,114,4,0,0,0,41,2, - 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,203,0,0,0,19,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,22,0,0,0, - 116,0,0,100,1,0,100,2,0,100,3,0,100,4,0,100, - 5,0,131,3,1,83,41,6,78,114,30,0,0,0,122,8, - 60,115,116,114,105,110,103,62,114,192,0,0,0,114,205,0, - 0,0,84,41,1,114,206,0,0,0,41,2,114,108,0,0, - 0,114,126,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,190,0,0,0,22,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,0,83,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,4,0, - 0,0,41,2,114,108,0,0,0,114,133,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,189,0, - 0,0,25,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,0,83,41,1,78,114,4,0,0, - 0,41,2,114,108,0,0,0,114,134,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,193,0,0, - 0,28,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,3,0,0,0,67,0,0,0,115, - 29,0,0,0,116,0,0,100,1,0,124,0,0,106,1,0, - 131,2,0,1,116,2,0,124,0,0,124,1,0,131,2,0, - 83,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, - 3,114,105,0,0,0,114,236,0,0,0,114,135,0,0,0, - 41,2,114,108,0,0,0,114,126,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,194,0,0,0, - 31,4,0,0,115,4,0,0,0,0,7,16,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,112, - 0,0,0,114,111,0,0,0,114,113,0,0,0,114,188,0, - 0,0,114,186,0,0,0,114,251,0,0,0,114,162,0,0, - 0,114,203,0,0,0,114,190,0,0,0,114,189,0,0,0, - 114,193,0,0,0,114,194,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,250, - 0,0,0,3,4,0,0,115,16,0,0,0,12,1,12,3, - 18,9,12,3,12,3,12,3,12,3,12,3,114,250,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,5,0, - 0,0,64,0,0,0,115,160,0,0,0,101,0,0,90,1, - 0,100,0,0,90,2,0,100,1,0,90,3,0,101,4,0, - 100,2,0,100,3,0,132,0,0,131,1,0,90,5,0,101, - 4,0,100,4,0,100,5,0,132,0,0,131,1,0,90,6, - 0,101,4,0,100,6,0,100,7,0,132,0,0,131,1,0, - 90,7,0,101,4,0,100,8,0,100,9,0,132,0,0,131, - 1,0,90,8,0,101,4,0,100,10,0,100,11,0,100,12, - 0,132,1,0,131,1,0,90,9,0,101,4,0,100,10,0, - 100,10,0,100,13,0,100,14,0,132,2,0,131,1,0,90, - 10,0,101,4,0,100,10,0,100,15,0,100,16,0,132,1, - 0,131,1,0,90,11,0,100,10,0,83,41,17,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,55, - 0,0,0,120,48,0,116,0,0,106,1,0,106,2,0,131, - 0,0,68,93,31,0,125,1,0,116,3,0,124,1,0,100, - 1,0,131,2,0,114,16,0,124,1,0,106,4,0,131,0, - 0,1,113,16,0,87,100,2,0,83,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,7,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,115,0,0,0,114,253,0,0,0,41,2,114, - 174,0,0,0,218,6,102,105,110,100,101,114,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,253,0,0,0, - 48,4,0,0,115,6,0,0,0,0,4,22,1,15,1,122, - 28,80,97,116,104,70,105,110,100,101,114,46,105,110,118,97, + 253,0,0,0,202,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,12,0,0,0,67,0, - 0,0,115,107,0,0,0,116,0,0,106,1,0,100,1,0, - 107,9,0,114,41,0,116,0,0,106,1,0,12,114,41,0, - 116,2,0,106,3,0,100,2,0,116,4,0,131,2,0,1, - 120,59,0,116,0,0,106,1,0,68,93,44,0,125,2,0, - 121,14,0,124,2,0,124,1,0,131,1,0,83,87,113,51, - 0,4,116,5,0,107,10,0,114,94,0,1,1,1,119,51, - 0,89,113,51,0,88,113,51,0,87,100,1,0,83,100,1, - 0,83,41,3,122,113,83,101,97,114,99,104,32,115,101,113, - 117,101,110,99,101,32,111,102,32,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,10,10,32,32,32,32,32,32,32, - 32,73,102,32,39,104,111,111,107,115,39,32,105,115,32,102, - 97,108,115,101,32,116,104,101,110,32,117,115,101,32,115,121, - 115,46,112,97,116,104,95,104,111,111,107,115,46,10,10,32, - 32,32,32,32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95,104, - 111,111,107,115,114,60,0,0,0,114,61,0,0,0,114,125, - 0,0,0,114,107,0,0,0,41,3,114,174,0,0,0,114, - 35,0,0,0,90,4,104,111,111,107,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,11,95,112,97,116,104, - 95,104,111,111,107,115,56,4,0,0,115,16,0,0,0,0, - 7,25,1,16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0,0, - 0,124,1,0,100,1,0,107,2,0,114,53,0,121,16,0, - 116,0,0,106,1,0,131,0,0,125,1,0,87,110,22,0, - 4,116,2,0,107,10,0,114,52,0,1,1,1,100,2,0, - 83,89,110,1,0,88,121,17,0,116,3,0,106,4,0,124, - 1,0,25,125,2,0,87,110,46,0,4,116,5,0,107,10, - 0,114,118,0,1,1,1,124,0,0,106,6,0,124,1,0, - 131,1,0,125,2,0,124,2,0,116,3,0,106,4,0,124, - 1,0,60,89,110,1,0,88,124,2,0,83,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,3,0,0,0,114, - 45,0,0,0,218,17,70,105,108,101,78,111,116,70,111,117, - 110,100,69,114,114,111,114,114,7,0,0,0,114,254,0,0, - 0,114,142,0,0,0,114,2,1,0,0,41,3,114,174,0, - 0,0,114,35,0,0,0,114,0,1,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,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,73,4,0,0,115,22,0,0,0,0,8,12,1,3,1, - 16,1,13,3,9,1,3,1,17,1,13,1,15,1,18,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,3,0, - 0,0,67,0,0,0,115,116,0,0,0,116,0,0,124,2, - 0,100,1,0,131,2,0,114,39,0,124,2,0,106,1,0, - 124,1,0,131,1,0,92,2,0,125,3,0,125,4,0,110, - 21,0,124,2,0,106,2,0,124,1,0,131,1,0,125,3, - 0,103,0,0,125,4,0,124,3,0,100,0,0,107,9,0, - 114,85,0,116,3,0,124,1,0,124,3,0,131,2,0,83, - 116,4,0,106,5,0,124,1,0,100,0,0,131,2,0,125, - 5,0,124,4,0,124,5,0,95,6,0,124,5,0,83,41, - 2,78,114,124,0,0,0,41,7,114,115,0,0,0,114,124, - 0,0,0,114,185,0,0,0,114,131,0,0,0,114,121,0, - 0,0,114,166,0,0,0,114,164,0,0,0,41,6,114,174, - 0,0,0,114,126,0,0,0,114,0,1,0,0,114,127,0, - 0,0,114,128,0,0,0,114,133,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,16,95,108,101, - 103,97,99,121,95,103,101,116,95,115,112,101,99,95,4,0, - 0,115,18,0,0,0,0,4,15,1,24,2,15,1,6,1, - 12,1,13,1,18,1,9,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,243,0,0,0, - 103,0,0,125,4,0,120,230,0,124,2,0,68,93,191,0, - 125,5,0,116,0,0,124,5,0,116,1,0,116,2,0,102, - 2,0,131,2,0,115,43,0,113,13,0,124,0,0,106,3, - 0,124,5,0,131,1,0,125,6,0,124,6,0,100,1,0, - 107,9,0,114,13,0,116,4,0,124,6,0,100,2,0,131, - 2,0,114,106,0,124,6,0,106,5,0,124,1,0,124,3, - 0,131,2,0,125,7,0,110,18,0,124,0,0,106,6,0, - 124,1,0,124,6,0,131,2,0,125,7,0,124,7,0,100, - 1,0,107,8,0,114,139,0,113,13,0,124,7,0,106,7, - 0,100,1,0,107,9,0,114,158,0,124,7,0,83,124,7, - 0,106,8,0,125,8,0,124,8,0,100,1,0,107,8,0, - 114,191,0,116,9,0,100,3,0,131,1,0,130,1,0,124, - 4,0,106,10,0,124,8,0,131,1,0,1,113,13,0,87, - 116,11,0,106,12,0,124,1,0,100,1,0,131,2,0,125, - 7,0,124,4,0,124,7,0,95,8,0,124,7,0,83,100, - 1,0,83,41,4,122,63,70,105,110,100,32,116,104,101,32, - 108,111,97,100,101,114,32,111,114,32,110,97,109,101,115,112, - 97,99,101,95,112,97,116,104,32,102,111,114,32,116,104,105, - 115,32,109,111,100,117,108,101,47,112,97,99,107,97,103,101, - 32,110,97,109,101,46,78,114,184,0,0,0,122,19,115,112, - 101,99,32,109,105,115,115,105,110,103,32,108,111,97,100,101, - 114,41,13,114,148,0,0,0,114,69,0,0,0,218,5,98, - 121,116,101,115,114,4,1,0,0,114,115,0,0,0,114,184, - 0,0,0,114,5,1,0,0,114,127,0,0,0,114,164,0, - 0,0,114,107,0,0,0,114,154,0,0,0,114,121,0,0, - 0,114,166,0,0,0,41,9,114,174,0,0,0,114,126,0, - 0,0,114,35,0,0,0,114,183,0,0,0,218,14,110,97, - 109,101,115,112,97,99,101,95,112,97,116,104,90,5,101,110, - 116,114,121,114,0,1,0,0,114,133,0,0,0,114,128,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,9,95,103,101,116,95,115,112,101,99,110,4,0,0, - 115,40,0,0,0,0,5,6,1,13,1,21,1,3,1,15, - 1,12,1,15,1,21,2,18,1,12,1,3,1,15,1,4, - 1,9,1,12,1,12,5,17,2,18,1,9,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, - 4,0,0,0,67,0,0,0,115,140,0,0,0,124,2,0, - 100,1,0,107,8,0,114,21,0,116,0,0,106,1,0,125, - 2,0,124,0,0,106,2,0,124,1,0,124,2,0,124,3, - 0,131,3,0,125,4,0,124,4,0,100,1,0,107,8,0, - 114,58,0,100,1,0,83,124,4,0,106,3,0,100,1,0, - 107,8,0,114,132,0,124,4,0,106,4,0,125,5,0,124, - 5,0,114,125,0,100,2,0,124,4,0,95,5,0,116,6, - 0,124,1,0,124,5,0,124,0,0,106,2,0,131,3,0, - 124,4,0,95,4,0,124,4,0,83,100,1,0,83,110,4, - 0,124,4,0,83,100,1,0,83,41,3,122,98,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,78, - 90,9,110,97,109,101,115,112,97,99,101,41,7,114,7,0, - 0,0,114,35,0,0,0,114,8,1,0,0,114,127,0,0, - 0,114,164,0,0,0,114,161,0,0,0,114,234,0,0,0, - 41,6,114,174,0,0,0,114,126,0,0,0,114,35,0,0, - 0,114,183,0,0,0,114,133,0,0,0,114,7,1,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 184,0,0,0,142,4,0,0,115,26,0,0,0,0,4,12, - 1,9,1,21,1,12,1,4,1,15,1,9,1,6,3,9, - 1,24,1,4,2,7,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,41,0,0,0,124,0,0,106,0,0,124,1,0, - 124,2,0,131,2,0,125,3,0,124,3,0,100,1,0,107, - 8,0,114,34,0,100,1,0,83,124,3,0,106,1,0,83, - 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,184,0,0,0,114,127,0,0,0,41,4,114,174,0, - 0,0,114,126,0,0,0,114,35,0,0,0,114,133,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,185,0,0,0,164,4,0,0,115,8,0,0,0,0,8, - 18,1,12,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,12, - 114,112,0,0,0,114,111,0,0,0,114,113,0,0,0,114, - 114,0,0,0,114,186,0,0,0,114,253,0,0,0,114,2, - 1,0,0,114,4,1,0,0,114,5,1,0,0,114,8,1, - 0,0,114,184,0,0,0,114,185,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,252,0,0,0,44,4,0,0,115,22,0,0,0,12,2, - 6,2,18,8,18,17,18,22,18,15,3,1,18,31,3,1, - 21,21,3,1,114,252,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,133, - 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, - 1,0,90,3,0,100,2,0,100,3,0,132,0,0,90,4, - 0,100,4,0,100,5,0,132,0,0,90,5,0,101,6,0, - 90,7,0,100,6,0,100,7,0,132,0,0,90,8,0,100, - 8,0,100,9,0,132,0,0,90,9,0,100,10,0,100,11, - 0,100,12,0,132,1,0,90,10,0,100,13,0,100,14,0, - 132,0,0,90,11,0,101,12,0,100,15,0,100,16,0,132, - 0,0,131,1,0,90,13,0,100,17,0,100,18,0,132,0, - 0,90,14,0,100,10,0,83,41,19,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,122,0,0,0,103,0, - 0,125,3,0,120,52,0,124,2,0,68,93,44,0,92,2, - 0,137,0,0,125,4,0,124,3,0,106,0,0,135,0,0, - 102,1,0,100,1,0,100,2,0,134,0,0,124,4,0,68, - 131,1,0,131,1,0,1,113,13,0,87,124,3,0,124,0, - 0,95,1,0,124,1,0,112,79,0,100,3,0,124,0,0, - 95,2,0,100,6,0,124,0,0,95,3,0,116,4,0,131, - 0,0,124,0,0,95,5,0,116,4,0,131,0,0,124,0, - 0,95,6,0,100,5,0,83,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,27,0,0,0, - 124,0,0,93,17,0,125,1,0,124,1,0,136,0,0,102, - 2,0,86,1,113,3,0,100,0,0,83,41,1,78,114,4, - 0,0,0,41,2,114,22,0,0,0,114,229,0,0,0,41, - 1,114,127,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,231,0,0,0,193,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0, - 0,0,78,114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0,0, - 0,41,1,114,127,0,0,0,114,5,0,0,0,114,188,0, - 0,0,187,4,0,0,115,16,0,0,0,0,4,6,1,19, - 1,36,1,9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0,0, - 95,0,0,100,2,0,83,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,29,0,0,0,78, - 114,87,0,0,0,41,1,114,11,1,0,0,41,1,114,108, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,253,0,0,0,201,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,59,0,0,0,124,0,0,106,0,0, - 124,1,0,131,1,0,125,2,0,124,2,0,100,1,0,107, - 8,0,114,37,0,100,1,0,103,0,0,102,2,0,83,124, - 2,0,106,1,0,124,2,0,106,2,0,112,55,0,103,0, - 0,102,2,0,83,41,2,122,197,84,114,121,32,116,111,32, + 0,0,0,0,0,0,3,0,0,0,2,0,0,0,67,0, + 0,0,115,59,0,0,0,124,0,0,106,0,0,124,1,0, + 131,1,0,125,2,0,124,2,0,100,1,0,107,8,0,114, + 37,0,100,1,0,103,0,0,102,2,0,83,124,2,0,106, + 1,0,124,2,0,106,2,0,112,55,0,103,0,0,102,2, + 0,83,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,184, + 0,0,0,114,127,0,0,0,114,164,0,0,0,41,3,114, + 108,0,0,0,114,126,0,0,0,114,133,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,124,0, + 0,0,208,4,0,0,115,8,0,0,0,0,7,15,1,12, + 1,10,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,7,0,0,0,67,0,0,0, + 115,40,0,0,0,124,1,0,124,2,0,124,3,0,131,2, + 0,125,6,0,116,0,0,124,2,0,124,3,0,100,1,0, + 124,6,0,100,2,0,124,4,0,131,2,2,83,41,3,78, + 114,127,0,0,0,114,164,0,0,0,41,1,114,165,0,0, + 0,41,7,114,108,0,0,0,114,170,0,0,0,114,126,0, + 0,0,114,35,0,0,0,90,4,115,109,115,108,114,183,0, + 0,0,114,127,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,8,1,0,0,220,4,0,0,115, + 6,0,0,0,0,1,15,1,18,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,234,1,0,0,100,1,0,125,3, + 0,124,1,0,106,0,0,100,2,0,131,1,0,100,3,0, + 25,125,4,0,121,34,0,116,1,0,124,0,0,106,2,0, + 112,49,0,116,3,0,106,4,0,131,0,0,131,1,0,106, + 5,0,125,5,0,87,110,24,0,4,116,6,0,107,10,0, + 114,85,0,1,1,1,100,10,0,125,5,0,89,110,1,0, + 88,124,5,0,124,0,0,106,7,0,107,3,0,114,120,0, + 124,0,0,106,8,0,131,0,0,1,124,5,0,124,0,0, + 95,7,0,116,9,0,131,0,0,114,153,0,124,0,0,106, + 10,0,125,6,0,124,4,0,106,11,0,131,0,0,125,7, + 0,110,15,0,124,0,0,106,12,0,125,6,0,124,4,0, + 125,7,0,124,7,0,124,6,0,107,6,0,114,45,1,116, + 13,0,124,0,0,106,2,0,124,4,0,131,2,0,125,8, + 0,120,100,0,124,0,0,106,14,0,68,93,77,0,92,2, + 0,125,9,0,125,10,0,100,5,0,124,9,0,23,125,11, + 0,116,13,0,124,8,0,124,11,0,131,2,0,125,12,0, + 116,15,0,124,12,0,131,1,0,114,208,0,124,0,0,106, + 16,0,124,10,0,124,1,0,124,12,0,124,8,0,103,1, + 0,124,2,0,131,5,0,83,113,208,0,87,116,17,0,124, + 8,0,131,1,0,125,3,0,120,123,0,124,0,0,106,14, + 0,68,93,112,0,92,2,0,125,9,0,125,10,0,116,13, + 0,124,0,0,106,2,0,124,4,0,124,9,0,23,131,2, + 0,125,12,0,116,18,0,100,6,0,106,19,0,124,12,0, + 131,1,0,100,7,0,100,3,0,131,1,1,1,124,7,0, + 124,9,0,23,124,6,0,107,6,0,114,55,1,116,15,0, + 124,12,0,131,1,0,114,55,1,124,0,0,106,16,0,124, + 10,0,124,1,0,124,12,0,100,8,0,124,2,0,131,5, + 0,83,113,55,1,87,124,3,0,114,230,1,116,18,0,100, + 9,0,106,19,0,124,8,0,131,1,0,131,1,0,1,116, + 20,0,106,21,0,124,1,0,100,8,0,131,2,0,125,13, + 0,124,8,0,103,1,0,124,13,0,95,22,0,124,13,0, + 83,100,8,0,83,41,11,122,125,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, @@ -2229,405 +2291,342 @@ 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,184,0,0,0,114,127,0,0,0,114,164,0,0,0, - 41,3,114,108,0,0,0,114,126,0,0,0,114,133,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,124,0,0,0,207,4,0,0,115,8,0,0,0,0,7, - 15,1,12,1,10,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,7,0,0,0,67, - 0,0,0,115,40,0,0,0,124,1,0,124,2,0,124,3, - 0,131,2,0,125,6,0,116,0,0,124,2,0,124,3,0, - 100,1,0,124,6,0,100,2,0,124,4,0,131,2,2,83, - 41,3,78,114,127,0,0,0,114,164,0,0,0,41,1,114, - 165,0,0,0,41,7,114,108,0,0,0,114,170,0,0,0, - 114,126,0,0,0,114,35,0,0,0,90,4,115,109,115,108, - 114,183,0,0,0,114,127,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,8,1,0,0,219,4, - 0,0,115,6,0,0,0,0,1,15,1,18,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,234,1,0,0,100,1, - 0,125,3,0,124,1,0,106,0,0,100,2,0,131,1,0, - 100,3,0,25,125,4,0,121,34,0,116,1,0,124,0,0, - 106,2,0,112,49,0,116,3,0,106,4,0,131,0,0,131, - 1,0,106,5,0,125,5,0,87,110,24,0,4,116,6,0, - 107,10,0,114,85,0,1,1,1,100,10,0,125,5,0,89, - 110,1,0,88,124,5,0,124,0,0,106,7,0,107,3,0, - 114,120,0,124,0,0,106,8,0,131,0,0,1,124,5,0, - 124,0,0,95,7,0,116,9,0,131,0,0,114,153,0,124, - 0,0,106,10,0,125,6,0,124,4,0,106,11,0,131,0, - 0,125,7,0,110,15,0,124,0,0,106,12,0,125,6,0, - 124,4,0,125,7,0,124,7,0,124,6,0,107,6,0,114, - 45,1,116,13,0,124,0,0,106,2,0,124,4,0,131,2, - 0,125,8,0,120,100,0,124,0,0,106,14,0,68,93,77, - 0,92,2,0,125,9,0,125,10,0,100,5,0,124,9,0, - 23,125,11,0,116,13,0,124,8,0,124,11,0,131,2,0, - 125,12,0,116,15,0,124,12,0,131,1,0,114,208,0,124, - 0,0,106,16,0,124,10,0,124,1,0,124,12,0,124,8, - 0,103,1,0,124,2,0,131,5,0,83,113,208,0,87,116, - 17,0,124,8,0,131,1,0,125,3,0,120,123,0,124,0, - 0,106,14,0,68,93,112,0,92,2,0,125,9,0,125,10, - 0,116,13,0,124,0,0,106,2,0,124,4,0,124,9,0, - 23,131,2,0,125,12,0,116,18,0,100,6,0,106,19,0, - 124,12,0,131,1,0,100,7,0,100,3,0,131,1,1,1, - 124,7,0,124,9,0,23,124,6,0,107,6,0,114,55,1, - 116,15,0,124,12,0,131,1,0,114,55,1,124,0,0,106, - 16,0,124,10,0,124,1,0,124,12,0,100,8,0,124,2, - 0,131,5,0,83,113,55,1,87,124,3,0,114,230,1,116, - 18,0,100,9,0,106,19,0,124,8,0,131,1,0,131,1, - 0,1,116,20,0,106,21,0,124,1,0,100,8,0,131,2, - 0,125,13,0,124,8,0,103,1,0,124,13,0,95,22,0, - 124,13,0,83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0,114, - 56,0,0,0,114,29,0,0,0,114,188,0,0,0,122,9, - 116,114,121,105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0,41, - 23,114,32,0,0,0,114,39,0,0,0,114,35,0,0,0, - 114,3,0,0,0,114,45,0,0,0,114,220,0,0,0,114, - 40,0,0,0,114,11,1,0,0,218,11,95,102,105,108,108, - 95,99,97,99,104,101,114,6,0,0,0,114,14,1,0,0, - 114,88,0,0,0,114,13,1,0,0,114,28,0,0,0,114, - 10,1,0,0,114,44,0,0,0,114,8,1,0,0,114,46, - 0,0,0,114,105,0,0,0,114,47,0,0,0,114,121,0, - 0,0,114,166,0,0,0,114,164,0,0,0,41,14,114,108, - 0,0,0,114,126,0,0,0,114,183,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,138,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,229,0, - 0,0,114,170,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,133,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,184,0,0,0,224,4,0,0,115,68, - 0,0,0,0,3,6,1,19,1,3,1,34,1,13,1,11, - 1,15,1,10,1,9,2,9,1,9,1,15,2,9,1,6, - 2,12,1,18,1,22,1,10,1,15,1,12,1,32,4,12, - 2,22,1,22,1,25,1,16,1,12,1,29,1,6,1,19, - 1,18,1,12,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,11,1,0,0,124,0,0,106,0,0,125,1,0, - 121,31,0,116,1,0,106,2,0,124,1,0,112,33,0,116, - 1,0,106,3,0,131,0,0,131,1,0,125,2,0,87,110, - 33,0,4,116,4,0,116,5,0,116,6,0,102,3,0,107, - 10,0,114,75,0,1,1,1,103,0,0,125,2,0,89,110, - 1,0,88,116,7,0,106,8,0,106,9,0,100,1,0,131, - 1,0,115,112,0,116,10,0,124,2,0,131,1,0,124,0, - 0,95,11,0,110,111,0,116,10,0,131,0,0,125,3,0, - 120,90,0,124,2,0,68,93,82,0,125,4,0,124,4,0, - 106,12,0,100,2,0,131,1,0,92,3,0,125,5,0,125, - 6,0,125,7,0,124,6,0,114,191,0,100,3,0,106,13, - 0,124,5,0,124,7,0,106,14,0,131,0,0,131,2,0, - 125,8,0,110,6,0,124,5,0,125,8,0,124,3,0,106, - 15,0,124,8,0,131,1,0,1,113,128,0,87,124,3,0, - 124,0,0,95,11,0,116,7,0,106,8,0,106,9,0,116, - 16,0,131,1,0,114,7,1,100,4,0,100,5,0,132,0, - 0,124,2,0,68,131,1,0,124,0,0,95,17,0,100,6, - 0,83,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, - 58,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,28,0,0,0,104,0,0,124,0,0,93,18,0,125,1, - 0,124,1,0,106,0,0,131,0,0,146,2,0,113,6,0, - 83,114,4,0,0,0,41,1,114,88,0,0,0,41,2,114, - 22,0,0,0,90,2,102,110,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,250,9,60,115,101,116,99,111,109, - 112,62,42,5,0,0,115,2,0,0,0,9,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,3,0,0,0,90,7,108,105,115,116,100,105,114,114,45, - 0,0,0,114,3,1,0,0,218,15,80,101,114,109,105,115, - 115,105,111,110,69,114,114,111,114,218,18,78,111,116,65,68, - 105,114,101,99,116,111,114,121,69,114,114,111,114,114,7,0, - 0,0,114,8,0,0,0,114,9,0,0,0,114,12,1,0, - 0,114,13,1,0,0,114,83,0,0,0,114,47,0,0,0, - 114,88,0,0,0,218,3,97,100,100,114,10,0,0,0,114, - 14,1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,241,0,0,0, - 114,229,0,0,0,90,8,110,101,119,95,110,97,109,101,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,16, - 1,0,0,13,5,0,0,115,34,0,0,0,0,2,9,1, - 3,1,31,1,22,3,11,3,18,1,18,7,9,1,13,1, - 24,1,6,1,27,2,6,1,17,1,9,1,18,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,25,0,0,0, - 135,0,0,135,1,0,102,2,0,100,1,0,100,2,0,134, - 0,0,125,2,0,124,2,0,83,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,43,0,0,0,116,0, - 0,124,0,0,131,1,0,115,30,0,116,1,0,100,1,0, - 100,2,0,124,0,0,131,1,1,130,1,0,136,0,0,124, - 0,0,136,1,0,140,1,0,83,41,3,122,45,80,97,116, - 104,32,104,111,111,107,32,102,111,114,32,105,109,112,111,114, - 116,108,105,98,46,109,97,99,104,105,110,101,114,121,46,70, - 105,108,101,70,105,110,100,101,114,46,122,30,111,110,108,121, - 32,100,105,114,101,99,116,111,114,105,101,115,32,97,114,101, - 32,115,117,112,112,111,114,116,101,100,114,35,0,0,0,41, - 2,114,46,0,0,0,114,107,0,0,0,41,1,114,35,0, - 0,0,41,2,114,174,0,0,0,114,15,1,0,0,114,4, - 0,0,0,114,5,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,54,5,0,0,115,6,0,0,0,0,2,12,1,18, - 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,174,0,0,0,114,15,1,0,0,114,21,1,0,0,114, - 4,0,0,0,41,2,114,174,0,0,0,114,15,1,0,0, - 114,5,0,0,0,218,9,112,97,116,104,95,104,111,111,107, - 44,5,0,0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1,0, - 106,0,0,124,0,0,106,1,0,131,1,0,83,41,2,78, - 122,16,70,105,108,101,70,105,110,100,101,114,40,123,33,114, - 125,41,41,2,114,47,0,0,0,114,35,0,0,0,41,1, - 114,108,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,247,0,0,0,62,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,15,114,112,0,0,0, - 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, - 188,0,0,0,114,253,0,0,0,114,130,0,0,0,114,185, - 0,0,0,114,124,0,0,0,114,8,1,0,0,114,184,0, - 0,0,114,16,1,0,0,114,186,0,0,0,114,22,1,0, - 0,114,247,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,9,1,0,0,178, - 4,0,0,115,20,0,0,0,12,7,6,2,12,14,12,4, - 6,2,12,12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106,0, - 0,100,1,0,131,1,0,125,4,0,124,0,0,106,0,0, - 100,2,0,131,1,0,125,5,0,124,4,0,115,99,0,124, - 5,0,114,54,0,124,5,0,106,1,0,125,4,0,110,45, - 0,124,2,0,124,3,0,107,2,0,114,84,0,116,2,0, - 124,1,0,124,2,0,131,2,0,125,4,0,110,15,0,116, - 3,0,124,1,0,124,2,0,131,2,0,125,4,0,124,5, - 0,115,126,0,116,4,0,124,1,0,124,2,0,100,3,0, - 124,4,0,131,2,1,125,5,0,121,44,0,124,5,0,124, - 0,0,100,2,0,60,124,4,0,124,0,0,100,1,0,60, - 124,2,0,124,0,0,100,4,0,60,124,3,0,124,0,0, - 100,5,0,60,87,110,18,0,4,116,5,0,107,10,0,114, - 190,0,1,1,1,89,110,1,0,88,100,0,0,83,41,6, - 78,114,227,0,0,0,218,8,95,95,115,112,101,99,95,95, - 114,127,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,127,0,0,0,114,224,0,0,0,114,219,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,106,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,127,0,0,0,114,133,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,14,95,102,105,120, - 95,117,112,95,109,111,100,117,108,101,68,5,0,0,115,34, - 0,0,0,0,2,15,1,15,1,6,1,6,1,12,1,12, - 1,18,2,15,1,6,1,21,1,3,1,10,1,10,1,10, - 1,14,1,13,2,114,26,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, - 55,0,0,0,116,0,0,116,1,0,106,2,0,131,0,0, - 102,2,0,125,0,0,116,3,0,116,4,0,102,2,0,125, - 1,0,116,5,0,116,6,0,102,2,0,125,2,0,124,0, - 0,124,1,0,124,2,0,103,3,0,83,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,225,0,0,0,114,150,0,0,0,218,18,101,120,116,101, - 110,115,105,111,110,95,115,117,102,102,105,120,101,115,114,219, - 0,0,0,114,84,0,0,0,114,224,0,0,0,114,74,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,5,0,0, - 0,114,167,0,0,0,91,5,0,0,115,8,0,0,0,0, - 5,18,1,12,1,12,1,114,167,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,70,2,0,0,124,0,0,97,0,0,116,0,0,106, - 1,0,97,1,0,116,0,0,106,2,0,97,2,0,116,1, - 0,106,3,0,116,4,0,25,125,1,0,120,76,0,100,26, - 0,68,93,68,0,125,2,0,124,2,0,116,1,0,106,3, - 0,107,7,0,114,83,0,116,0,0,106,5,0,124,2,0, - 131,1,0,125,3,0,110,13,0,116,1,0,106,3,0,124, - 2,0,25,125,3,0,116,6,0,124,1,0,124,2,0,124, - 3,0,131,3,0,1,113,44,0,87,100,5,0,100,6,0, - 103,1,0,102,2,0,100,7,0,100,8,0,100,6,0,103, - 2,0,102,2,0,102,2,0,125,4,0,120,149,0,124,4, - 0,68,93,129,0,92,2,0,125,5,0,125,6,0,116,7, - 0,100,9,0,100,10,0,132,0,0,124,6,0,68,131,1, - 0,131,1,0,115,199,0,116,8,0,130,1,0,124,6,0, - 100,11,0,25,125,7,0,124,5,0,116,1,0,106,3,0, - 107,6,0,114,241,0,116,1,0,106,3,0,124,5,0,25, - 125,8,0,80,113,156,0,121,20,0,116,0,0,106,5,0, - 124,5,0,131,1,0,125,8,0,80,87,113,156,0,4,116, - 9,0,107,10,0,114,28,1,1,1,1,119,156,0,89,113, - 156,0,88,113,156,0,87,116,9,0,100,12,0,131,1,0, - 130,1,0,116,6,0,124,1,0,100,13,0,124,8,0,131, - 3,0,1,116,6,0,124,1,0,100,14,0,124,7,0,131, - 3,0,1,116,6,0,124,1,0,100,15,0,100,16,0,106, - 10,0,124,6,0,131,1,0,131,3,0,1,121,19,0,116, - 0,0,106,5,0,100,17,0,131,1,0,125,9,0,87,110, - 24,0,4,116,9,0,107,10,0,114,147,1,1,1,1,100, - 18,0,125,9,0,89,110,1,0,88,116,6,0,124,1,0, - 100,17,0,124,9,0,131,3,0,1,116,0,0,106,5,0, - 100,19,0,131,1,0,125,10,0,116,6,0,124,1,0,100, - 19,0,124,10,0,131,3,0,1,124,5,0,100,7,0,107, - 2,0,114,238,1,116,0,0,106,5,0,100,20,0,131,1, - 0,125,11,0,116,6,0,124,1,0,100,21,0,124,11,0, - 131,3,0,1,116,6,0,124,1,0,100,22,0,116,11,0, - 131,0,0,131,3,0,1,116,12,0,106,13,0,116,2,0, - 106,14,0,131,0,0,131,1,0,1,124,5,0,100,7,0, - 107,2,0,114,66,2,116,15,0,106,16,0,100,23,0,131, - 1,0,1,100,24,0,116,12,0,107,6,0,114,66,2,100, - 25,0,116,17,0,95,18,0,100,18,0,83,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,49,0, - 0,0,114,60,0,0,0,218,8,98,117,105,108,116,105,110, - 115,114,147,0,0,0,90,5,112,111,115,105,120,250,1,47, - 218,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,33,0,0, - 0,124,0,0,93,23,0,125,1,0,116,0,0,124,1,0, - 131,1,0,100,0,0,107,2,0,86,1,113,3,0,100,1, - 0,83,41,2,114,29,0,0,0,78,41,1,114,31,0,0, - 0,41,2,114,22,0,0,0,114,77,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,231,0,0, - 0,127,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,173,0,0, - 0,114,6,0,0,0,122,4,46,112,121,119,122,6,95,100, - 46,112,121,100,84,41,4,122,3,95,105,111,122,9,95,119, - 97,114,110,105,110,103,115,122,8,98,117,105,108,116,105,110, - 115,122,7,109,97,114,115,104,97,108,41,19,114,121,0,0, - 0,114,7,0,0,0,114,150,0,0,0,114,132,0,0,0, - 114,112,0,0,0,90,18,95,98,117,105,108,116,105,110,95, - 102,114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0, - 0,0,114,233,0,0,0,114,154,0,0,0,114,27,1,0, - 0,114,84,0,0,0,114,169,0,0,0,114,172,0,0,0, - 114,177,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 6,95,115,101,116,117,112,102,5,0,0,115,82,0,0,0, - 0,8,6,1,9,1,9,3,13,1,13,1,15,1,18,2, - 13,1,20,3,33,1,19,2,31,1,10,1,15,1,13,1, - 4,2,3,1,15,1,5,1,13,1,12,2,12,1,16,1, - 16,1,25,3,3,1,19,1,13,2,11,1,16,3,15,1, - 16,3,12,1,15,1,16,3,19,1,19,1,12,1,13,1, - 12,1,114,35,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,116,0,0, - 0,116,0,0,124,0,0,131,1,0,1,116,1,0,131,0, - 0,125,1,0,116,2,0,106,3,0,106,4,0,116,5,0, - 106,6,0,124,1,0,140,0,0,103,1,0,131,1,0,1, - 116,7,0,106,8,0,100,1,0,107,2,0,114,78,0,116, - 2,0,106,9,0,106,10,0,116,11,0,131,1,0,1,116, - 2,0,106,9,0,106,10,0,116,12,0,131,1,0,1,116, - 5,0,124,0,0,95,5,0,116,13,0,124,0,0,95,13, - 0,100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0,114, - 167,0,0,0,114,7,0,0,0,114,1,1,0,0,114,154, - 0,0,0,114,9,1,0,0,114,22,1,0,0,114,3,0, - 0,0,114,112,0,0,0,218,9,109,101,116,97,95,112,97, - 116,104,114,169,0,0,0,114,172,0,0,0,114,252,0,0, - 0,114,219,0,0,0,41,2,114,34,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,5,0,0,0,218, - 8,95,105,110,115,116,97,108,108,170,5,0,0,115,16,0, - 0,0,0,2,10,1,9,1,28,1,15,1,16,1,16,4, - 9,1,114,37,1,0,0,41,3,122,3,119,105,110,114,1, - 0,0,0,114,2,0,0,0,41,59,114,114,0,0,0,114, - 10,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,55,0,0,0,218,4,116,121,112,101,218,8,95,95, - 99,111,100,101,95,95,114,149,0,0,0,114,15,0,0,0, - 114,140,0,0,0,114,14,0,0,0,114,18,0,0,0,90, - 17,95,82,65,87,95,77,65,71,73,67,95,78,85,77,66, - 69,82,114,73,0,0,0,114,72,0,0,0,114,84,0,0, - 0,114,74,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,79,0,0, - 0,114,85,0,0,0,114,91,0,0,0,114,95,0,0,0, - 114,97,0,0,0,114,105,0,0,0,114,123,0,0,0,114, - 130,0,0,0,114,135,0,0,0,114,146,0,0,0,114,152, - 0,0,0,114,155,0,0,0,114,160,0,0,0,114,131,0, - 0,0,218,6,111,98,106,101,99,116,114,168,0,0,0,114, - 165,0,0,0,114,172,0,0,0,114,187,0,0,0,114,195, - 0,0,0,114,211,0,0,0,114,219,0,0,0,114,224,0, - 0,0,114,233,0,0,0,114,225,0,0,0,114,234,0,0, - 0,114,250,0,0,0,114,252,0,0,0,114,9,1,0,0, - 114,26,1,0,0,114,167,0,0,0,114,35,1,0,0,114, - 37,1,0,0,114,4,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,8,60,109,111,100,117,108, - 101,62,8,0,0,0,115,104,0,0,0,6,17,6,3,12, - 12,12,5,12,5,12,6,12,12,12,10,12,9,12,5,12, - 7,15,22,15,107,22,1,18,2,6,1,6,2,9,2,9, - 2,10,2,21,44,12,33,12,19,12,12,12,12,18,8,12, - 27,12,18,12,15,21,55,21,12,18,10,12,14,24,22,9, - 3,12,1,15,65,19,63,19,27,22,110,19,41,25,43,25, - 16,6,3,19,57,19,57,19,41,19,134,19,146,15,23,12, - 11,12,68, + 105,111,110,115,41,46,70,114,58,0,0,0,114,56,0,0, + 0,114,29,0,0,0,114,188,0,0,0,122,9,116,114,121, + 105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0,41,23,114,32, + 0,0,0,114,39,0,0,0,114,35,0,0,0,114,3,0, + 0,0,114,45,0,0,0,114,220,0,0,0,114,40,0,0, + 0,114,11,1,0,0,218,11,95,102,105,108,108,95,99,97, + 99,104,101,114,6,0,0,0,114,14,1,0,0,114,88,0, + 0,0,114,13,1,0,0,114,28,0,0,0,114,10,1,0, + 0,114,44,0,0,0,114,8,1,0,0,114,46,0,0,0, + 114,105,0,0,0,114,47,0,0,0,114,121,0,0,0,114, + 166,0,0,0,114,164,0,0,0,41,14,114,108,0,0,0, + 114,126,0,0,0,114,183,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,138,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,229,0,0,0,114, + 170,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,133, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,184,0,0,0,225,4,0,0,115,68,0,0,0, + 0,3,6,1,19,1,3,1,34,1,13,1,11,1,15,1, + 10,1,9,2,9,1,9,1,15,2,9,1,6,2,12,1, + 18,1,22,1,10,1,15,1,12,1,32,4,12,2,22,1, + 22,1,25,1,16,1,12,1,29,1,6,1,19,1,18,1, + 12,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, + 11,1,0,0,124,0,0,106,0,0,125,1,0,121,31,0, + 116,1,0,106,2,0,124,1,0,112,33,0,116,1,0,106, + 3,0,131,0,0,131,1,0,125,2,0,87,110,33,0,4, + 116,4,0,116,5,0,116,6,0,102,3,0,107,10,0,114, + 75,0,1,1,1,103,0,0,125,2,0,89,110,1,0,88, + 116,7,0,106,8,0,106,9,0,100,1,0,131,1,0,115, + 112,0,116,10,0,124,2,0,131,1,0,124,0,0,95,11, + 0,110,111,0,116,10,0,131,0,0,125,3,0,120,90,0, + 124,2,0,68,93,82,0,125,4,0,124,4,0,106,12,0, + 100,2,0,131,1,0,92,3,0,125,5,0,125,6,0,125, + 7,0,124,6,0,114,191,0,100,3,0,106,13,0,124,5, + 0,124,7,0,106,14,0,131,0,0,131,2,0,125,8,0, + 110,6,0,124,5,0,125,8,0,124,3,0,106,15,0,124, + 8,0,131,1,0,1,113,128,0,87,124,3,0,124,0,0, + 95,11,0,116,7,0,106,8,0,106,9,0,116,16,0,131, + 1,0,114,7,1,100,4,0,100,5,0,132,0,0,124,2, + 0,68,131,1,0,124,0,0,95,17,0,100,6,0,83,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,58,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,28,0, + 0,0,104,0,0,124,0,0,93,18,0,125,1,0,124,1, + 0,106,0,0,131,0,0,146,2,0,113,6,0,83,114,4, + 0,0,0,41,1,114,88,0,0,0,41,2,114,22,0,0, + 0,90,2,102,110,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,250,9,60,115,101,116,99,111,109,112,62,43, + 5,0,0,115,2,0,0,0,9,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,3,0, + 0,0,90,7,108,105,115,116,100,105,114,114,45,0,0,0, + 114,3,1,0,0,218,15,80,101,114,109,105,115,115,105,111, + 110,69,114,114,111,114,218,18,78,111,116,65,68,105,114,101, + 99,116,111,114,121,69,114,114,111,114,114,7,0,0,0,114, + 8,0,0,0,114,9,0,0,0,114,12,1,0,0,114,13, + 1,0,0,114,83,0,0,0,114,47,0,0,0,114,88,0, + 0,0,218,3,97,100,100,114,10,0,0,0,114,14,1,0, + 0,41,9,114,108,0,0,0,114,35,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,248, + 0,0,0,114,106,0,0,0,114,241,0,0,0,114,229,0, + 0,0,90,8,110,101,119,95,110,97,109,101,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,16,1,0,0, + 14,5,0,0,115,34,0,0,0,0,2,9,1,3,1,31, + 1,22,3,11,3,18,1,18,7,9,1,13,1,24,1,6, + 1,27,2,6,1,17,1,9,1,18,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,25,0,0,0,135,0,0, + 135,1,0,102,2,0,100,1,0,100,2,0,134,0,0,125, + 2,0,124,2,0,83,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,43,0,0,0,116,0,0,124,0, + 0,131,1,0,115,30,0,116,1,0,100,1,0,100,2,0, + 124,0,0,131,1,1,130,1,0,136,0,0,124,0,0,136, + 1,0,140,1,0,83,41,3,122,45,80,97,116,104,32,104, + 111,111,107,32,102,111,114,32,105,109,112,111,114,116,108,105, + 98,46,109,97,99,104,105,110,101,114,121,46,70,105,108,101, + 70,105,110,100,101,114,46,122,30,111,110,108,121,32,100,105, + 114,101,99,116,111,114,105,101,115,32,97,114,101,32,115,117, + 112,112,111,114,116,101,100,114,35,0,0,0,41,2,114,46, + 0,0,0,114,107,0,0,0,41,1,114,35,0,0,0,41, + 2,114,174,0,0,0,114,15,1,0,0,114,4,0,0,0, + 114,5,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,55, + 5,0,0,115,6,0,0,0,0,2,12,1,18,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,174,0, + 0,0,114,15,1,0,0,114,21,1,0,0,114,4,0,0, + 0,41,2,114,174,0,0,0,114,15,1,0,0,114,5,0, + 0,0,218,9,112,97,116,104,95,104,111,111,107,45,5,0, + 0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1,0,106,0,0, + 124,0,0,106,1,0,131,1,0,83,41,2,78,122,16,70, + 105,108,101,70,105,110,100,101,114,40,123,33,114,125,41,41, + 2,114,47,0,0,0,114,35,0,0,0,41,1,114,108,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,247,0,0,0,63,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,15,114,112,0,0,0,114,111,0, + 0,0,114,113,0,0,0,114,114,0,0,0,114,188,0,0, + 0,114,253,0,0,0,114,130,0,0,0,114,185,0,0,0, + 114,124,0,0,0,114,8,1,0,0,114,184,0,0,0,114, + 16,1,0,0,114,186,0,0,0,114,22,1,0,0,114,247, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,9,1,0,0,179,4,0,0, + 115,20,0,0,0,12,7,6,2,12,14,12,4,6,2,12, + 12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106,0,0,100,1, + 0,131,1,0,125,4,0,124,0,0,106,0,0,100,2,0, + 131,1,0,125,5,0,124,4,0,115,99,0,124,5,0,114, + 54,0,124,5,0,106,1,0,125,4,0,110,45,0,124,2, + 0,124,3,0,107,2,0,114,84,0,116,2,0,124,1,0, + 124,2,0,131,2,0,125,4,0,110,15,0,116,3,0,124, + 1,0,124,2,0,131,2,0,125,4,0,124,5,0,115,126, + 0,116,4,0,124,1,0,124,2,0,100,3,0,124,4,0, + 131,2,1,125,5,0,121,44,0,124,5,0,124,0,0,100, + 2,0,60,124,4,0,124,0,0,100,1,0,60,124,2,0, + 124,0,0,100,4,0,60,124,3,0,124,0,0,100,5,0, + 60,87,110,18,0,4,116,5,0,107,10,0,114,190,0,1, + 1,1,89,110,1,0,88,100,0,0,83,41,6,78,114,227, + 0,0,0,218,8,95,95,115,112,101,99,95,95,114,127,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, + 127,0,0,0,114,224,0,0,0,114,219,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,106,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,127, + 0,0,0,114,133,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,14,95,102,105,120,95,117,112, + 95,109,111,100,117,108,101,69,5,0,0,115,34,0,0,0, + 0,2,15,1,15,1,6,1,6,1,12,1,12,1,18,2, + 15,1,6,1,21,1,3,1,10,1,10,1,10,1,14,1, + 13,2,114,26,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,55,0,0, + 0,116,0,0,116,1,0,106,2,0,131,0,0,102,2,0, + 125,0,0,116,3,0,116,4,0,102,2,0,125,1,0,116, + 5,0,116,6,0,102,2,0,125,2,0,124,0,0,124,1, + 0,124,2,0,103,3,0,83,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,225,0, + 0,0,114,150,0,0,0,218,18,101,120,116,101,110,115,105, + 111,110,95,115,117,102,102,105,120,101,115,114,219,0,0,0, + 114,84,0,0,0,114,224,0,0,0,114,74,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,5,0,0,0,114,167, + 0,0,0,92,5,0,0,115,8,0,0,0,0,5,18,1, + 12,1,12,1,114,167,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,70, + 2,0,0,124,0,0,97,0,0,116,0,0,106,1,0,97, + 1,0,116,0,0,106,2,0,97,2,0,116,1,0,106,3, + 0,116,4,0,25,125,1,0,120,76,0,100,26,0,68,93, + 68,0,125,2,0,124,2,0,116,1,0,106,3,0,107,7, + 0,114,83,0,116,0,0,106,5,0,124,2,0,131,1,0, + 125,3,0,110,13,0,116,1,0,106,3,0,124,2,0,25, + 125,3,0,116,6,0,124,1,0,124,2,0,124,3,0,131, + 3,0,1,113,44,0,87,100,5,0,100,6,0,103,1,0, + 102,2,0,100,7,0,100,8,0,100,6,0,103,2,0,102, + 2,0,102,2,0,125,4,0,120,149,0,124,4,0,68,93, + 129,0,92,2,0,125,5,0,125,6,0,116,7,0,100,9, + 0,100,10,0,132,0,0,124,6,0,68,131,1,0,131,1, + 0,115,199,0,116,8,0,130,1,0,124,6,0,100,11,0, + 25,125,7,0,124,5,0,116,1,0,106,3,0,107,6,0, + 114,241,0,116,1,0,106,3,0,124,5,0,25,125,8,0, + 80,113,156,0,121,20,0,116,0,0,106,5,0,124,5,0, + 131,1,0,125,8,0,80,87,113,156,0,4,116,9,0,107, + 10,0,114,28,1,1,1,1,119,156,0,89,113,156,0,88, + 113,156,0,87,116,9,0,100,12,0,131,1,0,130,1,0, + 116,6,0,124,1,0,100,13,0,124,8,0,131,3,0,1, + 116,6,0,124,1,0,100,14,0,124,7,0,131,3,0,1, + 116,6,0,124,1,0,100,15,0,100,16,0,106,10,0,124, + 6,0,131,1,0,131,3,0,1,121,19,0,116,0,0,106, + 5,0,100,17,0,131,1,0,125,9,0,87,110,24,0,4, + 116,9,0,107,10,0,114,147,1,1,1,1,100,18,0,125, + 9,0,89,110,1,0,88,116,6,0,124,1,0,100,17,0, + 124,9,0,131,3,0,1,116,0,0,106,5,0,100,19,0, + 131,1,0,125,10,0,116,6,0,124,1,0,100,19,0,124, + 10,0,131,3,0,1,124,5,0,100,7,0,107,2,0,114, + 238,1,116,0,0,106,5,0,100,20,0,131,1,0,125,11, + 0,116,6,0,124,1,0,100,21,0,124,11,0,131,3,0, + 1,116,6,0,124,1,0,100,22,0,116,11,0,131,0,0, + 131,3,0,1,116,12,0,106,13,0,116,2,0,106,14,0, + 131,0,0,131,1,0,1,124,5,0,100,7,0,107,2,0, + 114,66,2,116,15,0,106,16,0,100,23,0,131,1,0,1, + 100,24,0,116,12,0,107,6,0,114,66,2,100,25,0,116, + 17,0,95,18,0,100,18,0,83,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,49,0,0,0,114, + 60,0,0,0,218,8,98,117,105,108,116,105,110,115,114,147, + 0,0,0,90,5,112,111,115,105,120,250,1,47,218,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,33,0,0,0,124,0, + 0,93,23,0,125,1,0,116,0,0,124,1,0,131,1,0, + 100,0,0,107,2,0,86,1,113,3,0,100,1,0,83,41, + 2,114,29,0,0,0,78,41,1,114,31,0,0,0,41,2, + 114,22,0,0,0,114,77,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,231,0,0,0,128,5, + 0,0,115,2,0,0,0,6,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,59,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,25, + 0,0,0,114,21,0,0,0,114,30,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,173,0,0,0,114,6, + 0,0,0,122,4,46,112,121,119,122,6,95,100,46,112,121, + 100,84,41,4,122,3,95,105,111,122,9,95,119,97,114,110, + 105,110,103,115,122,8,98,117,105,108,116,105,110,115,122,7, + 109,97,114,115,104,97,108,41,19,114,121,0,0,0,114,7, + 0,0,0,114,150,0,0,0,114,132,0,0,0,114,112,0, + 0,0,90,18,95,98,117,105,108,116,105,110,95,102,114,111, + 109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0,0,0,114, + 233,0,0,0,114,154,0,0,0,114,27,1,0,0,114,84, + 0,0,0,114,169,0,0,0,114,172,0,0,0,114,177,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,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,6,95,115, + 101,116,117,112,103,5,0,0,115,82,0,0,0,0,8,6, + 1,9,1,9,3,13,1,13,1,15,1,18,2,13,1,20, + 3,33,1,19,2,31,1,10,1,15,1,13,1,4,2,3, + 1,15,1,5,1,13,1,12,2,12,1,16,1,16,1,25, + 3,3,1,19,1,13,2,11,1,16,3,15,1,16,3,12, + 1,15,1,16,3,19,1,19,1,12,1,13,1,12,1,114, + 35,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,116,0,0,0,116,0, + 0,124,0,0,131,1,0,1,116,1,0,131,0,0,125,1, + 0,116,2,0,106,3,0,106,4,0,116,5,0,106,6,0, + 124,1,0,140,0,0,103,1,0,131,1,0,1,116,7,0, + 106,8,0,100,1,0,107,2,0,114,78,0,116,2,0,106, + 9,0,106,10,0,116,11,0,131,1,0,1,116,2,0,106, + 9,0,106,10,0,116,12,0,131,1,0,1,116,5,0,124, + 0,0,95,5,0,116,13,0,124,0,0,95,13,0,100,2, + 0,83,41,3,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,114, + 30,1,0,0,78,41,14,114,35,1,0,0,114,167,0,0, + 0,114,7,0,0,0,114,1,1,0,0,114,154,0,0,0, + 114,9,1,0,0,114,22,1,0,0,114,3,0,0,0,114, + 112,0,0,0,218,9,109,101,116,97,95,112,97,116,104,114, + 169,0,0,0,114,172,0,0,0,114,252,0,0,0,114,219, + 0,0,0,41,2,114,34,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,5,0,0,0,218,8,95,105, + 110,115,116,97,108,108,171,5,0,0,115,16,0,0,0,0, + 2,10,1,9,1,28,1,15,1,16,1,16,4,9,1,114, + 37,1,0,0,41,3,122,3,119,105,110,114,1,0,0,0, + 114,2,0,0,0,41,59,114,114,0,0,0,114,10,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,55, + 0,0,0,218,4,116,121,112,101,218,8,95,95,99,111,100, + 101,95,95,114,149,0,0,0,114,15,0,0,0,114,140,0, + 0,0,114,14,0,0,0,114,18,0,0,0,90,17,95,82, + 65,87,95,77,65,71,73,67,95,78,85,77,66,69,82,114, + 73,0,0,0,114,72,0,0,0,114,84,0,0,0,114,74, + 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,79,0,0,0,114,85, + 0,0,0,114,91,0,0,0,114,95,0,0,0,114,97,0, + 0,0,114,105,0,0,0,114,123,0,0,0,114,130,0,0, + 0,114,135,0,0,0,114,146,0,0,0,114,152,0,0,0, + 114,155,0,0,0,114,160,0,0,0,114,131,0,0,0,218, + 6,111,98,106,101,99,116,114,168,0,0,0,114,165,0,0, + 0,114,172,0,0,0,114,187,0,0,0,114,195,0,0,0, + 114,211,0,0,0,114,219,0,0,0,114,224,0,0,0,114, + 233,0,0,0,114,225,0,0,0,114,234,0,0,0,114,250, + 0,0,0,114,252,0,0,0,114,9,1,0,0,114,26,1, + 0,0,114,167,0,0,0,114,35,1,0,0,114,37,1,0, + 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,8,60,109,111,100,117,108,101,62,8, + 0,0,0,115,104,0,0,0,6,17,6,3,12,12,12,5, + 12,5,12,6,12,12,12,10,12,9,12,5,12,7,15,22, + 15,108,22,1,18,2,6,1,6,2,9,2,9,2,10,2, + 21,44,12,33,12,19,12,12,12,12,18,8,12,27,12,18, + 12,15,21,55,21,12,18,10,12,14,24,22,9,3,12,1, + 15,65,19,63,19,27,22,110,19,41,25,43,25,16,6,3, + 19,57,19,57,19,41,19,134,19,146,15,23,12,11,12,68, }; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -148,11 +148,11 @@ &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_BUILD_LIST_UNPACK, + &&TARGET_BUILD_MAP_UNPACK, + &&TARGET_BUILD_MAP_UNPACK_WITH_CALL, + &&TARGET_BUILD_TUPLE_UNPACK, + &&TARGET_BUILD_SET_UNPACK, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1083,13 +1083,13 @@ } \ } -#define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \ +#define VISIT_SEQ_WITH_NULL(ST, TYPE, SEQ) { \ int i = 0; \ - asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ + asdl_seq *seq = (SEQ); /* avoid variable capture */ \ for (i = 0; i < asdl_seq_LEN(seq); i++) { \ - expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ + TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!elt) continue; /* can be NULL */ \ - if (!symtable_visit_expr((ST), elt)) \ + if (!symtable_visit_ ## TYPE((ST), elt)) \ VISIT_QUIT((ST), 0); \ } \ } @@ -1146,8 +1146,7 @@ if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) - VISIT_KWONLYDEFAULTS(st, - s->v.FunctionDef.args->kw_defaults); + VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults); if (!symtable_visit_annotations(st, s)) VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) @@ -1167,10 +1166,6 @@ VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); - if (s->v.ClassDef.starargs) - VISIT(st, expr, s->v.ClassDef.starargs); - if (s->v.ClassDef.kwargs) - VISIT(st, expr, s->v.ClassDef.kwargs); if (s->v.ClassDef.decorator_list) VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, @@ -1349,8 +1344,7 @@ if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) - VISIT_KWONLYDEFAULTS(st, - e->v.Lambda.args->kw_defaults); + VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults); if (!symtable_enter_block(st, lambda, FunctionBlock, (void *)e, e->lineno, e->col_offset)) @@ -1367,7 +1361,7 @@ VISIT(st, expr, e->v.IfExp.orelse); break; case Dict_kind: - VISIT_SEQ(st, expr, e->v.Dict.keys); + VISIT_SEQ_WITH_NULL(st, expr, e->v.Dict.keys); VISIT_SEQ(st, expr, e->v.Dict.values); break; case Set_kind: @@ -1405,11 +1399,7 @@ case Call_kind: VISIT(st, expr, e->v.Call.func); VISIT_SEQ(st, expr, e->v.Call.args); - VISIT_SEQ(st, keyword, e->v.Call.keywords); - if (e->v.Call.starargs) - VISIT(st, expr, e->v.Call.starargs); - if (e->v.Call.kwargs) - VISIT(st, expr, e->v.Call.kwargs); + VISIT_SEQ_WITH_NULL(st, keyword, e->v.Call.keywords); break; case Num_kind: case Str_kind: diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -211,16 +211,6 @@ if comma: self.write(", ") else: comma = True self.dispatch(e) - if t.starargs: - if comma: self.write(", ") - else: comma = True - self.write("*") - self.dispatch(t.starargs) - if t.kwargs: - if comma: self.write(", ") - else: comma = True - self.write("**") - self.dispatch(t.kwargs) self.write(")") self.enter() @@ -450,16 +440,6 @@ if comma: self.write(", ") else: comma = True self.dispatch(e) - if t.starargs: - if comma: self.write(", ") - else: comma = True - self.write("*") - self.dispatch(t.starargs) - if t.kwargs: - if comma: self.write(", ") - else: comma = True - self.write("**") - self.dispatch(t.kwargs) self.write(")") def _Subscript(self, t): @@ -543,8 +523,11 @@ self.dispatch(t.kwarg.annotation) def _keyword(self, t): - self.write(t.arg) - self.write("=") + if t.arg is None: + self.write("**") + else: + self.write(t.arg) + self.write("=") self.dispatch(t.value) def _Lambda(self, t): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 02:17:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 06 May 2015 00:17:54 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_448_is_done?= Message-ID: <20150506001754.1917.23605@psf.io> https://hg.python.org/peps/rev/2977ff310152 changeset: 5827:2977ff310152 user: Benjamin Peterson date: Tue May 05 20:17:53 2015 -0400 summary: 448 is done files: pep-0448.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0448.txt b/pep-0448.txt --- a/pep-0448.txt +++ b/pep-0448.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Joshua Landau Discussions-To: python-ideas at python.org -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 29-Jun-2013 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 02:23:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 06 May 2015 00:23:35 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Mark_the_PEP_as_A?= =?utf-8?q?ccepted=2E?= Message-ID: <20150506002334.14354.64234@psf.io> https://hg.python.org/peps/rev/f3bc743013db changeset: 5828:f3bc743013db user: Yury Selivanov date: Tue May 05 20:23:31 2015 -0400 summary: pep-0492: Mark the PEP as Accepted. files: pep-0492.txt | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Yury Selivanov -Status: Draft +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 09-Apr-2015 @@ -1357,6 +1357,14 @@ loop.close() +Acceptance +========== + +PEP 492 was accepted by Guido, Tuesday, May 5, 2015 [14]_. + +The reference implementation is tracked in issue 24017 [15]_. + + References ========== @@ -1384,6 +1392,11 @@ .. [12] https://docs.python.org/3/reference/expressions.html#primaries +.. [14] https://mail.python.org/pipermail/python-dev/2015-May/139844.html + +.. [15] http://bugs.python.org/issue24017 + + Acknowledgments =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 02:25:17 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 06 May 2015 00:25:17 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Mention_PEP_0492_?= =?utf-8?q?in_=22Accepted_PEPs=22?= Message-ID: <20150506002515.84486.61679@psf.io> https://hg.python.org/peps/rev/2340fd0b393f changeset: 5829:2340fd0b393f user: Yury Selivanov date: Tue May 05 20:25:12 2015 -0400 summary: pep-0478: Mention PEP 0492 in "Accepted PEPs" files: pep-0478.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -68,6 +68,7 @@ * PEP 475, retrying system calls that fail with EINTR * PEP 485, math.isclose(), a function for testing approximate equality * PEP 486, make the Python Launcher aware of virtual environments +* PEP 492, coroutines with async and await syntax Proposed changes for 3.5: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 02:39:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 06 May 2015 00:39:24 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Update_Acknowledg?= =?utf-8?q?ments_section=2E?= Message-ID: <20150506003924.8157.84563@psf.io> https://hg.python.org/peps/rev/f0b8cfe0eb7a changeset: 5830:f0b8cfe0eb7a user: Yury Selivanov date: Tue May 05 20:39:22 2015 -0400 summary: pep-0492: Update Acknowledgments section. files: pep-0492.txt | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1401,7 +1401,11 @@ =============== I thank Guido van Rossum, Victor Stinner, Elvis Pranskevichus, Andrew -Svetlov, and ?ukasz Langa for their initial feedback. +Svetlov, ?ukasz Langa, Greg Ewing, Stephen J. Turnbull, Jim J. Jewett, +Brett Cannon, Nick Coghlan, Steven D'Aprano, Paul Moore, Nathaniel +Smith, Ethan Furman, Stefan Behnel, Paul Sokolovsky, Victor Petrovykh, +and many others for their feedback, ideas, edits, criticism, and +discussions around this PEP. Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 02:57:06 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 06 May 2015 00:57:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_=22unexpected?= =?utf-8?q?_indentation=22_error?= Message-ID: <20150506005706.11924.71248@psf.io> https://hg.python.org/peps/rev/ee325bf8d9b9 changeset: 5831:ee325bf8d9b9 user: Yury Selivanov date: Tue May 05 20:57:03 2015 -0400 summary: pep-0492: Fix "unexpected indentation" error files: pep-0492.txt | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -9,8 +9,7 @@ Created: 09-Apr-2015 Python-Version: 3.5 Discussions-To: -Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, - 05-May-2015 +Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, 05-May-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 03:50:31 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 06 May 2015 01:50:31 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_492=3A_Sort_headers?= Message-ID: <20150506015031.14374.97474@psf.io> https://hg.python.org/peps/rev/d329de33bc12 changeset: 5832:d329de33bc12 user: Berker Peksag date: Wed May 06 04:51:00 2015 +0300 summary: PEP 492: Sort headers files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -3,12 +3,12 @@ Version: $Revision$ Last-Modified: $Date$ Author: Yury Selivanov +Discussions-To: Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 -Discussions-To: Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015, 05-May-2015 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 6 05:29:41 2015 From: python-checkins at python.org (eric.snow) Date: Wed, 06 May 2015 03:29:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_an_unnecessary_flag?= =?utf-8?q?=2E?= Message-ID: <20150506032941.1939.27268@psf.io> https://hg.python.org/cpython/rev/3bea670c9830 changeset: 95887:3bea670c9830 user: Eric Snow date: Tue May 05 21:29:31 2015 -0600 summary: Remove an unnecessary flag. files: Programs/_freeze_importlib.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -12,8 +12,6 @@ #include #endif -int Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ - /* To avoid a circular dependency on frozen.o, we create our own structure of frozen modules instead, left deliberately blank so as to avoid unintentional import of a stale version of _frozen_importlib. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 05:36:51 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 06 May 2015 03:36:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=239517=3A_Move_scri?= =?utf-8?q?pt=5Fhelper_to_the_support_package=2E?= Message-ID: <20150506033651.1924.45144@psf.io> https://hg.python.org/cpython/rev/f65174aef9ea changeset: 95888:f65174aef9ea parent: 95886:a65f685ba8c0 user: Berker Peksag date: Wed May 06 06:33:17 2015 +0300 summary: Issue #9517: Move script_helper to the support package. Patch by Christie Wilson. files: Lib/test/script_helper.py | 0 Lib/test/test_asyncio/test_base_events.py | 2 +- Lib/test/test_asyncio/test_tasks.py | 2 +- Lib/test/test_builtin.py | 2 +- Lib/test/test_calendar.py | 2 +- Lib/test/test_capi.py | 2 +- Lib/test/test_cgitb.py | 3 +- Lib/test/test_cmd_line.py | 6 +- Lib/test/test_cmd_line_script.py | 47 ++++----- Lib/test/test_compileall.py | 3 +- Lib/test/test_concurrent_futures.py | 2 +- Lib/test/test_crashers.py | 2 +- Lib/test/test_doctest.py | 8 +- Lib/test/test_eintr.py | 3 +- Lib/test/test_faulthandler.py | 4 +- Lib/test/test_gc.py | 5 +- Lib/test/test_hash.py | 2 +- Lib/test/test_import/__init__.py | 7 +- Lib/test/test_inspect.py | 2 +- Lib/test/test_io.py | 2 +- Lib/test/test_json/test_tool.py | 2 +- Lib/test/test_logging.py | 2 +- Lib/test/test_module.py | 2 +- Lib/test/test_multiprocessing_main_handling.py | 31 +++--- Lib/test/test_os.py | 2 +- Lib/test/test_parser.py | 2 +- Lib/test/test_pydoc.py | 2 +- Lib/test/test_readline.py | 2 +- Lib/test/test_runpy.py | 6 +- Lib/test/test_script_helper.py | 4 +- Lib/test/test_signal.py | 2 +- Lib/test/test_subprocess.py | 4 +- Lib/test/test_sys.py | 4 +- Lib/test/test_tarfile.py | 3 +- Lib/test/test_tempfile.py | 3 +- Lib/test/test_threading.py | 2 +- Lib/test/test_tools/test_md5sum.py | 2 +- Lib/test/test_tools/test_pindent.py | 2 +- Lib/test/test_tools/test_reindent.py | 2 +- Lib/test/test_traceback.py | 2 +- Lib/test/test_tracemalloc.py | 7 +- Lib/test/test_warnings.py | 2 +- Lib/test/test_weakref.py | 3 +- Lib/test/test_zipimport_support.py | 12 +- Misc/NEWS | 6 + 45 files changed, 115 insertions(+), 102 deletions(-) diff --git a/Lib/test/script_helper.py b/Lib/test/support/script_helper.py rename from Lib/test/script_helper.py rename to Lib/test/support/script_helper.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -16,7 +16,7 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support from asyncio.test_support import assert_python_ok diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -15,7 +15,7 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support from asyncio.test_support import assert_python_ok diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -16,7 +16,7 @@ import warnings from operator import neg from test.support import TESTFN, unlink, run_unittest, check_warnings -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok try: import pty, signal except ImportError: diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -2,7 +2,7 @@ import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import time import locale import sys diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -11,7 +11,7 @@ import unittest from test import support from test.support import MISSING_C_DOCSTRINGS -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure try: import _posixsubprocess except ImportError: diff --git a/Lib/test/test_cgitb.py b/Lib/test/test_cgitb.py --- a/Lib/test/test_cgitb.py +++ b/Lib/test/test_cgitb.py @@ -1,4 +1,5 @@ -from test.script_helper import assert_python_failure, temp_dir +from test.support import temp_dir +from test.support.script_helper import assert_python_failure import unittest import sys import cgitb diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -8,8 +8,8 @@ import sys import subprocess import tempfile -from test import script_helper -from test.script_helper import (spawn_python, kill_python, assert_python_ok, +from test.support import script_helper +from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, assert_python_failure) @@ -59,7 +59,7 @@ def test_xoptions(self): def get_xoptions(*args): - # use subprocess module directly because test.script_helper adds + # use subprocess module directly because test.support.script_helper adds # "-X faulthandler" to the command line args = (sys.executable, '-E') + args args += ('-c', 'import sys; print(sys._xoptions)') diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -13,10 +13,9 @@ import textwrap from test import support -from test.script_helper import ( +from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, - assert_python_ok, assert_python_failure, temp_dir, - spawn_python, kill_python) + assert_python_ok, assert_python_failure, spawn_python, kill_python) verbose = support.verbose @@ -223,14 +222,14 @@ self.check_repl_stderr_flush(True) def test_basic_script(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') self._check_script(script_name, script_name, script_name, script_dir, None, importlib.machinery.SourceFileLoader) def test_script_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -240,14 +239,14 @@ importlib.machinery.SourcelessFileLoader) def test_directory(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') self._check_script(script_dir, script_name, script_dir, script_dir, '', importlib.machinery.SourceFileLoader) def test_directory_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -257,19 +256,19 @@ importlib.machinery.SourcelessFileLoader) def test_directory_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) def test_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) def test_zipfile_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') compiled_name = py_compile.compile(script_name, doraise=True) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) @@ -277,14 +276,14 @@ zipimport.zipimporter) def test_zipfile_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'not_main') zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) msg = "can't find '__main__' module in %r" % zip_name self._check_import_error(zip_name, msg) def test_module_in_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, 'script') @@ -294,14 +293,14 @@ importlib.machinery.SourceFileLoader) def test_module_in_package_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name) self._check_script(launch_name, run_name, run_name, zip_name, 'test_pkg', zipimport.zipimporter) def test_module_in_subpackage_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2) launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) self._check_script(launch_name, run_name, run_name, @@ -309,7 +308,7 @@ zipimport.zipimporter) def test_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__') @@ -319,7 +318,7 @@ importlib.machinery.SourceFileLoader) def test_package_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__') @@ -332,7 +331,7 @@ importlib.machinery.SourcelessFileLoader) def test_package_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) msg = ("'test_pkg' is a package and cannot " @@ -341,7 +340,7 @@ self._check_import_error(launch_name, msg) def test_package_recursion(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) main_dir = os.path.join(pkg_dir, '__main__') @@ -355,7 +354,7 @@ def test_issue8202(self): # Make sure package __init__ modules see "-m" in sys.argv0 while # searching for the module to execute - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") @@ -372,7 +371,7 @@ def test_issue8202_dash_c_file_ignored(self): # Make sure a "-c" file in the current directory # does not alter the value of sys.path[0] - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): with open("-c", "w") as f: f.write("data") @@ -387,7 +386,7 @@ def test_issue8202_dash_m_file_ignored(self): # Make sure a "-m" file in the current directory # does not alter the value of sys.path[0] - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'other') with support.change_cwd(path=script_dir): with open("-m", "w") as f: @@ -402,7 +401,7 @@ # If a module is invoked with the -m command line flag # and results in an error that the return code to the # shell is '1' - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) @@ -422,7 +421,7 @@ except: raise NameError from None """) - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', script) exitcode, stdout, stderr = assert_python_failure(script_name) text = stderr.decode('ascii').split('\n') @@ -466,7 +465,7 @@ if error: sys.exit(error) """) - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', script) exitcode, stdout, stderr = assert_python_failure(script_name) text = stderr.decode('ascii') diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -17,7 +17,8 @@ except ImportError: _have_multiprocessing = False -from test import support, script_helper +from test import support +from test.support import script_helper class CompileallTests(unittest.TestCase): diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -9,7 +9,7 @@ # without thread support. test.support.import_module('threading') -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import os import sys diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers.py --- a/Lib/test/test_crashers.py +++ b/Lib/test/test_crashers.py @@ -8,7 +8,7 @@ import glob import os.path import test.support -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers") CRASHER_FILES = os.path.join(CRASHER_DIR, "*.py") diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2729,8 +2729,8 @@ simple tests and no errors. We'll run both the unadorned doctest command, and the verbose version, and then check the output: - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is a very simple test file.\n') @@ -2780,8 +2780,8 @@ file ends in '.py', its handling of python module files (as opposed to straight text files). - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is another simple test file.\n') diff --git a/Lib/test/test_eintr.py b/Lib/test/test_eintr.py --- a/Lib/test/test_eintr.py +++ b/Lib/test/test_eintr.py @@ -2,7 +2,8 @@ import signal import unittest -from test import script_helper, support +from test import support +from test.support import script_helper @unittest.skipUnless(os.name == "posix", "only supported on Unix") diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -6,8 +6,8 @@ import signal import subprocess import sys -from test import support, script_helper -from test.script_helper import assert_python_ok +from test import support +from test.support import script_helper import tempfile import unittest from textwrap import dedent diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,7 +1,8 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr, cpython_only, start_threads) -from test.script_helper import assert_python_ok, make_script, temp_dir + strip_python_stderr, cpython_only, start_threads, + temp_dir) +from test.support.script_helper import assert_python_ok, make_script import sys import time diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -7,7 +7,7 @@ import os import sys import unittest -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from collections import Hashable IS_64BIT = sys.maxsize > 2**32 diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -21,8 +21,9 @@ from test.support import ( EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython, make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask, - unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE) -from test import script_helper + unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE, + temp_dir) +from test.support import script_helper skip_if_dont_write_bytecode = unittest.skipIf( @@ -45,7 +46,7 @@ # temporarily clears the module from sys.modules (if any) # reverts or removes the module when cleaning up name = name or "spam" - with script_helper.temp_dir() as tempdir: + with temp_dir() as tempdir: path = script_helper.make_script(tempdir, name, source) old_module = sys.modules.pop(name, None) try: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -26,7 +26,7 @@ from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only from test.support import MISSING_C_DOCSTRINGS, cpython_only -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test import inspect_fodder as mod from test import inspect_fodder2 as mod2 diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -35,7 +35,7 @@ from collections import deque, UserList from itertools import cycle, count from test import support -from test.script_helper import assert_python_ok, run_python_until_end +from test.support.script_helper import assert_python_ok, run_python_until_end import codecs import io # C implementation of io diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -4,7 +4,7 @@ import unittest import subprocess from test import support -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok class TestTool(unittest.TestCase): diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -38,7 +38,7 @@ import struct import sys import tempfile -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test import support import textwrap import time diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py --- a/Lib/test/test_module.py +++ b/Lib/test/test_module.py @@ -2,7 +2,7 @@ import unittest import weakref from test.support import gc_collect -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import sys ModuleType = type(sys) diff --git a/Lib/test/test_multiprocessing_main_handling.py b/Lib/test/test_multiprocessing_main_handling.py --- a/Lib/test/test_multiprocessing_main_handling.py +++ b/Lib/test/test_multiprocessing_main_handling.py @@ -13,10 +13,9 @@ import os.path import py_compile -from test.script_helper import ( +from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, - assert_python_ok, assert_python_failure, temp_dir, - spawn_python, kill_python) + assert_python_ok, assert_python_failure, spawn_python, kill_python) # Look up which start methods are available to test import multiprocessing @@ -157,12 +156,12 @@ self._check_output(script_name, rc, out, err) def test_basic_script(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') self._check_script(script_name) def test_basic_script_no_suffix(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', omit_suffix=True) self._check_script(script_name) @@ -173,7 +172,7 @@ # a workaround for that case # See https://github.com/ipython/ipython/issues/4698 source = test_source_main_skipped_in_children - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'ipython', source=source) self._check_script(script_name) @@ -183,7 +182,7 @@ self._check_script(script_no_suffix) def test_script_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -192,14 +191,14 @@ def test_directory(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) self._check_script(script_dir) def test_directory_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) py_compile.compile(script_name, doraise=True) @@ -209,7 +208,7 @@ def test_zipfile(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) @@ -217,7 +216,7 @@ def test_zipfile_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) compiled_name = py_compile.compile(script_name, doraise=True) @@ -225,7 +224,7 @@ self._check_script(zip_name) def test_module_in_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, 'check_sibling') @@ -234,20 +233,20 @@ self._check_script(launch_name) def test_module_in_package_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name) self._check_script(launch_name) def test_module_in_subpackage_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2) launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) self._check_script(launch_name) def test_package(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__', @@ -257,7 +256,7 @@ def test_package_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__', diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -64,7 +64,7 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok root_in_posix = False if hasattr(os, 'geteuid'): diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -4,7 +4,7 @@ import operator import struct from test import support -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -21,7 +21,7 @@ import textwrap from io import StringIO from collections import namedtuple -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.support import ( TESTFN, rmtree, reap_children, reap_threads, captured_output, captured_stdout, diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -5,7 +5,7 @@ import tempfile import unittest from test.support import import_module, unlink -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok # Skip tests if there is no readline module readline = import_module('readline') diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -9,9 +9,9 @@ import py_compile from test.support import ( forget, make_legacy_pyc, unload, verbose, no_tracing, - create_empty_file) -from test.script_helper import ( - make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir) + create_empty_file, temp_dir) +from test.support.script_helper import ( + make_pkg, make_script, make_zip_pkg, make_zip_script) import runpy diff --git a/Lib/test/test_script_helper.py b/Lib/test/test_script_helper.py --- a/Lib/test/test_script_helper.py +++ b/Lib/test/test_script_helper.py @@ -1,8 +1,8 @@ -"""Unittests for test.script_helper. Who tests the test helper?""" +"""Unittests for test.support.script_helper. Who tests the test helper?""" import subprocess import sys -from test import script_helper +from test.support import script_helper import unittest from unittest import mock diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -11,7 +11,7 @@ import subprocess import traceback import sys, os, time, errno -from test.script_helper import assert_python_ok, spawn_python +from test.support.script_helper import assert_python_ok, spawn_python try: import threading except ImportError: diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1,5 +1,5 @@ import unittest -from test import script_helper +from test.support import script_helper from test import support import subprocess import sys @@ -394,7 +394,7 @@ python_dir, python_base = self._split_python_path() abs_python = os.path.join(python_dir, python_base) rel_python = os.path.join(os.curdir, python_base) - with script_helper.temp_dir() as wrong_dir: + with support.temp_dir() as wrong_dir: # Before calling with an absolute path, confirm that using a # relative path fails. self.assertRaises(FileNotFoundError, subprocess.Popen, diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,5 +1,5 @@ import unittest, test.support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct import subprocess @@ -708,7 +708,7 @@ @test.support.cpython_only def test_debugmallocstats(self): # Test sys._debugmallocstats() - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok args = ['-c', 'import sys; sys._debugmallocstats()'] ret, out, err = assert_python_ok(*args) self.assertIn(b"free PyDictObjects", err) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -8,7 +8,8 @@ import unittest.mock import tarfile -from test import support, script_helper +from test import support +from test.support import script_helper # Check for our compression modules. try: diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -12,7 +12,8 @@ from unittest import mock import unittest -from test import support, script_helper +from test import support +from test.support import script_helper if hasattr(os, 'stat'): diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -4,7 +4,7 @@ import test.support from test.support import verbose, strip_python_stderr, import_module, cpython_only -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import random import re diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py --- a/Lib/test/test_tools/test_md5sum.py +++ b/Lib/test/test_tools/test_md5sum.py @@ -4,7 +4,7 @@ import sys import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test.test_tools import scriptsdir, import_tool, skip_if_missing diff --git a/Lib/test/test_tools/test_pindent.py b/Lib/test/test_tools/test_pindent.py --- a/Lib/test/test_tools/test_pindent.py +++ b/Lib/test/test_tools/test_pindent.py @@ -6,7 +6,7 @@ import subprocess import textwrap from test import support -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.test_tools import scriptsdir, skip_if_missing diff --git a/Lib/test/test_tools/test_reindent.py b/Lib/test/test_tools/test_reindent.py --- a/Lib/test/test_tools/test_reindent.py +++ b/Lib/test/test_tools/test_reindent.py @@ -6,7 +6,7 @@ import os import unittest -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.test_tools import scriptsdir, skip_if_missing diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -8,7 +8,7 @@ import re from test import support from test.support import TESTFN, Error, captured_output, unlink, cpython_only -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import textwrap import traceback diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -4,8 +4,9 @@ import tracemalloc import unittest from unittest.mock import patch -from test.script_helper import assert_python_ok, assert_python_failure -from test import script_helper, support +from test.support.script_helper import (assert_python_ok, assert_python_failure, + interpreter_requires_environment) +from test import support try: import threading except ImportError: @@ -751,7 +752,7 @@ stdout = stdout.rstrip() self.assertEqual(stdout, b'False') - @unittest.skipIf(script_helper.interpreter_requires_environment(), + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -E tests when PYTHON env vars are required.') def test_env_var_ignored_with_E(self): """PYTHON* environment variables must be ignored when -E is present.""" diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -5,7 +5,7 @@ import sys import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test import warning_tests diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -7,7 +7,8 @@ import contextlib import copy -from test import support, script_helper +from test import support +from test.support import script_helper # Used in ReferencesTestCase.test_ref_created_during_del() . ref_from_del = None diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -14,8 +14,8 @@ import linecache import pdb import unittest -from test.script_helper import (spawn_python, kill_python, assert_python_ok, - temp_dir, make_script, make_zip_script) +from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, + make_script, make_zip_script) verbose = test.support.verbose @@ -78,7 +78,7 @@ def test_inspect_getsource_issue4223(self): test_src = "def foo(): pass\n" - with temp_dir() as d: + with test.support.temp_dir() as d: init_name = make_script(d, '__init__', test_src) name_in_zip = os.path.join('zip_pkg', os.path.basename(init_name)) @@ -118,7 +118,7 @@ mod_name = mod_name.replace("sample_", "sample_zipped_") sample_sources[mod_name] = src - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', @@ -195,7 +195,7 @@ doctest.testmod() """) pattern = 'File "%s", line 2, in %s' - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) rc, out, err = assert_python_ok(script_name) expected = pattern % (script_name, "__main__.Test") @@ -222,7 +222,7 @@ import pdb pdb.Pdb(nosigint=True).runcall(f) """) - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) p = spawn_python(script_name) p.stdin.write(b'l\n') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,12 @@ - Issue #23887: urllib.error.HTTPError now has a proper repr() representation. Patch by Berker Peksag. +Tests +----- + +- Issue #9517: Move script_helper into the support package. + Patch by Christie Wilson. + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 05:36:52 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 06 May 2015 03:36:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgaGVhZHMu?= Message-ID: <20150506033652.14364.66507@psf.io> https://hg.python.org/cpython/rev/058a6c1a7ee2 changeset: 95889:058a6c1a7ee2 parent: 95887:3bea670c9830 parent: 95888:f65174aef9ea user: Berker Peksag date: Wed May 06 06:36:29 2015 +0300 summary: Merge heads. files: Lib/test/script_helper.py | 0 Lib/test/test_asyncio/test_base_events.py | 2 +- Lib/test/test_asyncio/test_tasks.py | 2 +- Lib/test/test_builtin.py | 2 +- Lib/test/test_calendar.py | 2 +- Lib/test/test_capi.py | 2 +- Lib/test/test_cgitb.py | 3 +- Lib/test/test_cmd_line.py | 6 +- Lib/test/test_cmd_line_script.py | 47 ++++----- Lib/test/test_compileall.py | 3 +- Lib/test/test_concurrent_futures.py | 2 +- Lib/test/test_crashers.py | 2 +- Lib/test/test_doctest.py | 8 +- Lib/test/test_eintr.py | 3 +- Lib/test/test_faulthandler.py | 4 +- Lib/test/test_gc.py | 5 +- Lib/test/test_hash.py | 2 +- Lib/test/test_import/__init__.py | 7 +- Lib/test/test_inspect.py | 2 +- Lib/test/test_io.py | 2 +- Lib/test/test_json/test_tool.py | 2 +- Lib/test/test_logging.py | 2 +- Lib/test/test_module.py | 2 +- Lib/test/test_multiprocessing_main_handling.py | 31 +++--- Lib/test/test_os.py | 2 +- Lib/test/test_parser.py | 2 +- Lib/test/test_pydoc.py | 2 +- Lib/test/test_readline.py | 2 +- Lib/test/test_runpy.py | 6 +- Lib/test/test_script_helper.py | 4 +- Lib/test/test_signal.py | 2 +- Lib/test/test_subprocess.py | 4 +- Lib/test/test_sys.py | 4 +- Lib/test/test_tarfile.py | 3 +- Lib/test/test_tempfile.py | 3 +- Lib/test/test_threading.py | 2 +- Lib/test/test_tools/test_md5sum.py | 2 +- Lib/test/test_tools/test_pindent.py | 2 +- Lib/test/test_tools/test_reindent.py | 2 +- Lib/test/test_traceback.py | 2 +- Lib/test/test_tracemalloc.py | 7 +- Lib/test/test_warnings.py | 2 +- Lib/test/test_weakref.py | 3 +- Lib/test/test_zipimport_support.py | 12 +- Misc/NEWS | 6 + 45 files changed, 115 insertions(+), 102 deletions(-) diff --git a/Lib/test/script_helper.py b/Lib/test/support/script_helper.py rename from Lib/test/script_helper.py rename to Lib/test/support/script_helper.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -16,7 +16,7 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support from asyncio.test_support import assert_python_ok diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -15,7 +15,7 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support from asyncio.test_support import assert_python_ok diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -16,7 +16,7 @@ import warnings from operator import neg from test.support import TESTFN, unlink, run_unittest, check_warnings -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok try: import pty, signal except ImportError: diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -2,7 +2,7 @@ import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import time import locale import sys diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -11,7 +11,7 @@ import unittest from test import support from test.support import MISSING_C_DOCSTRINGS -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure try: import _posixsubprocess except ImportError: diff --git a/Lib/test/test_cgitb.py b/Lib/test/test_cgitb.py --- a/Lib/test/test_cgitb.py +++ b/Lib/test/test_cgitb.py @@ -1,4 +1,5 @@ -from test.script_helper import assert_python_failure, temp_dir +from test.support import temp_dir +from test.support.script_helper import assert_python_failure import unittest import sys import cgitb diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -8,8 +8,8 @@ import sys import subprocess import tempfile -from test import script_helper -from test.script_helper import (spawn_python, kill_python, assert_python_ok, +from test.support import script_helper +from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, assert_python_failure) @@ -59,7 +59,7 @@ def test_xoptions(self): def get_xoptions(*args): - # use subprocess module directly because test.script_helper adds + # use subprocess module directly because test.support.script_helper adds # "-X faulthandler" to the command line args = (sys.executable, '-E') + args args += ('-c', 'import sys; print(sys._xoptions)') diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -13,10 +13,9 @@ import textwrap from test import support -from test.script_helper import ( +from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, - assert_python_ok, assert_python_failure, temp_dir, - spawn_python, kill_python) + assert_python_ok, assert_python_failure, spawn_python, kill_python) verbose = support.verbose @@ -223,14 +222,14 @@ self.check_repl_stderr_flush(True) def test_basic_script(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') self._check_script(script_name, script_name, script_name, script_dir, None, importlib.machinery.SourceFileLoader) def test_script_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -240,14 +239,14 @@ importlib.machinery.SourcelessFileLoader) def test_directory(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') self._check_script(script_dir, script_name, script_dir, script_dir, '', importlib.machinery.SourceFileLoader) def test_directory_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -257,19 +256,19 @@ importlib.machinery.SourcelessFileLoader) def test_directory_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) def test_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) def test_zipfile_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') compiled_name = py_compile.compile(script_name, doraise=True) zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) @@ -277,14 +276,14 @@ zipimport.zipimporter) def test_zipfile_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'not_main') zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) msg = "can't find '__main__' module in %r" % zip_name self._check_import_error(zip_name, msg) def test_module_in_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, 'script') @@ -294,14 +293,14 @@ importlib.machinery.SourceFileLoader) def test_module_in_package_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name) self._check_script(launch_name, run_name, run_name, zip_name, 'test_pkg', zipimport.zipimporter) def test_module_in_subpackage_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2) launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) self._check_script(launch_name, run_name, run_name, @@ -309,7 +308,7 @@ zipimport.zipimporter) def test_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__') @@ -319,7 +318,7 @@ importlib.machinery.SourceFileLoader) def test_package_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__') @@ -332,7 +331,7 @@ importlib.machinery.SourcelessFileLoader) def test_package_error(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) msg = ("'test_pkg' is a package and cannot " @@ -341,7 +340,7 @@ self._check_import_error(launch_name, msg) def test_package_recursion(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) main_dir = os.path.join(pkg_dir, '__main__') @@ -355,7 +354,7 @@ def test_issue8202(self): # Make sure package __init__ modules see "-m" in sys.argv0 while # searching for the module to execute - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") @@ -372,7 +371,7 @@ def test_issue8202_dash_c_file_ignored(self): # Make sure a "-c" file in the current directory # does not alter the value of sys.path[0] - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): with open("-c", "w") as f: f.write("data") @@ -387,7 +386,7 @@ def test_issue8202_dash_m_file_ignored(self): # Make sure a "-m" file in the current directory # does not alter the value of sys.path[0] - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'other') with support.change_cwd(path=script_dir): with open("-m", "w") as f: @@ -402,7 +401,7 @@ # If a module is invoked with the -m command line flag # and results in an error that the return code to the # shell is '1' - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: with support.change_cwd(path=script_dir): pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) @@ -422,7 +421,7 @@ except: raise NameError from None """) - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', script) exitcode, stdout, stderr = assert_python_failure(script_name) text = stderr.decode('ascii').split('\n') @@ -466,7 +465,7 @@ if error: sys.exit(error) """) - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', script) exitcode, stdout, stderr = assert_python_failure(script_name) text = stderr.decode('ascii') diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -17,7 +17,8 @@ except ImportError: _have_multiprocessing = False -from test import support, script_helper +from test import support +from test.support import script_helper class CompileallTests(unittest.TestCase): diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -9,7 +9,7 @@ # without thread support. test.support.import_module('threading') -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import os import sys diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers.py --- a/Lib/test/test_crashers.py +++ b/Lib/test/test_crashers.py @@ -8,7 +8,7 @@ import glob import os.path import test.support -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers") CRASHER_FILES = os.path.join(CRASHER_DIR, "*.py") diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2729,8 +2729,8 @@ simple tests and no errors. We'll run both the unadorned doctest command, and the verbose version, and then check the output: - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is a very simple test file.\n') @@ -2780,8 +2780,8 @@ file ends in '.py', its handling of python module files (as opposed to straight text files). - >>> from test import script_helper - >>> with script_helper.temp_dir() as tmpdir: + >>> from test.support import script_helper, temp_dir + >>> with temp_dir() as tmpdir: ... fn = os.path.join(tmpdir, 'myfile.doc') ... with open(fn, 'w') as f: ... _ = f.write('This is another simple test file.\n') diff --git a/Lib/test/test_eintr.py b/Lib/test/test_eintr.py --- a/Lib/test/test_eintr.py +++ b/Lib/test/test_eintr.py @@ -2,7 +2,8 @@ import signal import unittest -from test import script_helper, support +from test import support +from test.support import script_helper @unittest.skipUnless(os.name == "posix", "only supported on Unix") diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -6,8 +6,8 @@ import signal import subprocess import sys -from test import support, script_helper -from test.script_helper import assert_python_ok +from test import support +from test.support import script_helper import tempfile import unittest from textwrap import dedent diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,7 +1,8 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr, cpython_only, start_threads) -from test.script_helper import assert_python_ok, make_script, temp_dir + strip_python_stderr, cpython_only, start_threads, + temp_dir) +from test.support.script_helper import assert_python_ok, make_script import sys import time diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -7,7 +7,7 @@ import os import sys import unittest -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from collections import Hashable IS_64BIT = sys.maxsize > 2**32 diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -21,8 +21,9 @@ from test.support import ( EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython, make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask, - unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE) -from test import script_helper + unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE, + temp_dir) +from test.support import script_helper skip_if_dont_write_bytecode = unittest.skipIf( @@ -45,7 +46,7 @@ # temporarily clears the module from sys.modules (if any) # reverts or removes the module when cleaning up name = name or "spam" - with script_helper.temp_dir() as tempdir: + with temp_dir() as tempdir: path = script_helper.make_script(tempdir, name, source) old_module = sys.modules.pop(name, None) try: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -26,7 +26,7 @@ from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only from test.support import MISSING_C_DOCSTRINGS, cpython_only -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test import inspect_fodder as mod from test import inspect_fodder2 as mod2 diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -35,7 +35,7 @@ from collections import deque, UserList from itertools import cycle, count from test import support -from test.script_helper import assert_python_ok, run_python_until_end +from test.support.script_helper import assert_python_ok, run_python_until_end import codecs import io # C implementation of io diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -4,7 +4,7 @@ import unittest import subprocess from test import support -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok class TestTool(unittest.TestCase): diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -38,7 +38,7 @@ import struct import sys import tempfile -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test import support import textwrap import time diff --git a/Lib/test/test_module.py b/Lib/test/test_module.py --- a/Lib/test/test_module.py +++ b/Lib/test/test_module.py @@ -2,7 +2,7 @@ import unittest import weakref from test.support import gc_collect -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import sys ModuleType = type(sys) diff --git a/Lib/test/test_multiprocessing_main_handling.py b/Lib/test/test_multiprocessing_main_handling.py --- a/Lib/test/test_multiprocessing_main_handling.py +++ b/Lib/test/test_multiprocessing_main_handling.py @@ -13,10 +13,9 @@ import os.path import py_compile -from test.script_helper import ( +from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, - assert_python_ok, assert_python_failure, temp_dir, - spawn_python, kill_python) + assert_python_ok, assert_python_failure, spawn_python, kill_python) # Look up which start methods are available to test import multiprocessing @@ -157,12 +156,12 @@ self._check_output(script_name, rc, out, err) def test_basic_script(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') self._check_script(script_name) def test_basic_script_no_suffix(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script', omit_suffix=True) self._check_script(script_name) @@ -173,7 +172,7 @@ # a workaround for that case # See https://github.com/ipython/ipython/issues/4698 source = test_source_main_skipped_in_children - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'ipython', source=source) self._check_script(script_name) @@ -183,7 +182,7 @@ self._check_script(script_no_suffix) def test_script_compiled(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') py_compile.compile(script_name, doraise=True) os.remove(script_name) @@ -192,14 +191,14 @@ def test_directory(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) self._check_script(script_dir) def test_directory_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) py_compile.compile(script_name, doraise=True) @@ -209,7 +208,7 @@ def test_zipfile(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) @@ -217,7 +216,7 @@ def test_zipfile_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', source=source) compiled_name = py_compile.compile(script_name, doraise=True) @@ -225,7 +224,7 @@ self._check_script(zip_name) def test_module_in_package(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, 'check_sibling') @@ -234,20 +233,20 @@ self._check_script(launch_name) def test_module_in_package_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name) self._check_script(launch_name) def test_module_in_subpackage_in_zipfile(self): - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2) launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) self._check_script(launch_name) def test_package(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__', @@ -257,7 +256,7 @@ def test_package_compiled(self): source = self.main_in_children_source - with temp_dir() as script_dir: + with support.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) script_name = _make_test_script(pkg_dir, '__main__', diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -64,7 +64,7 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok root_in_posix = False if hasattr(os, 'geteuid'): diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -4,7 +4,7 @@ import operator import struct from test import support -from test.script_helper import assert_python_failure +from test.support.script_helper import assert_python_failure # # First, we test that we can generate trees from valid source fragments, diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -21,7 +21,7 @@ import textwrap from io import StringIO from collections import namedtuple -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.support import ( TESTFN, rmtree, reap_children, reap_threads, captured_output, captured_stdout, diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -5,7 +5,7 @@ import tempfile import unittest from test.support import import_module, unlink -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok # Skip tests if there is no readline module readline = import_module('readline') diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -9,9 +9,9 @@ import py_compile from test.support import ( forget, make_legacy_pyc, unload, verbose, no_tracing, - create_empty_file) -from test.script_helper import ( - make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir) + create_empty_file, temp_dir) +from test.support.script_helper import ( + make_pkg, make_script, make_zip_pkg, make_zip_script) import runpy diff --git a/Lib/test/test_script_helper.py b/Lib/test/test_script_helper.py --- a/Lib/test/test_script_helper.py +++ b/Lib/test/test_script_helper.py @@ -1,8 +1,8 @@ -"""Unittests for test.script_helper. Who tests the test helper?""" +"""Unittests for test.support.script_helper. Who tests the test helper?""" import subprocess import sys -from test import script_helper +from test.support import script_helper import unittest from unittest import mock diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -11,7 +11,7 @@ import subprocess import traceback import sys, os, time, errno -from test.script_helper import assert_python_ok, spawn_python +from test.support.script_helper import assert_python_ok, spawn_python try: import threading except ImportError: diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1,5 +1,5 @@ import unittest -from test import script_helper +from test.support import script_helper from test import support import subprocess import sys @@ -394,7 +394,7 @@ python_dir, python_base = self._split_python_path() abs_python = os.path.join(python_dir, python_base) rel_python = os.path.join(os.curdir, python_base) - with script_helper.temp_dir() as wrong_dir: + with support.temp_dir() as wrong_dir: # Before calling with an absolute path, confirm that using a # relative path fails. self.assertRaises(FileNotFoundError, subprocess.Popen, diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,5 +1,5 @@ import unittest, test.support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct import subprocess @@ -708,7 +708,7 @@ @test.support.cpython_only def test_debugmallocstats(self): # Test sys._debugmallocstats() - from test.script_helper import assert_python_ok + from test.support.script_helper import assert_python_ok args = ['-c', 'import sys; sys._debugmallocstats()'] ret, out, err = assert_python_ok(*args) self.assertIn(b"free PyDictObjects", err) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -8,7 +8,8 @@ import unittest.mock import tarfile -from test import support, script_helper +from test import support +from test.support import script_helper # Check for our compression modules. try: diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -12,7 +12,8 @@ from unittest import mock import unittest -from test import support, script_helper +from test import support +from test.support import script_helper if hasattr(os, 'stat'): diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -4,7 +4,7 @@ import test.support from test.support import verbose, strip_python_stderr, import_module, cpython_only -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure import random import re diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py --- a/Lib/test/test_tools/test_md5sum.py +++ b/Lib/test/test_tools/test_md5sum.py @@ -4,7 +4,7 @@ import sys import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test.test_tools import scriptsdir, import_tool, skip_if_missing diff --git a/Lib/test/test_tools/test_pindent.py b/Lib/test/test_tools/test_pindent.py --- a/Lib/test/test_tools/test_pindent.py +++ b/Lib/test/test_tools/test_pindent.py @@ -6,7 +6,7 @@ import subprocess import textwrap from test import support -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.test_tools import scriptsdir, skip_if_missing diff --git a/Lib/test/test_tools/test_reindent.py b/Lib/test/test_tools/test_reindent.py --- a/Lib/test/test_tools/test_reindent.py +++ b/Lib/test/test_tools/test_reindent.py @@ -6,7 +6,7 @@ import os import unittest -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.test_tools import scriptsdir, skip_if_missing diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -8,7 +8,7 @@ import re from test import support from test.support import TESTFN, Error, captured_output, unlink, cpython_only -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok import textwrap import traceback diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -4,8 +4,9 @@ import tracemalloc import unittest from unittest.mock import patch -from test.script_helper import assert_python_ok, assert_python_failure -from test import script_helper, support +from test.support.script_helper import (assert_python_ok, assert_python_failure, + interpreter_requires_environment) +from test import support try: import threading except ImportError: @@ -751,7 +752,7 @@ stdout = stdout.rstrip() self.assertEqual(stdout, b'False') - @unittest.skipIf(script_helper.interpreter_requires_environment(), + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -E tests when PYTHON env vars are required.') def test_env_var_ignored_with_E(self): """PYTHON* environment variables must be ignored when -E is present.""" diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -5,7 +5,7 @@ import sys import unittest from test import support -from test.script_helper import assert_python_ok, assert_python_failure +from test.support.script_helper import assert_python_ok, assert_python_failure from test import warning_tests diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -7,7 +7,8 @@ import contextlib import copy -from test import support, script_helper +from test import support +from test.support import script_helper # Used in ReferencesTestCase.test_ref_created_during_del() . ref_from_del = None diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -14,8 +14,8 @@ import linecache import pdb import unittest -from test.script_helper import (spawn_python, kill_python, assert_python_ok, - temp_dir, make_script, make_zip_script) +from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, + make_script, make_zip_script) verbose = test.support.verbose @@ -78,7 +78,7 @@ def test_inspect_getsource_issue4223(self): test_src = "def foo(): pass\n" - with temp_dir() as d: + with test.support.temp_dir() as d: init_name = make_script(d, '__init__', test_src) name_in_zip = os.path.join('zip_pkg', os.path.basename(init_name)) @@ -118,7 +118,7 @@ mod_name = mod_name.replace("sample_", "sample_zipped_") sample_sources[mod_name] = src - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', @@ -195,7 +195,7 @@ doctest.testmod() """) pattern = 'File "%s", line 2, in %s' - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) rc, out, err = assert_python_ok(script_name) expected = pattern % (script_name, "__main__.Test") @@ -222,7 +222,7 @@ import pdb pdb.Pdb(nosigint=True).runcall(f) """) - with temp_dir() as d: + with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) p = spawn_python(script_name) p.stdin.write(b'l\n') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,12 @@ - Issue #23887: urllib.error.HTTPError now has a proper repr() representation. Patch by Berker Peksag. +Tests +----- + +- Issue #9517: Move script_helper into the support package. + Patch by Christie Wilson. + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 06:01:23 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 06 May 2015 04:01:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_remaining_tests_and_re?= =?utf-8?q?move_an_unused_import=2E?= Message-ID: <20150506040123.8149.29509@psf.io> https://hg.python.org/cpython/rev/1320ec1b24af changeset: 95890:1320ec1b24af user: Berker Peksag date: Wed May 06 07:01:52 2015 +0300 summary: Fix remaining tests and remove an unused import. files: Lib/test/_test_multiprocessing.py | 6 +++--- Lib/test/support/script_helper.py | 2 +- Lib/test/test_compile.py | 3 ++- Lib/test/test_tools/test_i18n.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -19,7 +19,7 @@ import struct import operator import test.support -import test.script_helper +import test.support.script_helper # Skip tests if _multiprocessing wasn't built. @@ -3483,11 +3483,11 @@ sm = multiprocessing.get_start_method() name = os.path.join(os.path.dirname(__file__), 'mp_fork_bomb.py') if sm != 'fork': - rc, out, err = test.script_helper.assert_python_failure(name, sm) + rc, out, err = test.support.script_helper.assert_python_failure(name, sm) self.assertEqual(out, b'') self.assertIn(b'RuntimeError', err) else: - rc, out, err = test.script_helper.assert_python_ok(name, sm) + rc, out, err = test.support.script_helper.assert_python_ok(name, sm) self.assertEqual(out.rstrip(), b'123') self.assertEqual(err, b'') diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -14,7 +14,7 @@ import zipfile from importlib.util import source_from_cache -from test.support import make_legacy_pyc, strip_python_stderr, temp_dir +from test.support import make_legacy_pyc, strip_python_stderr # Cached result of the expensive test performed in the function below. diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -5,7 +5,8 @@ import _ast import tempfile import types -from test import support, script_helper +from test import support +from test.support import script_helper class TestSpecifics(unittest.TestCase): diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -3,7 +3,7 @@ import os import unittest -from test.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok from test.test_tools import toolsdir from test.support import temp_cwd -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 08:54:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 06:54:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324009=3A_Got_rid_?= =?utf-8?q?of_using_rare_=22y=23=22_format_unit_in_TextIOWrapper=2Etell=28?= =?utf-8?b?KS4=?= Message-ID: <20150506065422.8151.57208@psf.io> https://hg.python.org/cpython/rev/d65233f630e1 changeset: 95894:d65233f630e1 user: Serhiy Storchaka date: Wed May 06 09:53:07 2015 +0300 summary: Issue #24009: Got rid of using rare "y#" format unit in TextIOWrapper.tell(). Parsed value should be bytes, not general robuffer, this is required in other places. files: Modules/_io/textio.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2262,7 +2262,6 @@ Py_ssize_t skip_bytes, skip_back; PyObject *saved_state = NULL; char *input, *input_end; - char *dec_buffer; Py_ssize_t dec_buffer_len; int dec_flags; @@ -2327,14 +2326,24 @@ goto fail; #define DECODER_GETSTATE() do { \ + PyObject *dec_buffer; \ PyObject *_state = PyObject_CallMethodObjArgs(self->decoder, \ _PyIO_str_getstate, NULL); \ if (_state == NULL) \ goto fail; \ - if (!PyArg_ParseTuple(_state, "y#i", &dec_buffer, &dec_buffer_len, &dec_flags)) { \ + if (!PyArg_ParseTuple(_state, "Oi", &dec_buffer, &dec_flags)) { \ Py_DECREF(_state); \ goto fail; \ } \ + if (!PyBytes_Check(dec_buffer)) { \ + PyErr_Format(PyExc_TypeError, \ + "decoder getstate() should have returned a bytes " \ + "object, not '%.200s'", \ + Py_TYPE(dec_buffer)->tp_name); \ + Py_DECREF(_state); \ + goto fail; \ + } \ + dec_buffer_len = PyBytes_GET_SIZE(dec_buffer); \ Py_DECREF(_state); \ } while (0) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 08:54:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 06:54:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324125=3A_Saved_error=27s_line_and_column_number?= =?utf-8?q?s_when_an_error_is_occured?= Message-ID: <20150506065421.1947.50684@psf.io> https://hg.python.org/cpython/rev/1fb83fa2cdef changeset: 95893:1fb83fa2cdef parent: 95890:1320ec1b24af parent: 95892:7f8cd879687b user: Serhiy Storchaka date: Wed May 06 09:38:22 2015 +0300 summary: Issue #24125: Saved error's line and column numbers when an error is occured during closing expatreader. Fixed a regression introduced in issue #23865. files: Lib/test/test_sax.py | 2 ++ Lib/xml/sax/expatreader.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -1166,6 +1166,8 @@ parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing self.assertRaises(SAXParseException, parser.parse, StringIO("")) + self.assertEqual(parser.getColumnNumber(), 5) + self.assertEqual(parser.getLineNumber(), 1) def test_sax_parse_exception_str(self): # pass various values from a locator to the SAXParseException to diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -43,6 +43,9 @@ _mkproxy = weakref.proxy del weakref, _weakref +class _ClosedParser: + pass + # --- ExpatLocator class ExpatLocator(xmlreader.Locator): @@ -211,16 +214,24 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack or self._parser is None: + if (self._entity_stack or self._parser is None or + isinstance(self._parser, _ClosedParser)): # If we are completing an external entity, do nothing here return try: self.feed("", isFinal = 1) self._cont_handler.endDocument() - finally: self._parsing = 0 # break cycle created by expat handlers pointing to our methods self._parser = None + finally: + self._parsing = 0 + if self._parser is not None: + # Keep ErrorColumnNumber and ErrorLineNumber after closing. + parser = _ClosedParser() + parser.ErrorColumnNumber = self._parser.ErrorColumnNumber + parser.ErrorLineNumber = self._parser.ErrorLineNumber + self._parser = parser try: file = self._source.getCharacterStream() if file is not None: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 08:54:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 06:54:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTI1?= =?utf-8?q?=3A_Saved_error=27s_line_and_column_numbers_when_an_error_is_oc?= =?utf-8?q?cured?= Message-ID: <20150506065421.8948.27370@psf.io> https://hg.python.org/cpython/rev/fe340c2a220e changeset: 95891:fe340c2a220e branch: 2.7 parent: 95874:376c2d81d0e2 user: Serhiy Storchaka date: Wed May 06 09:35:52 2015 +0300 summary: Issue #24125: Saved error's line and column numbers when an error is occured during closing expatreader. Fixed a regression introduced in issue #23865. files: Lib/test/test_sax.py | 2 ++ Lib/xml/sax/expatreader.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -933,6 +933,8 @@ parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing self.assertRaises(SAXParseException, parser.parse, StringIO("")) + self.assertEqual(parser.getColumnNumber(), 5) + self.assertEqual(parser.getLineNumber(), 1) def test_sax_parse_exception_str(self): # pass various values from a locator to the SAXParseException to diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -43,6 +43,9 @@ _mkproxy = weakref.proxy del weakref, _weakref +class _ClosedParser: + pass + # --- ExpatLocator class ExpatLocator(xmlreader.Locator): @@ -214,16 +217,24 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack or self._parser is None: + if (self._entity_stack or self._parser is None or + isinstance(self._parser, _ClosedParser)): # If we are completing an external entity, do nothing here return try: self.feed("", isFinal = 1) self._cont_handler.endDocument() - finally: self._parsing = 0 # break cycle created by expat handlers pointing to our methods self._parser = None + finally: + self._parsing = 0 + if self._parser is not None: + # Keep ErrorColumnNumber and ErrorLineNumber after closing. + parser = _ClosedParser() + parser.ErrorColumnNumber = self._parser.ErrorColumnNumber + parser.ErrorLineNumber = self._parser.ErrorLineNumber + self._parser = parser def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 08:54:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 06:54:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTI1?= =?utf-8?q?=3A_Saved_error=27s_line_and_column_numbers_when_an_error_is_oc?= =?utf-8?q?cured?= Message-ID: <20150506065421.14356.94639@psf.io> https://hg.python.org/cpython/rev/7f8cd879687b changeset: 95892:7f8cd879687b branch: 3.4 parent: 95884:29512e2015d9 user: Serhiy Storchaka date: Wed May 06 09:36:06 2015 +0300 summary: Issue #24125: Saved error's line and column numbers when an error is occured during closing expatreader. Fixed a regression introduced in issue #23865. files: Lib/test/test_sax.py | 2 ++ Lib/xml/sax/expatreader.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -1126,6 +1126,8 @@ parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing self.assertRaises(SAXParseException, parser.parse, StringIO("")) + self.assertEqual(parser.getColumnNumber(), 5) + self.assertEqual(parser.getLineNumber(), 1) def test_sax_parse_exception_str(self): # pass various values from a locator to the SAXParseException to diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -43,6 +43,9 @@ _mkproxy = weakref.proxy del weakref, _weakref +class _ClosedParser: + pass + # --- ExpatLocator class ExpatLocator(xmlreader.Locator): @@ -211,16 +214,24 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack or self._parser is None: + if (self._entity_stack or self._parser is None or + isinstance(self._parser, _ClosedParser)): # If we are completing an external entity, do nothing here return try: self.feed("", isFinal = 1) self._cont_handler.endDocument() - finally: self._parsing = 0 # break cycle created by expat handlers pointing to our methods self._parser = None + finally: + self._parsing = 0 + if self._parser is not None: + # Keep ErrorColumnNumber and ErrorLineNumber after closing. + parser = _ClosedParser() + parser.ErrorColumnNumber = self._parser.ErrorColumnNumber + parser.ErrorLineNumber = self._parser.ErrorLineNumber + self._parser = parser bs = self._source.getByteStream() if bs is not None: bs.close() -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed May 6 10:36:57 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 06 May 2015 08:36:57 +0000 Subject: [Python-checkins] Daily reference leaks (1320ec1b24af): sum=5 Message-ID: <20150506083657.7812.15150@psf.io> results for 1320ec1b24af on branch "default" -------------------------------------------- test_collections leaked [0, 2, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogNFG2Fy', '--timeout', '7200'] From python-checkins at python.org Wed May 6 13:00:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 11:00:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323880=3A_Tkinter?= =?utf-8?q?=27s_getint=28=29_and_getdouble=28=29_now_support_Tcl=5FObj=2E?= Message-ID: <20150506110026.25453.10064@psf.io> https://hg.python.org/cpython/rev/cb80dd82d3da changeset: 95895:cb80dd82d3da user: Serhiy Storchaka date: Wed May 06 14:00:04 2015 +0300 summary: Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. Tkinter's getdouble() now supports any numbers (in particular int). files: Lib/idlelib/CodeContext.py | 8 +- Lib/test/test_tcl.py | 2 +- Lib/tkinter/__init__.py | 132 +++++---- Lib/tkinter/font.py | 6 +- Lib/tkinter/simpledialog.py | 4 +- Lib/tkinter/test/test_tkinter/test_variables.py | 6 +- Lib/tkinter/test/test_ttk/test_extensions.py | 6 +- Misc/NEWS | 3 + Modules/_tkinter.c | 32 +- 9 files changed, 115 insertions(+), 84 deletions(-) diff --git a/Lib/idlelib/CodeContext.py b/Lib/idlelib/CodeContext.py --- a/Lib/idlelib/CodeContext.py +++ b/Lib/idlelib/CodeContext.py @@ -57,18 +57,18 @@ # Calculate the border width and horizontal padding required to # align the context with the text in the main Text widget. # - # All values are passed through int(str()), since some + # All values are passed through getint(), since some # values may be pixel objects, which can't simply be added to ints. widgets = self.editwin.text, self.editwin.text_frame # Calculate the required vertical padding padx = 0 for widget in widgets: - padx += int(str( widget.pack_info()['padx'] )) - padx += int(str( widget.cget('padx') )) + padx += widget.tk.getint(widget.pack_info()['padx']) + padx += widget.tk.getint(widget.cget('padx')) # Calculate the required border width border = 0 for widget in widgets: - border += int(str( widget.cget('border') )) + border += widget.tk.getint(widget.cget('border')) self.label = tkinter.Label(self.editwin.top, text="\n" * (self.context_depth - 1), anchor=W, justify=LEFT, diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -163,10 +163,10 @@ self.assertEqual(tcl.getdouble(' 42 '), 42.0) self.assertEqual(tcl.getdouble(' 42.5 '), 42.5) self.assertEqual(tcl.getdouble(42.5), 42.5) + self.assertEqual(tcl.getdouble(42), 42.0) self.assertRaises(TypeError, tcl.getdouble) self.assertRaises(TypeError, tcl.getdouble, '42.5', '10') self.assertRaises(TypeError, tcl.getdouble, b'42.5') - self.assertRaises(TypeError, tcl.getdouble, 42) self.assertRaises(TclError, tcl.getdouble, 'a') self.assertRaises((TypeError, ValueError, TclError), tcl.getdouble, '42.5\0') diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -355,7 +355,7 @@ def get(self): """Return the value of the variable as an integer.""" - return getint(self._tk.globalgetvar(self._name)) + return self._tk.getint(self._tk.globalgetvar(self._name)) class DoubleVar(Variable): """Value holder for float variables.""" @@ -374,7 +374,7 @@ def get(self): """Return the value of the variable as a float.""" - return getdouble(self._tk.globalgetvar(self._name)) + return self._tk.getdouble(self._tk.globalgetvar(self._name)) class BooleanVar(Variable): """Value holder for boolean variables.""" @@ -505,14 +505,26 @@ def getvar(self, name='PY_VAR'): """Return value of Tcl variable NAME.""" return self.tk.getvar(name) - getint = int - getdouble = float + + def getint(self, s): + try: + return self.tk.getint(s) + except TclError as exc: + raise ValueError(str(exc)) + + def getdouble(self, s): + try: + return self.tk.getdouble(s) + except TclError as exc: + raise ValueError(str(exc)) + def getboolean(self, s): """Return a boolean value for Tcl boolean values true and false given as parameter.""" try: return self.tk.getboolean(s) except TclError: raise ValueError("invalid literal for getboolean()") + def focus_set(self): """Direct input focus to this widget. @@ -778,7 +790,7 @@ def winfo_atom(self, name, displayof=0): """Return integer which represents atom NAME.""" args = ('winfo', 'atom') + self._displayof(displayof) + (name,) - return getint(self.tk.call(args)) + return self.tk.getint(self.tk.call(args)) def winfo_atomname(self, id, displayof=0): """Return name of atom with identifier ID.""" args = ('winfo', 'atomname') \ @@ -786,7 +798,7 @@ return self.tk.call(args) def winfo_cells(self): """Return number of cells in the colormap for this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'cells', self._w)) def winfo_children(self): """Return a list of all widgets which are children of this widget.""" @@ -817,22 +829,22 @@ return self._nametowidget(name) def winfo_depth(self): """Return the number of bits per pixel.""" - return getint(self.tk.call('winfo', 'depth', self._w)) + return self.tk.getint(self.tk.call('winfo', 'depth', self._w)) def winfo_exists(self): """Return true if this widget exists.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'exists', self._w)) def winfo_fpixels(self, number): """Return the number of pixels for the given distance NUMBER (e.g. "3c") as float.""" - return getdouble(self.tk.call( + return self.tk.getdouble(self.tk.call( 'winfo', 'fpixels', self._w, number)) def winfo_geometry(self): """Return geometry string for this widget in the form "widthxheight+X+Y".""" return self.tk.call('winfo', 'geometry', self._w) def winfo_height(self): """Return height of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'height', self._w)) def winfo_id(self): """Return identifier ID for this widget.""" @@ -844,7 +856,7 @@ return self.tk.splitlist(self.tk.call(args)) def winfo_ismapped(self): """Return true if this widget is mapped.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'ismapped', self._w)) def winfo_manager(self): """Return the window mananger name for this widget.""" @@ -862,11 +874,11 @@ return self.tk.call(args) def winfo_pixels(self, number): """Rounded integer value of winfo_fpixels.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'pixels', self._w, number)) def winfo_pointerx(self): """Return the x coordinate of the pointer on the root window.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'pointerx', self._w)) def winfo_pointerxy(self): """Return a tuple of x and y coordinates of the pointer on the root window.""" @@ -874,15 +886,15 @@ self.tk.call('winfo', 'pointerxy', self._w)) def winfo_pointery(self): """Return the y coordinate of the pointer on the root window.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'pointery', self._w)) def winfo_reqheight(self): """Return requested height of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'reqheight', self._w)) def winfo_reqwidth(self): """Return requested width of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'reqwidth', self._w)) def winfo_rgb(self, color): """Return tuple of decimal values for red, green, blue for @@ -892,12 +904,12 @@ def winfo_rootx(self): """Return x coordinate of upper left corner of this widget on the root window.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'rootx', self._w)) def winfo_rooty(self): """Return y coordinate of upper left corner of this widget on the root window.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'rooty', self._w)) def winfo_screen(self): """Return the screen name of this widget.""" @@ -905,27 +917,27 @@ def winfo_screencells(self): """Return the number of the cells in the colormap of the screen of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screencells', self._w)) def winfo_screendepth(self): """Return the number of bits per pixel of the root window of the screen of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screendepth', self._w)) def winfo_screenheight(self): """Return the number of pixels of the height of the screen of this widget in pixel.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screenheight', self._w)) def winfo_screenmmheight(self): """Return the number of pixels of the height of the screen of this widget in mm.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screenmmheight', self._w)) def winfo_screenmmwidth(self): """Return the number of pixels of the width of the screen of this widget in mm.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screenmmwidth', self._w)) def winfo_screenvisual(self): """Return one of the strings directcolor, grayscale, pseudocolor, @@ -935,7 +947,7 @@ def winfo_screenwidth(self): """Return the number of pixels of the width of the screen of this widget in pixel.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'screenwidth', self._w)) def winfo_server(self): """Return information of the X-Server of the screen of this widget in @@ -947,7 +959,7 @@ 'winfo', 'toplevel', self._w)) def winfo_viewable(self): """Return true if the widget and all its higher ancestors are mapped.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'viewable', self._w)) def winfo_visual(self): """Return one of the strings directcolor, grayscale, pseudocolor, @@ -979,37 +991,37 @@ """Return the height of the virtual root window associated with this widget in pixels. If there is no virtual root window return the height of the screen.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'vrootheight', self._w)) def winfo_vrootwidth(self): """Return the width of the virtual root window associated with this widget in pixel. If there is no virtual root window return the width of the screen.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'vrootwidth', self._w)) def winfo_vrootx(self): """Return the x offset of the virtual root relative to the root window of the screen of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'vrootx', self._w)) def winfo_vrooty(self): """Return the y offset of the virtual root relative to the root window of the screen of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'vrooty', self._w)) def winfo_width(self): """Return the width of this widget.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'width', self._w)) def winfo_x(self): """Return the x coordinate of the upper left corner of this widget in the parent.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'x', self._w)) def winfo_y(self): """Return the y coordinate of the upper left corner of this widget in the parent.""" - return getint( + return self.tk.getint( self.tk.call('winfo', 'y', self._w)) def update(self): """Enter event loop until all pending events have been processed by Tcl.""" @@ -1126,11 +1138,11 @@ def _getints(self, string): """Internal function.""" if string: - return tuple(map(getint, self.tk.splitlist(string))) + return tuple(map(self.tk.getint, self.tk.splitlist(string))) def _getdoubles(self, string): """Internal function.""" if string: - return tuple(map(getdouble, self.tk.splitlist(string))) + return tuple(map(self.tk.getdouble, self.tk.splitlist(string))) def _getboolean(self, string): """Internal function.""" if string: @@ -1229,12 +1241,12 @@ if len(args) != len(self._subst_format): return args getboolean = self.tk.getboolean - getint = int + getint = self.tk.getint def getint_event(s): """Tk changed behavior in 8.4.2, returning "??" rather more often.""" try: - return int(s) - except ValueError: + return getint(s) + except (ValueError, TclError): return s nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args @@ -1278,7 +1290,7 @@ e.y_root = getint_event(Y) try: e.delta = getint(D) - except ValueError: + except (ValueError, TclError): e.delta = 0 return (e,) def _report_exception(self): @@ -1403,10 +1415,10 @@ if not svalue: return None elif '.' in svalue: - return getdouble(svalue) + return self.tk.getdouble(svalue) else: - return getint(svalue) - except ValueError: + return self.tk.getint(svalue) + except (ValueError, TclError): pass return value @@ -2284,17 +2296,17 @@ def canvasx(self, screenx, gridspacing=None): """Return the canvas x coordinate of pixel position SCREENX rounded to nearest multiple of GRIDSPACING units.""" - return getdouble(self.tk.call( + return self.tk.getdouble(self.tk.call( self._w, 'canvasx', screenx, gridspacing)) def canvasy(self, screeny, gridspacing=None): """Return the canvas y coordinate of pixel position SCREENY rounded to nearest multiple of GRIDSPACING units.""" - return getdouble(self.tk.call( + return self.tk.getdouble(self.tk.call( self._w, 'canvasy', screeny, gridspacing)) def coords(self, *args): """Return a list of coordinates for the item given in ARGS.""" # XXX Should use _flatten on args - return [getdouble(x) for x in + return [self.tk.getdouble(x) for x in self.tk.splitlist( self.tk.call((self._w, 'coords') + args))] def _create(self, itemType, args, kw): # Args: (val, val, ..., cnf={}) @@ -2305,7 +2317,7 @@ args = args[:-1] else: cnf = {} - return getint(self.tk.call( + return self.tk.getint(self.tk.call( self._w, 'create', itemType, *(args + self._options(cnf, kw)))) def create_arc(self, *args, **kw): @@ -2389,7 +2401,7 @@ self.tk.call((self._w, 'icursor') + args) def index(self, *args): """Return position of cursor as integer in item specified in ARGS.""" - return getint(self.tk.call((self._w, 'index') + args)) + return self.tk.getint(self.tk.call((self._w, 'index') + args)) def insert(self, *args): """Insert TEXT in item TAGORID at position POS. ARGS must be TAGORID POS TEXT.""" @@ -2515,7 +2527,7 @@ self.tk.call(self._w, 'icursor', index) def index(self, index): """Return position of cursor.""" - return getint(self.tk.call( + return self.tk.getint(self.tk.call( self._w, 'index', index)) def insert(self, index, string): """Insert STRING at INDEX.""" @@ -2630,13 +2642,13 @@ """Return index of item identified with INDEX.""" i = self.tk.call(self._w, 'index', index) if i == 'none': return None - return getint(i) + return self.tk.getint(i) def insert(self, index, *elements): """Insert ELEMENTS at INDEX.""" self.tk.call((self._w, 'insert', index) + elements) def nearest(self, y): """Get index of item which is nearest to y coordinate Y.""" - return getint(self.tk.call( + return self.tk.getint(self.tk.call( self._w, 'nearest', y)) def scan_mark(self, x, y): """Remember the current X, Y coordinates.""" @@ -2670,7 +2682,7 @@ select_set = selection_set def size(self): """Return the number of elements in the listbox.""" - return getint(self.tk.call(self._w, 'size')) + return self.tk.getint(self.tk.call(self._w, 'size')) def itemcget(self, index, option): """Return the resource value for an ITEM and an OPTION.""" return self.tk.call( @@ -2772,7 +2784,7 @@ """Return the index of a menu item identified by INDEX.""" i = self.tk.call(self._w, 'index', index) if i == 'none': return None - return getint(i) + return self.tk.getint(i) def invoke(self, index): """Invoke a menu item identified by INDEX and execute the associated command.""" @@ -2789,10 +2801,10 @@ def xposition(self, index): # new in Tk 8.5 """Return the x-position of the leftmost pixel of the menu item at INDEX.""" - return getint(self.tk.call(self._w, 'xposition', index)) + return self.tk.getint(self.tk.call(self._w, 'xposition', index)) def yposition(self, index): """Return the y-position of the topmost pixel of the menu item at INDEX.""" - return getint(self.tk.call( + return self.tk.getint(self.tk.call( self._w, 'yposition', index)) class Menubutton(Widget): @@ -2848,9 +2860,9 @@ """Get the current value as integer or float.""" value = self.tk.call(self._w, 'get') try: - return getint(value) - except ValueError: - return getdouble(value) + return self.tk.getint(value) + except (ValueError, TclError): + return self.tk.getdouble(value) def set(self, value): """Set the value to VALUE.""" self.tk.call(self._w, 'set', value) @@ -2888,12 +2900,12 @@ def delta(self, deltax, deltay): """Return the fractional change of the scrollbar setting if it would be moved by DELTAX or DELTAY pixels.""" - return getdouble( + return self.tk.getdouble( self.tk.call(self._w, 'delta', deltax, deltay)) def fraction(self, x, y): """Return the fractional value which corresponds to a slider position of X,Y.""" - return getdouble(self.tk.call(self._w, 'fraction', x, y)) + return self.tk.getdouble(self.tk.call(self._w, 'fraction', x, y)) def identify(self, x, y): """Return the element under position X,Y as one of "arrow1","slider","arrow2" or "".""" @@ -3364,14 +3376,14 @@ config = configure def height(self): """Return the height of the image.""" - return getint( + return self.tk.getint( self.tk.call('image', 'height', self.name)) def type(self): """Return the type of the imgage, e.g. "photo" or "bitmap".""" return self.tk.call('image', 'type', self.name) def width(self): """Return the width of the image.""" - return getint( + return self.tk.getint( self.tk.call('image', 'width', self.name)) class PhotoImage(Image): diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -153,7 +153,7 @@ args = (text,) if displayof: args = ('-displayof', displayof, text) - return int(self._call("font", "measure", self.name, *args)) + return self._root.tk.getint(self._call("font", "measure", self.name, *args)) def metrics(self, *options, **kw): """Return font metrics. @@ -166,13 +166,13 @@ args = ('-displayof', displayof) if options: args = args + self._get(options) - return int( + return self._root.tk.getint( self._call("font", "metrics", self.name, *args)) else: res = self._split(self._call("font", "metrics", self.name, *args)) options = {} for i in range(0, len(res), 2): - options[res[i][1:]] = int(res[i+1]) + options[res[i][1:]] = self._root.tk.getint(res[i+1]) return options diff --git a/Lib/tkinter/simpledialog.py b/Lib/tkinter/simpledialog.py --- a/Lib/tkinter/simpledialog.py +++ b/Lib/tkinter/simpledialog.py @@ -325,7 +325,7 @@ class _QueryInteger(_QueryDialog): errormessage = "Not an integer." def getresult(self): - return int(self.entry.get()) + return self.getint(self.entry.get()) def askinteger(title, prompt, **kw): '''get an integer from the user @@ -344,7 +344,7 @@ class _QueryFloat(_QueryDialog): errormessage = "Not a floating point value." def getresult(self): - return float(self.entry.get()) + return self.getdouble(self.entry.get()) def askfloat(title, prompt, **kw): '''get a float from the user diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -122,10 +122,10 @@ def test_invalid_value(self): v = IntVar(self.root, name="name") self.root.globalsetvar("name", "value") - with self.assertRaises(ValueError): + with self.assertRaises((ValueError, TclError)): v.get() self.root.globalsetvar("name", "345.0") - with self.assertRaises(ValueError): + with self.assertRaises((ValueError, TclError)): v.get() @@ -152,7 +152,7 @@ def test_invalid_value(self): v = DoubleVar(self.root, name="name") self.root.globalsetvar("name", "value") - with self.assertRaises(ValueError): + with self.assertRaises((ValueError, TclError)): v.get() diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -70,17 +70,15 @@ # variable initialization/passing passed_expected = (('0', 0), (0, 0), (10, 10), (-1, -1), (sys.maxsize + 1, sys.maxsize + 1)) - if self.wantobjects: - passed_expected += ((2.5, 2),) for pair in passed_expected: x = ttk.LabeledScale(self.root, from_=pair[0]) self.assertEqual(x.value, pair[1]) x.destroy() x = ttk.LabeledScale(self.root, from_='2.5') - self.assertRaises(ValueError, x._variable.get) + self.assertRaises((ValueError, tkinter.TclError), x._variable.get) x.destroy() x = ttk.LabeledScale(self.root, from_=None) - self.assertRaises(ValueError, x._variable.get) + self.assertRaises((ValueError, tkinter.TclError), x._variable.get) x.destroy() # variable should have its default value set to the from_ value myvar = tkinter.DoubleVar(self.root, value=20) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,9 @@ Library ------- +- Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. + Tkinter's getdouble() now supports any numbers (in particular int). + - Issue #22619: Added negative limit support in the traceback module. Based on patch by Dmitry Kazakov. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1934,12 +1934,18 @@ return arg; } - if (!PyArg_Parse(arg, "s:getint", &s)) - return NULL; - CHECK_STRING_LENGTH(s); - value = Tcl_NewStringObj(s, -1); - if (value == NULL) - return Tkinter_Error((PyObject *)self); + if (PyTclObject_Check(arg)) { + value = ((PyTclObject*)arg)->value; + Tcl_IncrRefCount(value); + } + else { + if (!PyArg_Parse(arg, "s:getint", &s)) + return NULL; + CHECK_STRING_LENGTH(s); + value = Tcl_NewStringObj(s, -1); + if (value == NULL) + return Tkinter_Error((PyObject *)self); + } /* Don't use Tcl_GetInt() because it returns ambiguous result for value in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). @@ -1977,12 +1983,24 @@ return arg; } + if (PyNumber_Check(arg)) { + return PyNumber_Float(arg); + } + + if (PyTclObject_Check(arg)) { + if (Tcl_GetDoubleFromObj(Tkapp_Interp(self), + ((PyTclObject*)arg)->value, + &v) == TCL_ERROR) + return Tkinter_Error((PyObject *)self); + return PyFloat_FromDouble(v); + } + if (!PyArg_Parse(arg, "s:getdouble", &s)) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR) return Tkinter_Error((PyObject *)self); - return Py_BuildValue("d", v); + return PyFloat_FromDouble(v); } /*[clinic input] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 13:19:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 11:19:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_specialized_functions_?= =?utf-8?q?intead_of_Py=5FBuildValue=28=29_in_=5Ftkinter=2E?= Message-ID: <20150506111941.8940.94963@psf.io> https://hg.python.org/cpython/rev/8bac00eadfda changeset: 95896:8bac00eadfda user: Serhiy Storchaka date: Wed May 06 14:19:22 2015 +0300 summary: Use specialized functions intead of Py_BuildValue() in _tkinter. files: Modules/_tkinter.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -2092,7 +2092,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error((PyObject *)self); else - res = Py_BuildValue("l", v); + res = PyLong_FromLong(v); LEAVE_OVERLAP_TCL return res; } @@ -2123,7 +2123,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error((PyObject *)self); else - res = Py_BuildValue("d", v); + res = PyFloat_FromDouble(v); LEAVE_OVERLAP_TCL return res; } @@ -2152,7 +2152,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error((PyObject *)self); else - res = Py_BuildValue("i", v); + res = PyLong_FromLong(v); LEAVE_OVERLAP_TCL return res; } @@ -2891,7 +2891,7 @@ ENTER_TCL rv = Tcl_DoOneEvent(flags); LEAVE_TCL - return Py_BuildValue("i", rv); + return PyLong_FromLong(rv); } /*[clinic input] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:15:11 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:15:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324134=3A_assertRaises=28=29=2C_assertRaisesRege?= =?utf-8?q?x=28=29=2C_assertWarns=28=29_and?= Message-ID: <20150506161511.1917.59647@psf.io> https://hg.python.org/cpython/rev/679b5439b9a1 changeset: 95899:679b5439b9a1 parent: 95896:8bac00eadfda parent: 95898:5418ab3e5556 user: Serhiy Storchaka date: Wed May 06 19:14:47 2015 +0300 summary: Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. Added tests for assertRaises(). files: Lib/unittest/case.py | 24 +++++---- Lib/unittest/test/test_case.py | 52 ++++++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -129,15 +129,17 @@ msg = self.test_case._formatMessage(self.msg, standardMsg) raise self.test_case.failureException(msg) +def _sentinel(*args, **kwargs): + raise AssertionError('Should never called') class _AssertRaisesBaseContext(_BaseTestCaseContext): - def __init__(self, expected, test_case, callable_obj=None, + def __init__(self, expected, test_case, callable_obj=_sentinel, expected_regex=None): _BaseTestCaseContext.__init__(self, test_case) self.expected = expected self.test_case = test_case - if callable_obj is not None: + if callable_obj is not _sentinel: try: self.obj_name = callable_obj.__name__ except AttributeError: @@ -151,11 +153,11 @@ def handle(self, name, callable_obj, args, kwargs): """ - If callable_obj is None, assertRaises/Warns is being used as a + If callable_obj is _sentinel, assertRaises/Warns is being used as a context manager, so check for a 'msg' kwarg and return self. - If callable_obj is not None, call it passing args and kwargs. + If callable_obj is not _sentinel, call it passing args and kwargs. """ - if callable_obj is None: + if callable_obj is _sentinel: self.msg = kwargs.pop('msg', None) return self with self: @@ -674,7 +676,7 @@ except UnicodeDecodeError: return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=None, *args, **kwargs): + def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -682,7 +684,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted or None, will return a + If called with callableObj omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -703,7 +705,7 @@ context = _AssertRaisesContext(excClass, self, callableObj) return context.handle('assertRaises', callableObj, args, kwargs) - def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): + def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs): """Fail unless a warning of class warnClass is triggered by callable_obj when invoked with arguments args and keyword arguments kwargs. If a different type of warning is @@ -711,7 +713,7 @@ warning filtering rules in effect, it might be silenced, printed out, or raised as an exception. - If called with callable_obj omitted or None, will return a + If called with callable_obj omitted, will return a context object used like this:: with self.assertWarns(SomeWarning): @@ -1219,7 +1221,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegex(self, expected_exception, expected_regex, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a raised exception matches a regex. Args: @@ -1238,7 +1240,7 @@ return context.handle('assertRaisesRegex', callable_obj, args, kwargs) def assertWarnsRegex(self, expected_warning, expected_regex, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1132,6 +1132,50 @@ self.assertRaises(self.failureException, self.assertRegex, 'saaas', r'aaaa') + def testAssertRaisesCallable(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + self.assertRaises(ExceptionMock, Stub) + # A tuple of exception classes is accepted + self.assertRaises((ValueError, ExceptionMock), Stub) + # *args and **kwargs also work + self.assertRaises(ValueError, int, '19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + self.assertRaises(ExceptionMock, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertRaises(ExceptionMock, None) + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesContext(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + with self.assertRaises(ExceptionMock): + Stub() + # A tuple of exception classes is accepted + with self.assertRaises((ValueError, ExceptionMock)) as cm: + Stub() + # The context manager exposes caught exception + self.assertIsInstance(cm.exception, ExceptionMock) + self.assertEqual(cm.exception.args[0], 'We expect') + # *args and **kwargs also work + with self.assertRaises(ValueError): + int('19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + with self.assertRaises(ExceptionMock): + pass + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + def testAssertRaisesRegex(self): class ExceptionMock(Exception): pass @@ -1141,6 +1185,8 @@ self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) + with self.assertRaises(TypeError): + self.assertRaisesRegex(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegex(self): self.assertRaisesRegex( @@ -1208,6 +1254,9 @@ # Failure when no warning is triggered with self.assertRaises(self.failureException): self.assertWarns(RuntimeWarning, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertWarns(RuntimeWarning, None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) @@ -1269,6 +1318,9 @@ with self.assertRaises(self.failureException): self.assertWarnsRegex(RuntimeWarning, "o+", lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertWarnsRegex(RuntimeWarning, "o+", None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,9 @@ Library ------- +- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() checks are not longer successful if the callable is None. + - Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. Tkinter's getdouble() now supports any numbers (in particular int). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:15:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:15:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTM0?= =?utf-8?q?=3A_assertRaises=28=29=2C_assertRaisesRegex=28=29=2C_assertWarn?= =?utf-8?q?s=28=29_and?= Message-ID: <20150506161511.14356.1284@psf.io> https://hg.python.org/cpython/rev/5418ab3e5556 changeset: 95898:5418ab3e5556 branch: 3.4 parent: 95892:7f8cd879687b user: Serhiy Storchaka date: Wed May 06 19:13:11 2015 +0300 summary: Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. Added tests for assertRaises(). files: Lib/unittest/case.py | 24 +++++---- Lib/unittest/test/test_case.py | 52 ++++++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -129,15 +129,17 @@ msg = self.test_case._formatMessage(self.msg, standardMsg) raise self.test_case.failureException(msg) +def _sentinel(*args, **kwargs): + raise AssertionError('Should never called') class _AssertRaisesBaseContext(_BaseTestCaseContext): - def __init__(self, expected, test_case, callable_obj=None, + def __init__(self, expected, test_case, callable_obj=_sentinel, expected_regex=None): _BaseTestCaseContext.__init__(self, test_case) self.expected = expected self.test_case = test_case - if callable_obj is not None: + if callable_obj is not _sentinel: try: self.obj_name = callable_obj.__name__ except AttributeError: @@ -151,11 +153,11 @@ def handle(self, name, callable_obj, args, kwargs): """ - If callable_obj is None, assertRaises/Warns is being used as a + If callable_obj is _sentinel, assertRaises/Warns is being used as a context manager, so check for a 'msg' kwarg and return self. - If callable_obj is not None, call it passing args and kwargs. + If callable_obj is not _sentinel, call it passing args and kwargs. """ - if callable_obj is None: + if callable_obj is _sentinel: self.msg = kwargs.pop('msg', None) return self with self: @@ -674,7 +676,7 @@ except UnicodeDecodeError: return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=None, *args, **kwargs): + def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -682,7 +684,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted or None, will return a + If called with callableObj omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -703,7 +705,7 @@ context = _AssertRaisesContext(excClass, self, callableObj) return context.handle('assertRaises', callableObj, args, kwargs) - def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): + def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs): """Fail unless a warning of class warnClass is triggered by callable_obj when invoked with arguments args and keyword arguments kwargs. If a different type of warning is @@ -711,7 +713,7 @@ warning filtering rules in effect, it might be silenced, printed out, or raised as an exception. - If called with callable_obj omitted or None, will return a + If called with callable_obj omitted, will return a context object used like this:: with self.assertWarns(SomeWarning): @@ -1219,7 +1221,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegex(self, expected_exception, expected_regex, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a raised exception matches a regex. Args: @@ -1238,7 +1240,7 @@ return context.handle('assertRaisesRegex', callable_obj, args, kwargs) def assertWarnsRegex(self, expected_warning, expected_regex, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1134,6 +1134,50 @@ self.assertRaises(self.failureException, self.assertRegex, 'saaas', r'aaaa') + def testAssertRaisesCallable(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + self.assertRaises(ExceptionMock, Stub) + # A tuple of exception classes is accepted + self.assertRaises((ValueError, ExceptionMock), Stub) + # *args and **kwargs also work + self.assertRaises(ValueError, int, '19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + self.assertRaises(ExceptionMock, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertRaises(ExceptionMock, None) + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesContext(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + with self.assertRaises(ExceptionMock): + Stub() + # A tuple of exception classes is accepted + with self.assertRaises((ValueError, ExceptionMock)) as cm: + Stub() + # The context manager exposes caught exception + self.assertIsInstance(cm.exception, ExceptionMock) + self.assertEqual(cm.exception.args[0], 'We expect') + # *args and **kwargs also work + with self.assertRaises(ValueError): + int('19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + with self.assertRaises(ExceptionMock): + pass + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + def testAssertRaisesRegex(self): class ExceptionMock(Exception): pass @@ -1143,6 +1187,8 @@ self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) + with self.assertRaises(TypeError): + self.assertRaisesRegex(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegex(self): self.assertRaisesRegex( @@ -1210,6 +1256,9 @@ # Failure when no warning is triggered with self.assertRaises(self.failureException): self.assertWarns(RuntimeWarning, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertWarns(RuntimeWarning, None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) @@ -1271,6 +1320,9 @@ with self.assertRaises(self.failureException): self.assertWarnsRegex(RuntimeWarning, "o+", lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertWarnsRegex(RuntimeWarning, "o+", None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ Library ------- +- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() checks are not longer successful if the callable is None. + - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:15:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:15:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTM0?= =?utf-8?q?=3A_assertRaises=28=29_and_assertRaisesRegexp=28=29_checks_are_?= =?utf-8?q?not_longer?= Message-ID: <20150506161511.98663.26531@psf.io> https://hg.python.org/cpython/rev/111ec3d5bf19 changeset: 95897:111ec3d5bf19 branch: 2.7 parent: 95891:fe340c2a220e user: Serhiy Storchaka date: Wed May 06 19:10:40 2015 +0300 summary: Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer successful if the callable is None. Added tests for assertRaises(). files: Lib/unittest/case.py | 12 +++-- Lib/unittest/test/test_case.py | 46 ++++++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -127,6 +127,8 @@ (expected_regexp.pattern, str(exc_value))) return True +def _sentinel(*args, **kwargs): + raise AssertionError('Should never called') class TestCase(object): """A class whose instances are single test cases. @@ -443,7 +445,7 @@ return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=None, *args, **kwargs): + def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -451,7 +453,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted or None, will return a + If called with callableObj omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -467,7 +469,7 @@ self.assertEqual(the_exception.error_code, 3) """ context = _AssertRaisesContext(excClass, self) - if callableObj is None: + if callableObj is _sentinel: return context with context: callableObj(*args, **kwargs) @@ -973,7 +975,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegexp(self, expected_exception, expected_regexp, - callable_obj=None, *args, **kwargs): + callable_obj=_sentinel, *args, **kwargs): """Asserts that the message in a raised exception matches a regexp. Args: @@ -987,7 +989,7 @@ if expected_regexp is not None: expected_regexp = re.compile(expected_regexp) context = _AssertRaisesContext(expected_exception, self, expected_regexp) - if callable_obj is None: + if callable_obj is _sentinel: return context with context: callable_obj(*args, **kwargs) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -954,6 +954,50 @@ self.assertRaises(self.failureException, self.assertRegexpMatches, 'saaas', r'aaaa') + def testAssertRaisesCallable(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + self.assertRaises(ExceptionMock, Stub) + # A tuple of exception classes is accepted + self.assertRaises((ValueError, ExceptionMock), Stub) + # *args and **kwargs also work + self.assertRaises(ValueError, int, '19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + self.assertRaises(ExceptionMock, lambda: 0) + # Failure when the function is None + with self.assertRaises(TypeError): + self.assertRaises(ExceptionMock, None) + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesContext(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + with self.assertRaises(ExceptionMock): + Stub() + # A tuple of exception classes is accepted + with self.assertRaises((ValueError, ExceptionMock)) as cm: + Stub() + # The context manager exposes caught exception + self.assertIsInstance(cm.exception, ExceptionMock) + self.assertEqual(cm.exception.args[0], 'We expect') + # *args and **kwargs also work + with self.assertRaises(ValueError): + int('19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + with self.assertRaises(ExceptionMock): + pass + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + def testAssertRaisesRegexp(self): class ExceptionMock(Exception): pass @@ -964,6 +1008,8 @@ self.assertRaisesRegexp(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegexp(ExceptionMock, 'expect$', Stub) self.assertRaisesRegexp(ExceptionMock, u'expect$', Stub) + with self.assertRaises(TypeError): + self.assertRaisesRegexp(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegexp(self): self.assertRaisesRegexp( diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer + successful if the callable is None. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:23:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:23:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_English_?= =?utf-8?q?in_error_message=2E?= Message-ID: <20150506162340.8149.61452@psf.io> https://hg.python.org/cpython/rev/66f698d08576 changeset: 95901:66f698d08576 branch: 3.4 parent: 95898:5418ab3e5556 user: Serhiy Storchaka date: Wed May 06 19:21:00 2015 +0300 summary: Fixed English in error message. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -130,7 +130,7 @@ raise self.test_case.failureException(msg) def _sentinel(*args, **kwargs): - raise AssertionError('Should never called') + raise AssertionError('Should never be called') class _AssertRaisesBaseContext(_BaseTestCaseContext): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:23:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:23:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_English_in_error_message=2E?= Message-ID: <20150506162340.84484.53114@psf.io> https://hg.python.org/cpython/rev/5f2ae82157af changeset: 95902:5f2ae82157af parent: 95899:679b5439b9a1 parent: 95901:66f698d08576 user: Serhiy Storchaka date: Wed May 06 19:22:55 2015 +0300 summary: Fixed English in error message. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -130,7 +130,7 @@ raise self.test_case.failureException(msg) def _sentinel(*args, **kwargs): - raise AssertionError('Should never called') + raise AssertionError('Should never be called') class _AssertRaisesBaseContext(_BaseTestCaseContext): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 6 18:23:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 06 May 2015 16:23:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_English_?= =?utf-8?q?in_error_message=2E?= Message-ID: <20150506162340.8938.793@psf.io> https://hg.python.org/cpython/rev/e8783c581928 changeset: 95900:e8783c581928 branch: 2.7 parent: 95897:111ec3d5bf19 user: Serhiy Storchaka date: Wed May 06 19:21:00 2015 +0300 summary: Fixed English in error message. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -128,7 +128,7 @@ return True def _sentinel(*args, **kwargs): - raise AssertionError('Should never called') + raise AssertionError('Should never be called') class TestCase(object): """A class whose instances are single test cases. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 7 03:20:21 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 07 May 2015 01:20:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjQu?= Message-ID: <20150507012021.25451.26689@psf.io> https://hg.python.org/cpython/rev/69e8ed66d4d6 changeset: 95904:69e8ed66d4d6 parent: 95902:5f2ae82157af parent: 95903:d0f7eaf9aac7 user: Zachary Ware date: Wed May 06 20:19:35 2015 -0500 summary: Merge from 3.4. files: Doc/library/asyncio-sync.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -196,9 +196,9 @@ .. method:: notify_all() - Wake up all threads waiting on this condition. This method acts like - :meth:`notify`, but wakes up all waiting threads instead of one. If the - calling thread has not acquired the lock when this method is called, a + Wake up all coroutines waiting on this condition. This method acts like + :meth:`notify`, but wakes up all waiting coroutines instead of one. If the + calling coroutine has not acquired the lock when this method is called, a :exc:`RuntimeError` is raised. .. method:: release() @@ -250,7 +250,7 @@ A semaphore manages an internal counter which is decremented by each :meth:`acquire` call and incremented by each :meth:`release` call. The counter can never go below zero; when :meth:`acquire` finds that it is zero, - it blocks, waiting until some other thread calls :meth:`release`. + it blocks, waiting until some other coroutine calls :meth:`release`. Semaphores also support the context management protocol. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 7 03:20:21 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 07 May 2015 01:20:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_copy/paste?= =?utf-8?q?_errors=2E?= Message-ID: <20150507012021.25433.80915@psf.io> https://hg.python.org/cpython/rev/d0f7eaf9aac7 changeset: 95903:d0f7eaf9aac7 branch: 3.4 parent: 95901:66f698d08576 user: Zachary Ware date: Wed May 06 20:19:06 2015 -0500 summary: Fix copy/paste errors. Basically, s/thread/coroutine/. files: Doc/library/asyncio-sync.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -196,9 +196,9 @@ .. method:: notify_all() - Wake up all threads waiting on this condition. This method acts like - :meth:`notify`, but wakes up all waiting threads instead of one. If the - calling thread has not acquired the lock when this method is called, a + Wake up all coroutines waiting on this condition. This method acts like + :meth:`notify`, but wakes up all waiting coroutines instead of one. If the + calling coroutine has not acquired the lock when this method is called, a :exc:`RuntimeError` is raised. .. method:: release() @@ -250,7 +250,7 @@ A semaphore manages an internal counter which is decremented by each :meth:`acquire` call and incremented by each :meth:`release` call. The counter can never go below zero; when :meth:`acquire` finds that it is zero, - it blocks, waiting until some other thread calls :meth:`release`. + it blocks, waiting until some other coroutine calls :meth:`release`. Semaphores also support the context management protocol. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 7 03:32:18 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 07 May 2015 01:32:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150507013218.98679.61886@psf.io> https://hg.python.org/cpython/rev/1bc0e1aad3dd changeset: 95906:1bc0e1aad3dd parent: 95902:5f2ae82157af parent: 95905:c79fd57f86b6 user: Benjamin Peterson date: Wed May 06 21:31:07 2015 -0400 summary: merge 3.4 files: Doc/library/asyncio-sync.rst | 8 ++++---- Doc/library/symtable.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -196,9 +196,9 @@ .. method:: notify_all() - Wake up all threads waiting on this condition. This method acts like - :meth:`notify`, but wakes up all waiting threads instead of one. If the - calling thread has not acquired the lock when this method is called, a + Wake up all coroutines waiting on this condition. This method acts like + :meth:`notify`, but wakes up all waiting coroutines instead of one. If the + calling coroutine has not acquired the lock when this method is called, a :exc:`RuntimeError` is raised. .. method:: release() @@ -250,7 +250,7 @@ A semaphore manages an internal counter which is decremented by each :meth:`acquire` call and incremented by each :meth:`release` call. The counter can never go below zero; when :meth:`acquire` finds that it is zero, - it blocks, waiting until some other thread calls :meth:`release`. + it blocks, waiting until some other coroutine calls :meth:`release`. Semaphores also support the context management protocol. diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -185,4 +185,4 @@ .. method:: get_namespace() Return the namespace bound to this name. If more than one namespace is - bound, a :exc:`ValueError` is raised. + bound, :exc:`ValueError` is raised. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 7 03:32:18 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 07 May 2015 01:32:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <20150507013218.25441.97933@psf.io> https://hg.python.org/cpython/rev/1ea01f2c5b10 changeset: 95907:1ea01f2c5b10 parent: 95906:1bc0e1aad3dd parent: 95904:69e8ed66d4d6 user: Benjamin Peterson date: Wed May 06 21:32:14 2015 -0400 summary: merge heads files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 7 03:32:18 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 07 May 2015 01:32:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_word_we?= =?utf-8?q?_don=27t_need?= Message-ID: <20150507013218.98669.15051@psf.io> https://hg.python.org/cpython/rev/c79fd57f86b6 changeset: 95905:c79fd57f86b6 branch: 3.4 parent: 95903:d0f7eaf9aac7 user: Benjamin Peterson date: Wed May 06 21:29:14 2015 -0400 summary: remove word we don't need files: Doc/library/symtable.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -189,4 +189,4 @@ .. method:: get_namespace() Return the namespace bound to this name. If more than one namespace is - bound, a :exc:`ValueError` is raised. + bound, :exc:`ValueError` is raised. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu May 7 10:38:41 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 07 May 2015 08:38:41 +0000 Subject: [Python-checkins] Daily reference leaks (1ea01f2c5b10): sum=3 Message-ID: <20150507083841.1913.16370@psf.io> results for 1ea01f2c5b10 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogCxh1Ic', '--timeout', '7200'] From python-checkins at python.org Thu May 7 17:22:31 2015 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 07 May 2015 15:22:31 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Discuss_issue_=23105_and_a_so?= =?utf-8?q?lution=2E?= Message-ID: <20150507152231.76600.37981@psf.io> https://hg.python.org/peps/rev/06fbe54fcfe1 changeset: 5833:06fbe54fcfe1 user: Guido van Rossum date: Thu May 07 08:22:27 2015 -0700 summary: Discuss issue #105 and a solution. files: pep-0484.txt | 42 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 41 insertions(+), 1 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -473,6 +473,46 @@ def leaves(self) -> List['Tree']: ... +A common use for forward references is when e.g. Django models are +needed in the signatures. Typically, each model is in a separate +file, and has methods that arguments whose type involves other models. +Because of the way circular imports work in Python, it is often not +possible to import all the needed models directly:: + + # File models/a.py + from models.b import B + class A(Model): + def foo(self, b: B): ... + + # File models/b.py + from models.a import A + class B(Model): + def bar(self, a: A): ... + + # File main.py + from a import A + from b import B + +Assuming main is imported first, this will fail with an ImportError at +the line ``from models.a import A`` in models/b.py, which is being +imported from models/a.py before a has defined class A. The solution +is to switch to module-only imports and reference the models by their +_module_._class_ name:: + + # File models/a.py + from models import b + class A(Model): + def foo(self, b: 'b.B'): ... + + # File models/b.py + from models import a + class B(Model): + def bar(self, a: 'a.A'): ... + + # File main.py + from a import A + from b import B + Union types ----------- @@ -1127,7 +1167,7 @@ assert ImSet.add.__annotations__ == {'a': 'ImSet', 'return': 'List[ImSet]'} -Such a ``__future__`` import statement will be proposed in a separate +Such a ``__future__`` import statement may be proposed in a separate PEP. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 8 00:42:20 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 07 May 2015 22:42:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_shorten_capsul?= =?utf-8?q?e_name_macro=3B_it_doesn=27t_need_to_be_so_long?= Message-ID: <20150507224220.8141.13837@psf.io> https://hg.python.org/cpython/rev/1556f2804456 changeset: 95908:1556f2804456 branch: 3.4 parent: 95905:c79fd57f86b6 user: Benjamin Peterson date: Thu May 07 18:41:47 2015 -0400 summary: shorten capsule name macro; it doesn't need to be so long files: Python/compile.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -206,7 +206,7 @@ static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; -#define COMPILER_CAPSULE_NAME_COMPILER_UNIT "compile.c compiler unit" +#define CAPSULE_NAME "compile.c compiler unit" PyObject * _Py_Mangle(PyObject *privateobj, PyObject *ident) @@ -608,7 +608,7 @@ /* Push the old compiler_unit on the stack. */ if (c->u) { - PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); + PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL); if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { Py_XDECREF(capsule); compiler_unit_free(u); @@ -644,7 +644,7 @@ n = PyList_GET_SIZE(c->c_stack) - 1; if (n >= 0) { capsule = PyList_GET_ITEM(c->c_stack, n); - c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(c->u); /* we are deleting from a list so this really shouldn't fail */ if (PySequence_DelItem(c->c_stack, n) < 0) @@ -674,7 +674,7 @@ PyObject *mangled, *capsule; capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(parent); if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 00:42:20 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 07 May 2015 22:42:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40?= Message-ID: <20150507224220.98689.4061@psf.io> https://hg.python.org/cpython/rev/1158f5d7a48e changeset: 95909:1158f5d7a48e parent: 95907:1ea01f2c5b10 parent: 95908:1556f2804456 user: Benjamin Peterson date: Thu May 07 18:42:16 2015 -0400 summary: Merge 3.4 files: Python/compile.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -202,7 +202,7 @@ static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; -#define COMPILER_CAPSULE_NAME_COMPILER_UNIT "compile.c compiler unit" +#define CAPSULE_NAME "compile.c compiler unit" PyObject * _Py_Mangle(PyObject *privateobj, PyObject *ident) @@ -604,7 +604,7 @@ /* Push the old compiler_unit on the stack. */ if (c->u) { - PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); + PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL); if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { Py_XDECREF(capsule); compiler_unit_free(u); @@ -640,7 +640,7 @@ n = PyList_GET_SIZE(c->c_stack) - 1; if (n >= 0) { capsule = PyList_GET_ITEM(c->c_stack, n); - c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(c->u); /* we are deleting from a list so this really shouldn't fail */ if (PySequence_DelItem(c->c_stack, n) < 0) @@ -670,8 +670,7 @@ PyObject *mangled, *capsule; capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - parent = (struct compiler_unit *)PyCapsule_GetPointer( - capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(parent); if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 03:58:25 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 08 May 2015 01:58:25 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_Updates_from_Petr_?= =?utf-8?q?Viktorin=2E?= Message-ID: <20150508015825.11950.51788@psf.io> https://hg.python.org/peps/rev/1687c8f840f5 changeset: 5834:1687c8f840f5 user: Berker Peksag date: Fri May 08 04:58:19 2015 +0300 summary: PEP 489: Updates from Petr Viktorin. Summary: - PyModuleExport -> PyModuleDef (which brings us down to two slot types, create & exec) - Removed "singleton modules" - Stated that PyModule_Create, PyState_FindModule, PyState_AddModule, PyState_RemoveModule will not work on slots-based modules. - Added a section on C-level callbacks - Clarified that if PyModuleExport_* returns NULL, it's as if it wasn't defined (i.e. falls back to PyInit) - Added API functions: PyModule_FromDefAndSpec, PyModule_ExecDef - Added PyModule_AddMethods and PyModule_AddDocstring helpers - Added PyMODEXPORT_FUNC macro for x-platform declarations of the export function - Added summary of API changes - Added example code for a backwards-compatible module - Changed modules ported in the initial implementation to "array" and "xx*" - Changed ImportErrors to SystemErrors in cases where the module is badly written (and to mirror what PyInit does now) - Several typo fixes and clarifications files: pep-0489.txt | 377 ++++++++++++++++++++------------------ 1 files changed, 198 insertions(+), 179 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -116,34 +116,46 @@ If defined, this symbol must resolve to a C function with the following signature:: - PyModuleExport* (*PyModuleExportFunction)(void) + PyModuleDef* (*PyModuleExportFunction)(void) -The function must return a pointer to a PyModuleExport structure. +For cross-platform compatibility, the function should be declared as:: + + PyMODEXPORT_FUNC PyModuleExport_(void) + +The function must return a pointer to a PyModuleDef structure. This structure must be available for the lifetime of the module created from it ? usually, it will be declared statically. -The PyModuleExport structure describes the new module, similarly to -PEP 384's PyType_Spec for types. The structure is defined as:: +Alternatively, this function can return NULL, in which case it is as if the +symbol was not defined ? see the "Legacy Init" section. + +The PyModuleDef structure will be changed to contain a list of slots, +similarly to PEP 384's PyType_Spec for types. +To keep binary compatibility, and avoid needing to introduce a new structure +(which would introduce additional supporting functions and per-module storage), +the currently unused m_reload pointer of PyModuleDef will be changed to +hold the slots. The structures are defined as:: typedef struct { int slot; void *value; - } PyModuleExport_Slot; + } PyModuleDef_Slot; - typedef struct { - const char* doc; - int flags; - PyModuleExport_Slot *slots; - } PyModuleExport; + typedef struct PyModuleDef { + PyModuleDef_Base m_base; + const char* m_name; + const char* m_doc; + Py_ssize_t m_size; + PyMethodDef *m_methods; + PyModuleDef_Slot *m_slots; /* changed from `inquiry m_reload;` */ + traverseproc m_traverse; + inquiry m_clear; + freefunc m_free; + } PyModuleDef; -The *doc* member specifies the module's docstring. - -The *flags* may currently be either 0 or ``PyModule_EXPORT_SINGLETON``, described -in "Singleton Modules" below. -Other flag values may be added in the future. - -The *slots* points to an array of PyModuleExport_Slot structures, terminated -by a slot with id set to 0 (i.e. ``{0, NULL}``). +The *m_slots* member must be either NULL, or point to an array of +PyModuleDef_Slot structures, terminated by a slot with id set to 0 +(i.e. ``{0, NULL}``). To specify a slot, a unique slot ID must be provided. New Python versions may introduce new slot IDs, but slot IDs will never be @@ -153,54 +165,34 @@ A slot's value pointer may not be NULL, unless specified otherwise in the slot's documentation. -The following slots are available, and described later: +The following slots are currently available, and described later: * Py_mod_create -* Py_mod_statedef -* Py_mod_methods * Py_mod_exec -Unknown slot IDs will cause the import to fail with ImportError. +Unknown slot IDs will cause the import to fail with SystemError. -.. note:: +When using the new import mechanism, m_size must not be negative. +Also, the *m_name* field of PyModuleDef will not be unused during importing; +the module name will be taken from the ModuleSpec. - An alternate proposal is to use PyModuleDef instead of PyModuleExport, - re-purposing the m_reload pointer to hold the slots:: - typedef struct PyModuleDef { - PyModuleDef_Base m_base; - const char* m_name; - const char* m_doc; - Py_ssize_t m_size; - PyMethodDef *m_methods; - PyModuleExport_Slot* m_slots; /* changed from `inquiry m_reload;` */ - traverseproc m_traverse; - inquiry m_clear; - freefunc m_free; - } PyModuleDef; +Module Creation +--------------- - This would simplify both the implementation and the API, at the expense - of renaming a member of PyModuleDef, and re-purposing a function pointer as - a data pointer. +Module creation ? that is, the implementation of +ExecutionLoader.create_module ? is governed by the Py_mod_create slot. - -Creation Slots --------------- - -The following slots affect module creation phase, i.e. they are hooks for -ExecutionLoader.create_module. -They serve to describe creation of the module object itself. - -Py_mod_create -............. +The Py_mod_create slot +...................... The Py_mod_create slot is used to support custom module subclasses. The value pointer must point to a function with the following signature:: - PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleExport *exp) + PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleDef *def) The function receives a ModuleSpec instance, as defined in PEP 451, -and the PyModuleExport structure. +and the PyModuleDef structure. It should return a new module object, or set an error and return NULL. @@ -211,15 +203,8 @@ There is no requirement for the returned object to be an instance of types.ModuleType. Any type can be used, as long as it supports setting and getting attributes, including at least the import-related attributes. - -If a module instance is returned from Py_mod_create, the import machinery will -store a pointer to PyModuleExport in the module object so that it may be -retrieved by PyModule_GetExport (described later). - -.. note:: - - If PyModuleDef is used instead of PyModuleExport, the def is stored - instead, to be retrieved by PyModule_GetDef. +However, only ModuleType instances support module-specific functionality +such as per-module state. Note that when this function is called, the module's entry in sys.modules is not populated yet. Attempting to import the same module again @@ -228,70 +213,48 @@ to not call user code from it. Multiple Py_mod_create slots may not be specified. If they are, import -will fail with ImportError. +will fail with SystemError. If Py_mod_create is not specified, the import machinery will create a normal -module object, as if by calling PyModule_Create. +module object by PyModule_New. The name is taken from *spec*. -Py_mod_statedef -............... +Post-creation steps +................... -The Py_mod_statedef slot is used to allocate per-module storage for C-level -state. -The value pointer must point to the following structure:: +If the Py_mod_create function returns an instance of types.ModuleType +(or subclass), or if a Py_mod_create slot is not present, the import machinery +will do the following steps after the module is created: - typedef struct PyModule_StateDef { - int size; - traverseproc traverse; - inquiry clear; - freefunc free; - } PyModule_StateDef; +* If *m_size* is specified, per-module state is allocated and made accessible + through PyModule_GetState +* The PyModuleDef is associated with the module, making it accessible to + PyModule_GetDef, and enabling the m_traverse, m_clear and m_free hooks. +* The docstring is set from m_doc. +* The module's functions are initialized from m_methods. -The meaning of the members is the same as for the corresponding members in -PyModuleDef. +If the Py_mod_create function does not return a module subclass, then m_size +must be 0 or negative, and m_traverse, m_clear and m_free must all be NULL. +Otherwise, SystemError is raised. -Specifying multiple Py_mod_statedef slots, or specifying Py_mod_statedef -together with Py_mod_create, will cause the import to fail with ImportError. -.. note:: +Module Execution +---------------- - If PyModuleDef is reused, this information is taken from PyModuleDef, - so the slot is not necessary. +Module execution -- that is, the implementation of +ExecutionLoader.exec_module -- is governed by "execution slots". +This PEP only adds one, Py_mod_exec, but others may be added in the future. - -Execution slots ---------------- - -The following slots affect module "execution" phase, i.e. they are processed in -ExecutionLoader.exec_module. -They serve to describe how the module is initialized ? e.g. how it is populated -with functions, types, or constants, and what import-time side effects -take place. - -These slots may be specified multiple times, and are processed in the order +Execution slots may be specified multiple times, and are processed in the order they appear in the slots array. - -When using the default import machinery, these slots are processed after +When using the default import machinery, they are processed after import-related attributes specified in PEP 451 [#pep-0451-attributes]_ (such as ``__name__`` or ``__loader__``) are set and the module is added to sys.modules. -Py_mod_methods -.............. - -This slot's value pointer must point to an array of PyMethodDef structures. -The specified methods are added to the module, like with PyModuleDef.m_methods. - -.. note:: - - If PyModuleDef is reused this slot is unnecessary, since methods are - already included in PyModuleDef. - - -Py_mod_exec -........... +The Py_mod_exec slot +.................... The entry in this slot must point to a function with the following signature:: @@ -299,12 +262,7 @@ It will be called to initialize a module. Usually, this amounts to setting the module's initial attributes. - -The "module" argument receives the module object to initialize. This will -always be the module object created from the corresponding PyModuleExport. -When this function is called, import-related attributes (such as ``__spec__``) -will have been set, and the module has already been added to sys.modules. - +The "module" argument receives the module object to initialize. If PyModuleExec replaces the module's entry in sys.modules, the new object will be used and returned by importlib machinery. @@ -319,9 +277,9 @@ Legacy Init ----------- -If the PyModuleExport function is not defined, the import machinery will try to -initialize the module using the "PyInit_" hook, -as described in PEP 3121. +If the PyModuleExport function is not defined, or if it returns NULL, the +import machinery will try to initialize the module using the +"PyInit_" hook, as described in PEP 3121. If the PyModuleExport function is defined, the PyInit function will be ignored. Modules requiring compatibility with previous versions of CPython may implement @@ -330,17 +288,56 @@ Modules using the legacy init API will be initialized entirely in the Loader.create_module step; Loader.exec_module will be a no-op. -.. XXX: Give example code for a backwards-compatible PyInit based on slots +A module that supports older CPython versions can be coded as:: -.. note:: + #define Py_LIMITED_API + #include - If PyModuleDef is reused, implementing the PyInit function becomes easy: + static int spam_exec(PyObject *module) { + PyModule_AddStringConstant(module, "food", "spam"); + return 0; + } - * call PyModule_Create with the PyModuleDef (m_reload was ignored in - previous Python versions, so the slots array will be ignored). - Alternatively, call the Py_mod_create function (keeping in mind that - the spec is not available with PyInit). - * call the Py_mod_exec function(s). + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_exec, spam_exec}, + {0, NULL} + }; + + static PyModuleDef spam_def = { + PyModuleDef_HEAD_INIT, /* m_base */ + "spam", /* m_name */ + PyDoc_STR("Utilities for cooking spam"), /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + spam_slots, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ + }; + + PyModuleDef* PyModuleExport_spam(void) { + return &spam_def; + } + + PyMODINIT_FUNC + PyInit_spam(void) { + PyObject *module; + module = PyModule_Create(&spam_def); + if (module == NULL) return NULL; + if (spam_exec(module) != 0) { + Py_DECREF(module); + return NULL; + } + return module; + } + +Note that this must be *compiled* on a new CPython version, but the resulting +shared library will be backwards compatible. +(Source-level compatibility is possible with preprocessor directives.) + +If a Py_mod_create slot is used, PyInit should call its function instead of +PyModule_Create. Keep in mind that the ModuleSpec object is not available in +the legacy init scheme. Subinterpreters and Interpreter Reloading @@ -357,70 +354,63 @@ A simple rule of thumb is: Do not define any static data, except built-in types with no mutable or user-settable class attributes. +Behavior of existing module creation functions +---------------------------------------------- -PyModule_GetExport ------------------- +The PyModule_Create function will fail when used on a PyModuleDef structure +with a non-NULL m_slots pointer. +The function doesn't have access to the ModuleSpec object necessary for +"new style" module creation. -To retrieve the PyModuleExport structure used to create a module, -a new function will be added:: +The PyState_FindModule function will return NULL, and PyState_AddModule +and PyState_RemoveModule will fail with SystemError. +PyState registration is disabled because multiple module objects may be +created from the same PyModuleDef. - PyModuleExport* PyModule_GetExport(PyObject *module) -The function returns NULL if the parameter is not a module object, or was not -created using PyModuleExport. +Module state and C-level callbacks +---------------------------------- -.. note:: +Due to the unavailability of PyState_FindModule, any function that needs access +to module-level state (including functions, classes or exceptions defined at +the module level) must receive a reference to the module object (or the +particular object it needs), either directly or indirectly. +This is currently difficult in two situations: - This is unnecessary if PyModuleDef is reused: the existing - PyModule_GetDef can be used instead. +* Methods of classes, which receive a reference to the class, but not to + the class's module +* Libraries with C-level callbacks, unless the callbacks can receive custom + data set at cllback registration +Fixing these cases is outside of the scope of this PEP, but will be needed for +the new mechanism to be useful to all modules. Proper fixes have been discussed +on the import-sig mailing list [#findmodule-discussion]_. -Singleton Modules ------------------ +As a rule of thumb, modules that rely on PyState_FindModule are, at the moment, +not good candidates for porting to the new mechanism. -Modules defined by PyModuleDef may be registered with PyState_AddModule, -and later retrieved with PyState_FindModule. -Under the new API, there is no one-to-one mapping between PyModuleSpec -and the module created from it. -In particular, multiple modules may be loaded from the same description. +New Functions +------------- -This means that there is no "global" instance of a module object. -Any C-level callbacks that need access to the module state need to be passed -a reference to the module object, either directly or indirectly. +A new function and macro will be added to implement module creation. +These are similar to PyModule_Create and PyModule_Create2, except they +take an additional ModuleSpec argument, and handle module definitions with +non-NULL slots:: + PyObject * PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec) + PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, + int module_api_version) -However, there are some modules that really need to be only loaded once: -typically ones that wrap a C library with global state. -These modules should set the PyModule_EXPORT_SINGLETON flag -in PyModuleExport.flags. When this flag is set, loading an additional -copy of the module after it has been loaded once will return the previously -loaded object. -This will be done on a low level, using _PyImport_FixupExtensionObject. -Additionally, the module will be automatically registered using -PyState_AddSingletonModule (see below) after execution slots are processed. +A new function will be added to run "execution slots" on a module:: -Singleton modules can be retrieved, registered or unregistered with -the interpreter state using three new functions, which parallel their -PyModuleDef counterparts, PyState_FindModule, PyState_AddModule, -and PyState_RemoveModule:: + PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def) - PyObject* PyState_FindSingletonModule(PyModuleExport *exp) - int PyState_AddSingletonModule(PyObject *module, PyModuleExport *exp) - int PyState_RemoveSingletonModule(PyModuleExport *exp) +Additionally, two helpers will be added for setting the docstring and +methods on a module:: - -.. note:: - - If PyModuleDef is used instead of PyModuleExport, the flag would be specified - as a slot with NULL value, i.e. ``{Py_mod_flag_singleton, NULL}``. - In this case, PyState_FindModule, PyState_AddModule and - PyState_RemoveModule can be used instead of the new functions. - -.. note:: - - Another possibility is to use PyModuleDef_Base in PyModuleExport, and - have PyState_FindModule and friends work with either of the two structures. + int PyModule_SetDocString(PyObject *, const char *) + int PyModule_AddFunctions(PyObject *, PyMethodDef *) Export Hook Name @@ -442,10 +432,10 @@ def export_hook_name(name): try: - encoded = b'_' + name.encode('ascii') - except UnicodeDecodeError: - encoded = b'U_' + name.encode('punycode').replace(b'-', b'_') - return b'PyModuleExport' + encoded + suffix = b'_' + name.encode('ascii') + except UnicodeEncodeError: + suffix = b'U_' + name.encode('punycode').replace(b'-', b'_') + return b'PyModuleExport' + suffix Examples: @@ -491,7 +481,9 @@ import importlib.util loader = importlib.machinery.ExtensionFileLoader(name, path) spec = importlib.util.spec_from_loader(name, loader) - return importlib.util.module_from_spec(spec) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) + return module On platforms that support symbolic links, these may be used to install one library under multiple names, exposing all exported modules to normal @@ -501,17 +493,41 @@ Testing and initial implementations ----------------------------------- -For testing, a new built-in module ``_testimportmodexport`` will be created. +For testing, a new built-in module ``_testmoduleexport`` will be created. The library will export several additional modules using the mechanism described in "Multiple modules in one library". The ``_testcapi`` module will be unchanged, and will use the old API indefinitely (or until the old API is removed). -The ``_csv`` and ``readline`` modules will be converted to the new API as +The ``array`` and ``xx*`` modules will be converted to the new API as part of the initial implementation. +API Changes and Additions +------------------------- + +New functions: + +* PyModule_FromDefAndSpec (macro) +* PyModule_FromDefAndSpec2 +* PyModule_ExecDef +* PyModule_SetDocString +* PyModule_AddFunctions + +New macros: + +* PyMODEXPORT_FUNC +* Py_mod_create +* Py_mod_exec + +New structures: + +* PyModuleDef_Slot + +PyModuleDef.m_reload changes to PyModuleDef.m_slots. + + Possible Future Extensions ========================== @@ -595,6 +611,9 @@ .. [#gh-patch] https://github.com/encukou/cpython/compare/master...encukou:pep489.patch +.. [#findmodule-discussion] + https://mail.python.org/pipermail/import-sig/2015-April/000959.html + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 8 08:30:23 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 06:30:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324000=3A_Improved?= =?utf-8?q?_Argument_Clinic=27s_mapping_of_converters_to_legacy?= Message-ID: <20150508063023.25435.71322@psf.io> https://hg.python.org/cpython/rev/36d5e04b6cfa changeset: 95910:36d5e04b6cfa user: Larry Hastings date: Thu May 07 23:30:09 2015 -0700 summary: Issue #24000: Improved Argument Clinic's mapping of converters to legacy "format units". Updated the documentation to match. files: Doc/howto/clinic.rst | 70 +++++++-------- Misc/NEWS | 3 + Modules/_dbmmodule.c | 9 +- Modules/_gdbmmodule.c | 4 +- Modules/arraymodule.c | 4 +- Modules/unicodedata.c | 4 +- Tools/clinic/clinic.py | 131 ++++++++++++++++------------ 7 files changed, 123 insertions(+), 102 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -758,6 +758,14 @@ In addition, some converters accept additional arguments. Here is a list of these arguments, along with their meanings: + ``accept`` + A set of Python types (and possibly pseudo-types); + this restricts the allowable Python argument to values of these types. + (This is not a general-purpose facility; as a rule it only supports + specific lists of types as shown in the legacy converter table.) + + To accept ``None``, add ``NoneType`` to this set. + ``bitwise`` Only supported for unsigned integers. The native integer value of this Python argument will be written to the parameter without any range checking, @@ -772,39 +780,27 @@ Only supported for strings. Specifies the encoding to use when converting this string from a Python str (Unicode) value into a C ``char *`` value. - ``length`` - Only supported for strings. If true, requests that the length of the - string be passed in to the impl function, just after the string parameter, - in a parameter named ``_length``. - - ``nullable`` - Only supported for strings. If true, this parameter may also be set to - ``None``, in which case the C parameter will be set to ``NULL``. ``subclass_of`` Only supported for the ``object`` converter. Requires that the Python value be a subclass of a Python type, as expressed in C. - ``types`` - Only supported for the ``object`` (and ``self``) converter. Specifies + ``type`` + Only supported for the ``object`` and ``self`` converters. Specifies the C type that will be used to declare the variable. Default value is ``"PyObject *"``. - ``types`` - A string containing a list of Python types (and possibly pseudo-types); - this restricts the allowable Python argument to values of these types. - (This is not a general-purpose facility; as a rule it only supports - specific lists of types as shown in the legacy converter table.) - ``zeroes`` Only supported for strings. If true, embedded NUL bytes (``'\\0'``) are - permitted inside the value. + permitted inside the value. The length of the string will be passed in + to the impl function, just after the string parameter, as a parameter named + ``_length``. Please note, not every possible combination of arguments will work. -Often these arguments are implemented internally by specific ``PyArg_ParseTuple`` +Usually these arguments are implemented by specific ``PyArg_ParseTuple`` *format units*, with specific behavior. For example, currently you cannot -call ``str`` and pass in ``zeroes=True`` without also specifying an ``encoding``; -although it's perfectly reasonable to think this would work, these semantics don't +call ``unsigned_short`` without also specifying ``bitwise=True``. +Although it's perfectly reasonable to think this would work, these semantics don't map to any existing format unit. So Argument Clinic doesn't support it. (Or, at least, not yet.) @@ -816,13 +812,13 @@ ``'B'`` ``unsigned_char(bitwise=True)`` ``'b'`` ``unsigned_char`` ``'c'`` ``char`` -``'C'`` ``int(types='str')`` +``'C'`` ``int(accept={str})`` ``'d'`` ``double`` ``'D'`` ``Py_complex`` -``'es#'`` ``str(encoding='name_of_encoding', length=True, zeroes=True)`` ``'es'`` ``str(encoding='name_of_encoding')`` -``'et#'`` ``str(encoding='name_of_encoding', types='bytes bytearray str', length=True)`` -``'et'`` ``str(encoding='name_of_encoding', types='bytes bytearray str')`` +``'es#'`` ``str(encoding='name_of_encoding', zeroes=True)`` +``'et'`` ``str(encoding='name_of_encoding', accept={bytes, bytearray, str})`` +``'et#'`` ``str(encoding='name_of_encoding', accept={bytes, bytearray, str}, zeroes=True)`` ``'f'`` ``float`` ``'h'`` ``short`` ``'H'`` ``unsigned_short(bitwise=True)`` @@ -832,27 +828,27 @@ ``'K'`` ``unsigned_PY_LONG_LONG(bitwise=True)`` ``'L'`` ``PY_LONG_LONG`` ``'n'`` ``Py_ssize_t`` +``'O'`` ``object`` ``'O!'`` ``object(subclass_of='&PySomething_Type')`` ``'O&'`` ``object(converter='name_of_c_function')`` -``'O'`` ``object`` ``'p'`` ``bool`` -``'s#'`` ``str(length=True)`` ``'S'`` ``PyBytesObject`` ``'s'`` ``str`` -``'s*'`` ``Py_buffer(types='str bytes bytearray buffer')`` -``'u#'`` ``Py_UNICODE(length=True)`` +``'s#'`` ``str(zeroes=True)`` +``'s*'`` ``Py_buffer(accept={buffer, str})`` +``'U'`` ``unicode`` ``'u'`` ``Py_UNICODE`` -``'U'`` ``unicode`` -``'w*'`` ``Py_buffer(types='bytearray rwbuffer')`` -``'y#'`` ``str(types='bytes', length=True)`` +``'u#'`` ``Py_UNICODE(zeroes=True)`` +``'w*'`` ``Py_buffer(accept={rwbuffer})`` ``'Y'`` ``PyByteArrayObject`` -``'y'`` ``str(types='bytes')`` +``'y'`` ``str(accept={bytes})`` +``'y#'`` ``str(accept={robuffer}, zeroes=True)`` ``'y*'`` ``Py_buffer`` -``'Z#'`` ``Py_UNICODE(nullable=True, length=True)`` -``'z#'`` ``str(nullable=True, length=True)`` -``'Z'`` ``Py_UNICODE(nullable=True)`` -``'z'`` ``str(nullable=True)`` -``'z*'`` ``Py_buffer(types='str bytes bytearray buffer', nullable=True)`` +``'Z'`` ``Py_UNICODE(accept={str, NoneType})`` +``'Z#'`` ``Py_UNICODE(accept={str, NoneType}, zeroes=True)`` +``'z'`` ``str(accept={str, NoneType})`` +``'z#'`` ``str(accept={str, NoneType}, zeroes=True)`` +``'z*'`` ``Py_buffer(accept={buffer, str, NoneType})`` ========= ================================================================================= As an example, here's our sample ``pickle.Pickler.dump`` using the proper diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -82,6 +82,9 @@ Tools/Demos ----------- +- Issue #24000: Improved Argument Clinic's mapping of converters to legacy + "format units". Updated the documentation to match. + - Issue #24001: Argument Clinic converters now use accept={type} instead of types={'type'} to specify the types the converter accepts. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -274,7 +274,7 @@ /*[clinic input] _dbm.dbm.get - key: str(accept={str, robuffer}, length=True) + key: str(accept={str, robuffer}, zeroes=True) default: object(c_default="NULL") = b'' / @@ -284,7 +284,8 @@ static PyObject * _dbm_dbm_get_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=b44f95eba8203d93 input=3c7c1afd9c508457]*/ +/*[clinic end generated code: output=b44f95eba8203d93 input=a3a279957f85eb6d]*/ +/*[clinic end generated code: output=4f5c0e523eaf1251 input=9402c0af8582dc69]*/ { datum dbm_key, val; @@ -301,7 +302,7 @@ /*[clinic input] _dbm.dbm.setdefault - key: str(accept={str, robuffer}, length=True) + key: str(accept={str, robuffer}, zeroes=True) default: object(c_default="NULL") = b'' / @@ -314,7 +315,7 @@ _dbm_dbm_setdefault_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=52545886cf272161 input=a66fcb7f18ee2f50]*/ +/*[clinic end generated code: output=52545886cf272161 input=bf40c48edaca01d6]*/ { datum dbm_key, val; Py_ssize_t tmp_size; diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -383,7 +383,7 @@ /*[clinic input] _gdbm.gdbm.nextkey - key: str(accept={str, robuffer}, length=True) + key: str(accept={str, robuffer}, zeroes=True) / Returns the key that follows key in the traversal. @@ -400,7 +400,7 @@ static PyObject * _gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key, Py_ssize_clean_t key_length) -/*[clinic end generated code: output=192ab892de6eb2f6 input=1eb2ff9b4b0e6ffd]*/ +/*[clinic end generated code: output=192ab892de6eb2f6 input=1f1606943614e36f]*/ { PyObject *v; datum dbm_key, nextkey; diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1673,7 +1673,7 @@ /*[clinic input] array.array.fromunicode - ustr: Py_UNICODE(length=True) + ustr: Py_UNICODE(zeroes=True) / Extends this array with data from the unicode string ustr. @@ -1686,7 +1686,7 @@ static PyObject * array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, Py_ssize_clean_t ustr_length) -/*[clinic end generated code: output=ebb72fc16975e06d input=56bcedb5ef70139f]*/ +/*[clinic end generated code: output=ebb72fc16975e06d input=150f00566ffbca6e]*/ { char typecode; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1215,7 +1215,7 @@ unicodedata.UCD.lookup self: self - name: str(accept={str, robuffer}, length=True) + name: str(accept={str, robuffer}, zeroes=True) / Look up character by name. @@ -1227,7 +1227,7 @@ static PyObject * unicodedata_UCD_lookup_impl(PyObject *self, const char *name, Py_ssize_clean_t name_length) -/*[clinic end generated code: output=765cb8186788e6be input=2dfe682c2491447a]*/ +/*[clinic end generated code: output=765cb8186788e6be input=a557be0f8607a0d6]*/ { Py_UCS4 code; unsigned int index; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2644,64 +2644,85 @@ class rwbuffer: pass class robuffer: pass - at add_legacy_c_converter('s#', accept={str, robuffer}, length=True) - at add_legacy_c_converter('y', accept={robuffer}) - at add_legacy_c_converter('y#', accept={robuffer}, length=True) - at add_legacy_c_converter('z', accept={str, NoneType}) - at add_legacy_c_converter('z#', accept={str, NoneType}, length=True) -# add_legacy_c_converter not supported for es, es#, et, et# -# because of their extra encoding argument +def str_converter_key(types, encoding, zeroes): + return (frozenset(types), bool(encoding), bool(zeroes)) + +str_converter_argument_map = {} + class str_converter(CConverter): type = 'const char *' default_type = (str, Null, NoneType) format_unit = 's' - def converter_init(self, *, encoding=None, accept={str}, length=False, zeroes=False): - - self.length = bool(length) - - is_b_or_ba = accept == {bytes, bytearray} - is_b_or_ba_or_none = accept == {bytes, bytearray, NoneType} - is_str = accept == {str} - is_str_or_none = accept == {str, NoneType} - is_robuffer = accept == {robuffer} - is_str_or_robuffer = accept == {str, robuffer} - is_str_or_robuffer_or_none = accept == {str, robuffer, NoneType} - - format_unit = None - + def converter_init(self, *, accept={str}, encoding=None, zeroes=False): + + key = str_converter_key(accept, encoding, zeroes) + format_unit = str_converter_argument_map.get(key) + if not format_unit: + fail("str_converter: illegal combination of arguments", key) + + self.format_unit = format_unit + self.length = bool(zeroes) if encoding: + if self.default not in (Null, None, unspecified): + fail("str_converter: Argument Clinic doesn't support default values for encoded strings") self.encoding = encoding - - if is_str and not length and not zeroes: - format_unit = 'es' - elif is_str_or_none and length and zeroes: - format_unit = 'es#' - elif is_b_or_ba and not length and not zeroes: - format_unit = 'et' - elif is_b_or_ba_or_none and length and zeroes: - format_unit = 'et#' - - else: - if zeroes: - fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)") - - if is_str and not length: - format_unit = 's' - elif is_str_or_none and not length: - format_unit = 'z' - elif is_robuffer and not length: - format_unit = 'y' - elif is_robuffer and length: - format_unit = 'y#' - elif is_str_or_robuffer and length: - format_unit = 's#' - elif is_str_or_robuffer_or_none and length: - format_unit = 'z#' - - if not format_unit: - fail("str_converter: illegal combination of arguments") - self.format_unit = format_unit + self.type = 'char *' + # sorry, clinic can't support preallocated buffers + # for es# and et# + self.c_default = "NULL" + + def cleanup(self): + if self.encoding: + name = ensure_legal_c_identifier(self.name) + return "".join(["if (", name, ")\n PyMem_FREE(", name, ");\n"]) + +# +# This is the fourth or fifth rewrite of registering all the +# crazy string converter format units. Previous approaches hid +# bugs--generally mismatches between the semantics of the format +# unit and the arguments necessary to represent those semantics +# properly. Hopefully with this approach we'll get it 100% right. +# +# The r() function (short for "register") both registers the +# mapping from arguments to format unit *and* registers the +# legacy C converter for that format unit. +# +def r(format_unit, *, accept, encoding=False, zeroes=False): + if not encoding and format_unit != 's': + # add the legacy c converters here too. + # + # note: add_legacy_c_converter can't work for + # es, es#, et, or et# + # because of their extra encoding argument + # + # also don't add the converter for 's' because + # the metaclass for CConverter adds it for us. + kwargs = {} + if accept != {str}: + kwargs['accept'] = accept + if zeroes: + kwargs['zeroes'] = True + added_f = functools.partial(str_converter, **kwargs) + legacy_converters[format_unit] = added_f + + d = str_converter_argument_map + key = str_converter_key(accept, encoding, zeroes) + if key in d: + sys.exit("Duplicate keys specified for str_converter_argument_map!") + d[key] = format_unit + +r('es', encoding=True, accept={str}) +r('es#', encoding=True, zeroes=True, accept={str}) +r('et', encoding=True, accept={bytes, bytearray, str}) +r('et#', encoding=True, zeroes=True, accept={bytes, bytearray, str}) +r('s', accept={str}) +r('s#', zeroes=True, accept={robuffer, str}) +r('y', accept={robuffer}) +r('y#', zeroes=True, accept={robuffer}) +r('z', accept={str, NoneType}) +r('z#', zeroes=True, accept={robuffer, str, NoneType}) +del r class PyBytesObject_converter(CConverter): @@ -2719,17 +2740,17 @@ default_type = (str, Null, NoneType) format_unit = 'U' - at add_legacy_c_converter('u#', length=True) + at add_legacy_c_converter('u#', zeroes=True) @add_legacy_c_converter('Z', accept={str, NoneType}) - at add_legacy_c_converter('Z#', accept={str, NoneType}, length=True) + at add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True) class Py_UNICODE_converter(CConverter): type = 'Py_UNICODE *' default_type = (str, Null, NoneType) format_unit = 'u' - def converter_init(self, *, accept={str}, length=False): + def converter_init(self, *, accept={str}, zeroes=False): format_unit = 'Z' if accept=={str, NoneType} else 'u' - if length: + if zeroes: format_unit += '#' self.length = True self.format_unit = format_unit -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri May 8 10:40:15 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 08 May 2015 08:40:15 +0000 Subject: [Python-checkins] Daily reference leaks (1158f5d7a48e): sum=8 Message-ID: <20150508084015.1928.82400@psf.io> results for 1158f5d7a48e on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [2, 0, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogcWI0jS', '--timeout', '7200'] From python-checkins at python.org Fri May 8 13:15:23 2015 From: python-checkins at python.org (andrew.svetlov) Date: Fri, 08 May 2015 11:15:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40?= Message-ID: <20150508111521.76616.27910@psf.io> https://hg.python.org/cpython/rev/e5ff10873d0f changeset: 95912:e5ff10873d0f parent: 95910:36d5e04b6cfa parent: 95911:7eb524cbe6e5 user: Andrew Svetlov date: Fri May 08 14:15:11 2015 +0300 summary: Merge 3.4 files: Doc/library/asyncio-sync.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -275,7 +275,7 @@ Returns ``True`` if semaphore can not be acquired immediately. - .. coroutinemethod:: release() + .. method:: release() Release a semaphore, incrementing the internal counter by one. When it was zero on entry and another coroutine is waiting for it to become @@ -291,4 +291,3 @@ This raises :exc:`ValueError` in :meth:`~Semaphore.release` if it would increase the value above the initial value. - -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 13:15:23 2015 From: python-checkins at python.org (andrew.svetlov) Date: Fri, 08 May 2015 11:15:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogRml4IGRvYzogYXN5?= =?utf-8?q?ncio=2ESemaphore=2Erelease=28=29_actually_is_a_regular_function?= =?utf-8?q?=2C_not?= Message-ID: <20150508111520.84478.90911@psf.io> https://hg.python.org/cpython/rev/7eb524cbe6e5 changeset: 95911:7eb524cbe6e5 branch: 3.4 parent: 95908:1556f2804456 user: Andrew Svetlov date: Fri May 08 14:13:41 2015 +0300 summary: Fix doc: asyncio.Semaphore.release() actually is a regular function, not coroutine files: Doc/library/asyncio-sync.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -275,7 +275,7 @@ Returns ``True`` if semaphore can not be acquired immediately. - .. coroutinemethod:: release() + .. method:: release() Release a semaphore, incrementing the internal counter by one. When it was zero on entry and another coroutine is waiting for it to become @@ -291,4 +291,3 @@ This raises :exc:`ValueError` in :meth:`~Semaphore.release` if it would increase the value above the initial value. - -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 15:59:32 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 13:59:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjQu?= Message-ID: <20150508135932.11924.8926@psf.io> https://hg.python.org/cpython/rev/a3ee6990daea changeset: 95914:a3ee6990daea parent: 95912:e5ff10873d0f parent: 95913:bff966aed6a3 user: Larry Hastings date: Fri May 08 06:58:56 2015 -0700 summary: Merge from 3.4. files: Lib/test/test_zipfile.py | 5 +++-- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -750,9 +750,10 @@ self.assertTrue('SyntaxError' not in reportStr) # then check that the filter works on individual files + def filter(path): + return not os.path.basename(path).startswith("bad") with captured_stdout() as reportSIO, self.assertWarns(UserWarning): - zipfp.writepy(packagedir, filterfunc=lambda fn: - 'bad' not in fn) + zipfp.writepy(packagedir, filterfunc=filter) reportStr = reportSIO.getvalue() if reportStr: print(reportStr) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -69,6 +69,9 @@ Tests ----- +- Issue #21520: test_zipfile no longer fails if the word 'bad' appears + anywhere in the name of the current directory. + - Issue #9517: Move script_helper into the support package. Patch by Christie Wilson. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 15:59:34 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 13:59:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNTIw?= =?utf-8?q?=3A_test=5Fzipfile_no_longer_fails_if_the_word_=27bad=27_appear?= =?utf-8?q?s?= Message-ID: <20150508135931.14374.84311@psf.io> https://hg.python.org/cpython/rev/bff966aed6a3 changeset: 95913:bff966aed6a3 branch: 3.4 parent: 95911:7eb524cbe6e5 user: Larry Hastings date: Fri May 08 06:54:58 2015 -0700 summary: Issue #21520: test_zipfile no longer fails if the word 'bad' appears anywhere in the name of the current directory. files: Lib/test/test_zipfile.py | 5 +++-- Misc/NEWS | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -719,9 +719,10 @@ self.assertTrue('SyntaxError' not in reportStr) # then check that the filter works on individual files + def filter(path): + return not os.path.basename(path).startswith("bad") with captured_stdout() as reportSIO, self.assertWarns(UserWarning): - zipfp.writepy(packagedir, filterfunc=lambda fn: - 'bad' not in fn) + zipfp.writepy(packagedir, filterfunc=filter) reportStr = reportSIO.getvalue() if reportStr: print(reportStr) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -228,6 +228,9 @@ Tests ----- +- Issue #21520: test_zipfile no longer fails if the word 'bad' appears + anywhere in the name of the current directory. + - Issue #23799: Added test.support.start_threads() for running and cleaning up multiple threads. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 16:45:24 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 14:45:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIwMjc0?= =?utf-8?q?=3A_Remove_ignored_and_erroneous_=22kwargs=22_parameters_from_t?= =?utf-8?q?hree?= Message-ID: <20150508144524.76604.15543@psf.io> https://hg.python.org/cpython/rev/4c860369b6c2 changeset: 95915:4c860369b6c2 branch: 3.4 parent: 95913:bff966aed6a3 user: Larry Hastings date: Fri May 08 07:37:49 2015 -0700 summary: Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. files: Misc/NEWS | 3 +++ Modules/_sqlite/connection.c | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #24096: Make warnings.warn_explicit more robust against mutation of the warnings.filters list. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1287,7 +1287,7 @@ return NULL; } -PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1316,7 +1316,7 @@ return cursor; } -PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1345,7 +1345,7 @@ return cursor; } -PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 16:45:24 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 14:45:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320274=3A_When_calling_a_=5Fsqlite=2EConnection?= =?utf-8?q?=2C_it_now_complains_if_passed?= Message-ID: <20150508144524.98679.14543@psf.io> https://hg.python.org/cpython/rev/3e9f4f3c7fa7 changeset: 95916:3e9f4f3c7fa7 parent: 95914:a3ee6990daea parent: 95915:4c860369b6c2 user: Larry Hastings date: Fri May 08 07:45:10 2015 -0700 summary: Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. Also: merge related change from 3.4, also reported on Issue #20274. files: Misc/NEWS | 6 ++++++ Modules/_sqlite/connection.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #20274: When calling a _sqlite.Connection, it now complains if passed + any keyword arguments. Previously it silently ignored them. + +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #2292: PEP 448: Additional Unpacking Generalizations. - Issue #24096: Make warnings.warn_explicit more robust against mutation of the diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1241,6 +1241,9 @@ return NULL; } + if (!_PyArg_NoKeywords(MODULE_NAME ".Connection()", kwargs)) + return NULL; + if (!PyArg_ParseTuple(args, "O", &sql)) return NULL; @@ -1287,7 +1290,7 @@ return NULL; } -PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1316,7 +1319,7 @@ return cursor; } -PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1345,7 +1348,7 @@ return cursor; } -PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 18:39:36 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 08 May 2015 16:39:36 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_2=2E7=2E10_dates?= Message-ID: <20150508163936.11944.94532@psf.io> https://hg.python.org/peps/rev/1ee1f1c9fdd1 changeset: 5835:1ee1f1c9fdd1 user: Benjamin Peterson date: Fri May 08 12:39:35 2015 -0400 summary: 2.7.10 dates files: pep-0373.txt | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/pep-0373.txt b/pep-0373.txt --- a/pep-0373.txt +++ b/pep-0373.txt @@ -71,7 +71,9 @@ Planned future release dates: -- 2.7.10 June 2015 +- 2.7.10rc1 2015-05-09 +- 2.7.10 2015-05-23 +- 2.7.11 December, 2015 - beyond this date, releases as needed Dates of previous maintenance releases: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 8 18:56:48 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 08 May 2015 16:56:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMjc0?= =?utf-8?q?=3A_When_calling_a_=5Fsqlite=2EConnection=2C_it_now_complains_i?= =?utf-8?q?f_passed?= Message-ID: <20150508165647.98675.81893@psf.io> https://hg.python.org/cpython/rev/c91d135b0776 changeset: 95917:c91d135b0776 branch: 2.7 parent: 95900:e8783c581928 user: Larry Hastings date: Fri May 08 09:56:29 2015 -0700 summary: Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. Also: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. files: Misc/NEWS | 6 ++++++ Modules/_sqlite/connection.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #20274: When calling a _sqlite.Connection, it now complains if passed + any keyword arguments. Previously it silently ignored them. + +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #23629: Fix the default __sizeof__ implementation for variable-sized objects. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1192,6 +1192,9 @@ return NULL; } + if (!_PyArg_NoKeywords(MODULE_NAME ".Connection()", kwargs)) + return NULL; + if (!PyArg_ParseTuple(args, "O", &sql)) { return NULL; } @@ -1242,7 +1245,7 @@ return (PyObject*)statement; } -PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1271,7 +1274,7 @@ return cursor; } -PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; @@ -1300,7 +1303,7 @@ return cursor; } -PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) { PyObject* cursor = 0; PyObject* result = 0; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 23:47:28 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 08 May 2015 21:47:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Minor_updates_to_the_OS_X_installer_ReadMe=2Ertf=2E?= Message-ID: <20150508214727.1945.13287@psf.io> https://hg.python.org/cpython/rev/b9b772a91db0 changeset: 95920:b9b772a91db0 parent: 95916:3e9f4f3c7fa7 parent: 95919:71ee988111b2 user: Ned Deily date: Fri May 08 14:46:53 2015 -0700 summary: Minor updates to the OS X installer ReadMe.rtf. files: Mac/BuildScript/resources/ReadMe.rtf | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160 +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -23,8 +23,8 @@ \i $MACOSX_DEPLOYMENT_TARGET \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL -\i0 below. -\b \ul \ +\i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. +\b \ul \ulc0 \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 23:47:28 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 08 May 2015 21:47:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Minor_updates_?= =?utf-8?q?to_the_OS_X_installer_ReadMe=2Ertf=2E?= Message-ID: <20150508214727.7812.74248@psf.io> https://hg.python.org/cpython/rev/71ee988111b2 changeset: 95919:71ee988111b2 branch: 3.4 parent: 95915:4c860369b6c2 user: Ned Deily date: Fri May 08 14:42:32 2015 -0700 summary: Minor updates to the OS X installer ReadMe.rtf. files: Mac/BuildScript/resources/ReadMe.rtf | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160 +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww13380\viewh14600\viewkind0 @@ -23,8 +23,8 @@ \i $MACOSX_DEPLOYMENT_TARGET \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL -\i0 below. -\b \ul \ +\i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. +\b \ul \ulc0 \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications \b0 \ulnone \ @@ -125,7 +125,7 @@ \i0 . To solve this problem, as of 3.4.3 the \i 10.5+ 32-bit-only python.org variant \i0 is linked with a private copy of -\i OpenSSL 1.0.1 +\i OpenSSL 1.0 \i0 ; it consults the same default certificate directory, \f1 /System/Library/OpenSSL \f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 8 23:47:28 2015 From: python-checkins at python.org (ned.deily) Date: Fri, 08 May 2015 21:47:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Minor_updates_?= =?utf-8?q?to_the_OS_X_installer_ReadMe=2Ertf=2E?= Message-ID: <20150508214727.84488.59523@psf.io> https://hg.python.org/cpython/rev/212798281f14 changeset: 95918:212798281f14 branch: 2.7 user: Ned Deily date: Fri May 08 14:42:07 2015 -0700 summary: Minor updates to the OS X installer ReadMe.rtf. files: Mac/BuildScript/resources/ReadMe.rtf | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160 +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww15240\viewh15540\viewkind0 @@ -23,7 +23,7 @@ \i $MACOSX_DEPLOYMENT_TARGET \i0 variant. Unless you are installing to an 10.5 system or you need to build applications that can run on 10.5 systems, use the 10.6 variant if possible. There are some additional operating system functions that are supported starting with 10.6 and you may see better performance using 64-bit mode. By default, Python will automatically run in 64-bit mode if your system supports it. Also see \i Certificate verification and OpenSSL -\i0 below. +\i0 below. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in OS X itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. \b \ul \ \ Update your version of Tcl/Tk to use IDLE or other Tk applications @@ -111,7 +111,7 @@ \i0 . To solve this problem, as of 2.7.9 the \i 10.5+ 32-bit-only python.org variant \i0 is linked with a private copy of -\i OpenSSL 1.0.1 +\i OpenSSL 1.0 \i0 ; it consults the same default certificate directory, \f1 /System/Library/OpenSSL \f0 . As before, it is still necessary to manage certificates yourself when you use this Python variant and, with certificate verification now enabled by default, you may now need to take additional steps to ensure your Python programs have access to CA certificates you trust. If you use this Python variant to build standalone applications with third-party tools like {\field{\*\fldinst{HYPERLINK "https://pypi.python.org/pypi/py2app/"}}{\fldrslt -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:29:03 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 09 May 2015 01:29:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Upgrade_setupt?= =?utf-8?q?ools_to_15=2E2?= Message-ID: <20150509012903.76594.79725@psf.io> https://hg.python.org/cpython/rev/5c13ead2002a changeset: 95921:5c13ead2002a branch: 2.7 parent: 95918:212798281f14 user: Donald Stufft date: Fri May 08 21:28:57 2015 -0400 summary: Upgrade setuptools to 15.2 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,7 +12,7 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.0" +_SETUPTOOLS_VERSION = "15.2" _PIP_VERSION = "6.1.1" diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl deleted file mode 100644 index 578ff3c31c7db40f8777aa1272566362a3793956..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f153ed376684275e08fcfebdb2de8352fb074171 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:30:12 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 09 May 2015 01:30:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Upgrade_setupt?= =?utf-8?q?ools_to_15=2E2?= Message-ID: <20150509013012.7792.7023@psf.io> https://hg.python.org/cpython/rev/b11073fba1d4 changeset: 95922:b11073fba1d4 branch: 3.4 parent: 95919:71ee988111b2 user: Donald Stufft date: Fri May 08 21:30:04 2015 -0400 summary: Upgrade setuptools to 15.2 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,7 +8,7 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.0" +_SETUPTOOLS_VERSION = "15.2" _PIP_VERSION = "6.1.1" diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl deleted file mode 100644 index 578ff3c31c7db40f8777aa1272566362a3793956..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f153ed376684275e08fcfebdb2de8352fb074171 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:30:42 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 09 May 2015 01:30:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge_-_upgrade_setuptools_to_15=2E2?= Message-ID: <20150509013042.8135.49483@psf.io> https://hg.python.org/cpython/rev/8b940a130c47 changeset: 95923:8b940a130c47 parent: 95920:b9b772a91db0 parent: 95922:b11073fba1d4 user: Donald Stufft date: Fri May 08 21:30:37 2015 -0400 summary: merge - upgrade setuptools to 15.2 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,7 +8,7 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.0" +_SETUPTOOLS_VERSION = "15.2" _PIP_VERSION = "6.1.1" diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl deleted file mode 100644 index 578ff3c31c7db40f8777aa1272566362a3793956..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f153ed376684275e08fcfebdb2de8352fb074171 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:31:41 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 01:31:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_fix_libffi_com?= =?utf-8?q?pilation_on_FreeBSD_=28=2323042=29?= Message-ID: <20150509013141.11926.98752@psf.io> https://hg.python.org/cpython/rev/96a7b401d5e4 changeset: 95924:96a7b401d5e4 branch: 2.7 parent: 95921:5c13ead2002a user: Benjamin Peterson date: Fri May 08 21:31:36 2015 -0400 summary: fix libffi compilation on FreeBSD (#23042) Patch from Marc-Andre Lemburg. files: Modules/_ctypes/libffi/src/x86/ffi.c | 48 ++++++++++------ 1 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/libffi/src/x86/ffi.c b/Modules/_ctypes/libffi/src/x86/ffi.c --- a/Modules/_ctypes/libffi/src/x86/ffi.c +++ b/Modules/_ctypes/libffi/src/x86/ffi.c @@ -331,10 +331,11 @@ extern int ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); -#else +#elif defined(X86_WIN32) extern void ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); +#else extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); #endif @@ -376,16 +377,9 @@ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; -#else -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif case FFI_STDCALL: ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -419,6 +413,11 @@ ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); @@ -787,28 +786,36 @@ /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ +#ifdef X86_WIN64 + if (rvalue == NULL + && cif->flags == FFI_TYPE_STRUCT + && cif->rtype->size != 1 && cif->rtype->size != 2 + && cif->rtype->size != 4 && cif->rtype->size != 8) + { + ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); + } +#else if (rvalue == NULL && (cif->flags == FFI_TYPE_STRUCT || cif->flags == FFI_TYPE_MS_STRUCT)) { ecif.rvalue = alloca(cif->rtype->size); } +#endif else ecif.rvalue = rvalue; switch (cif->abi) { -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); +#ifdef X86_WIN64 + case FFI_WIN64: + ffi_call_win64(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif -#ifndef X86_WIN64 case FFI_STDCALL: ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -835,13 +842,18 @@ ++passed_regs; } if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; + abi = FFI_THISCALL; if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; + abi = FFI_STDCALL; ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:32:48 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 01:32:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_fix_libffi_com?= =?utf-8?q?pilation_on_FreeBSD_=28=2323042=29?= Message-ID: <20150509013248.11934.2535@psf.io> https://hg.python.org/cpython/rev/a04b3de18c4c changeset: 95925:a04b3de18c4c branch: 3.4 parent: 95919:71ee988111b2 user: Benjamin Peterson date: Fri May 08 21:31:36 2015 -0400 summary: fix libffi compilation on FreeBSD (#23042) Patch from Marc-Andre Lemburg. files: Modules/_ctypes/libffi/src/x86/ffi.c | 48 ++++++++++------ 1 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/libffi/src/x86/ffi.c b/Modules/_ctypes/libffi/src/x86/ffi.c --- a/Modules/_ctypes/libffi/src/x86/ffi.c +++ b/Modules/_ctypes/libffi/src/x86/ffi.c @@ -331,10 +331,11 @@ extern int ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); -#else +#elif defined(X86_WIN32) extern void ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); +#else extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); #endif @@ -376,16 +377,9 @@ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; -#else -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif case FFI_STDCALL: ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -419,6 +413,11 @@ ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); @@ -787,28 +786,36 @@ /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ +#ifdef X86_WIN64 + if (rvalue == NULL + && cif->flags == FFI_TYPE_STRUCT + && cif->rtype->size != 1 && cif->rtype->size != 2 + && cif->rtype->size != 4 && cif->rtype->size != 8) + { + ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); + } +#else if (rvalue == NULL && (cif->flags == FFI_TYPE_STRUCT || cif->flags == FFI_TYPE_MS_STRUCT)) { ecif.rvalue = alloca(cif->rtype->size); } +#endif else ecif.rvalue = rvalue; switch (cif->abi) { -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); +#ifdef X86_WIN64 + case FFI_WIN64: + ffi_call_win64(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif -#ifndef X86_WIN64 case FFI_STDCALL: ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -835,13 +842,18 @@ ++passed_regs; } if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; + abi = FFI_THISCALL; if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; + abi = FFI_STDCALL; ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:32:49 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 01:32:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_merge_heads?= Message-ID: <20150509013249.76592.53173@psf.io> https://hg.python.org/cpython/rev/c78137bff841 changeset: 95926:c78137bff841 branch: 3.4 parent: 95925:a04b3de18c4c parent: 95922:b11073fba1d4 user: Benjamin Peterson date: Fri May 08 21:32:19 2015 -0400 summary: merge heads files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,7 +8,7 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.0" +_SETUPTOOLS_VERSION = "15.2" _PIP_VERSION = "6.1.1" diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl deleted file mode 100644 index 578ff3c31c7db40f8777aa1272566362a3793956..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f153ed376684275e08fcfebdb2de8352fb074171 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 03:32:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 01:32:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjMwNDIp?= Message-ID: <20150509013254.84480.85914@psf.io> https://hg.python.org/cpython/rev/987b30a88653 changeset: 95927:987b30a88653 parent: 95923:8b940a130c47 parent: 95926:c78137bff841 user: Benjamin Peterson date: Fri May 08 21:32:36 2015 -0400 summary: merge 3.4 (#23042) files: Modules/_ctypes/libffi/src/x86/ffi.c | 48 ++++++++++------ 1 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Modules/_ctypes/libffi/src/x86/ffi.c b/Modules/_ctypes/libffi/src/x86/ffi.c --- a/Modules/_ctypes/libffi/src/x86/ffi.c +++ b/Modules/_ctypes/libffi/src/x86/ffi.c @@ -331,10 +331,11 @@ extern int ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); -#else +#elif defined(X86_WIN32) extern void ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); +#else extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); #endif @@ -376,16 +377,9 @@ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; -#else -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif case FFI_STDCALL: ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -419,6 +413,11 @@ ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); @@ -787,28 +786,36 @@ /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ +#ifdef X86_WIN64 + if (rvalue == NULL + && cif->flags == FFI_TYPE_STRUCT + && cif->rtype->size != 1 && cif->rtype->size != 2 + && cif->rtype->size != 4 && cif->rtype->size != 8) + { + ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); + } +#else if (rvalue == NULL && (cif->flags == FFI_TYPE_STRUCT || cif->flags == FFI_TYPE_MS_STRUCT)) { ecif.rvalue = alloca(cif->rtype->size); } +#endif else ecif.rvalue = rvalue; switch (cif->abi) { -#ifndef X86_WIN32 - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); +#ifdef X86_WIN64 + case FFI_WIN64: + ffi_call_win64(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; -#else +#elif defined(X86_WIN32) case FFI_SYSV: case FFI_MS_CDECL: -#endif -#ifndef X86_WIN64 case FFI_STDCALL: ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); @@ -835,13 +842,18 @@ ++passed_regs; } if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; + abi = FFI_THISCALL; if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; + abi = FFI_STDCALL; ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, ecif.rvalue, fn); } break; +#else + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + break; #endif default: FFI_ASSERT(0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 06:29:12 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 04:29:12 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogZW5zdXJlIC5rZXl3?= =?utf-8?q?ords_is_always_a_dict?= Message-ID: <20150509042912.1931.26949@psf.io> https://hg.python.org/cpython/rev/9dfda4e7169a changeset: 95929:9dfda4e7169a branch: 3.4 parent: 95926:c78137bff841 user: Benjamin Peterson date: Sat May 09 00:25:18 2015 -0400 summary: ensure .keywords is always a dict files: Lib/test/test_functools.py | 2 ++ Misc/NEWS | 2 ++ Modules/_functoolsmodule.c | 14 +++++--------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -77,9 +77,11 @@ # exercise special code paths for no keyword args in # either the partial object or the caller p = self.partial(capture) + self.assertEqual(p.keywords, {}) self.assertEqual(p(), ((), {})) self.assertEqual(p(a=1), ((), {'a':1})) p = self.partial(capture, a=1) + self.assertEqual(p.keywords, {'a':1}) self.assertEqual(p(), ((), {'a':1})) self.assertEqual(p(b=2), ((), {'a':1, 'b':2})) # keyword args in the call override those in the partial object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,8 @@ - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. +- The keywords attribute of functools.partial is now always a dictionary. + - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup and siftdown functions. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -54,17 +54,13 @@ Py_DECREF(pto); return NULL; } - if (kw != NULL) { - pto->kw = PyDict_Copy(kw); - if (pto->kw == NULL) { - Py_DECREF(pto); - return NULL; - } - } else { - pto->kw = Py_None; - Py_INCREF(Py_None); + pto->kw = (kw != NULL) ? PyDict_Copy(kw) : PyDict_New(); + if (pto->kw == NULL) { + Py_DECREF(pto); + return NULL; } + pto->weakreflist = NULL; pto->dict = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 06:29:12 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 04:29:12 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogZW5zdXJlIC5rZXl3?= =?utf-8?q?ords_is_always_a_dict?= Message-ID: <20150509042912.11938.24444@psf.io> https://hg.python.org/cpython/rev/d6f6eded80d8 changeset: 95928:d6f6eded80d8 branch: 2.7 parent: 95924:96a7b401d5e4 user: Benjamin Peterson date: Sat May 09 00:23:41 2015 -0400 summary: ensure .keywords is always a dict files: Lib/test/test_functools.py | 2 ++ Misc/NEWS | 2 ++ Modules/_functoolsmodule.c | 14 +++++--------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -89,9 +89,11 @@ # exercise special code paths for no keyword args in # either the partial object or the caller p = self.thetype(capture) + self.assertEqual(p.keywords, {}) self.assertEqual(p(), ((), {})) self.assertEqual(p(a=1), ((), {'a':1})) p = self.thetype(capture, a=1) + self.assertEqual(p.keywords, {'a':1}) self.assertEqual(p(), ((), {'a':1})) self.assertEqual(p(b=2), ((), {'a':1, 'b':2})) # keyword args in the call override those in the partial object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,8 @@ Library ------- +- The keywords attribute of functools.partial is now always a dictionary. + - Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer successful if the callable is None. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -132,17 +132,13 @@ Py_DECREF(pto); return NULL; } - if (kw != NULL) { - pto->kw = PyDict_Copy(kw); - if (pto->kw == NULL) { - Py_DECREF(pto); - return NULL; - } - } else { - pto->kw = Py_None; - Py_INCREF(Py_None); + pto->kw = (kw != NULL) ? PyDict_Copy(kw) : PyDict_New(); + if (pto->kw == NULL) { + Py_DECREF(pto); + return NULL; } + pto->weakreflist = NULL; pto->dict = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 06:29:12 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 09 May 2015 04:29:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150509042912.8147.83784@psf.io> https://hg.python.org/cpython/rev/73c79edc7f40 changeset: 95930:73c79edc7f40 parent: 95927:987b30a88653 parent: 95929:9dfda4e7169a user: Benjamin Peterson date: Sat May 09 00:29:08 2015 -0400 summary: merge 3.4 files: Lib/test/test_functools.py | 2 ++ Misc/NEWS | 2 ++ Modules/_functoolsmodule.c | 13 +++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -77,9 +77,11 @@ # exercise special code paths for no keyword args in # either the partial object or the caller p = self.partial(capture) + self.assertEqual(p.keywords, {}) self.assertEqual(p(), ((), {})) self.assertEqual(p(a=1), ((), {'a':1})) p = self.partial(capture, a=1) + self.assertEqual(p.keywords, {'a':1}) self.assertEqual(p(), ((), {'a':1})) self.assertEqual(p(b=2), ((), {'a':1, 'b':2})) # keyword args in the call override those in the partial object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -167,6 +167,8 @@ lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger and Allison Kaptur. +- The keywords attribute of functools.partial is now always a dictionary. + - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -102,8 +102,17 @@ } } else { - pto->kw = pkw; - Py_INCREF(pkw); + if (pkw == Py_None) { + pto->kw = PyDict_New(); + if (pto->kw == NULL) { + Py_DECREF(pto); + return NULL; + } + } + else { + pto->kw = pkw; + Py_INCREF(pkw); + } } pto->weakreflist = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 07:07:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 09 May 2015 05:07:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324018=3A_Add_a_co?= =?utf-8?q?llections=2EGenerator_abstract_base_class=2E?= Message-ID: <20150509050730.14346.2647@psf.io> https://hg.python.org/cpython/rev/ba5d7041e2f5 changeset: 95931:ba5d7041e2f5 user: Raymond Hettinger date: Sat May 09 01:07:23 2015 -0400 summary: Issue #24018: Add a collections.Generator abstract base class. files: Doc/library/collections.abc.rst | 10 ++ Lib/_collections_abc.py | 61 +++++++++++++++++- Lib/test/test_collections.py | 73 ++++++++++++++++++++- Misc/NEWS | 3 + 4 files changed, 145 insertions(+), 2 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -40,6 +40,7 @@ :class:`Hashable` ``__hash__`` :class:`Iterable` ``__iter__`` :class:`Iterator` :class:`Iterable` ``__next__`` ``__iter__`` +:class:`Generator` :class:`Iterator` ``send``, ``throw`` ``close``, ``__iter__``, ``__next__`` :class:`Sized` ``__len__`` :class:`Callable` ``__call__`` @@ -102,6 +103,15 @@ :meth:`~iterator.__next__` methods. See also the definition of :term:`iterator`. +.. class:: Generator + + ABC for generator classes that implement the protocol defined in + :pep:`342` that extends iterators with the :meth:`~generator.send`, + :meth:`~generator.throw` and :meth:`~generator.close` methods. + See also the definition of :term:`generator`. + + .. versionadded:: 3.5 + .. class:: Sequence MutableSequence diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -9,7 +9,7 @@ from abc import ABCMeta, abstractmethod import sys -__all__ = ["Hashable", "Iterable", "Iterator", +__all__ = ["Hashable", "Iterable", "Iterator", "Generator", "Sized", "Container", "Callable", "Set", "MutableSet", "Mapping", "MutableMapping", @@ -50,6 +50,7 @@ dict_items = type({}.items()) ## misc ## mappingproxy = type(type.__dict__) +generator = type((lambda: (yield))()) ### ONE-TRICK PONIES ### @@ -124,6 +125,64 @@ Iterator.register(tuple_iterator) Iterator.register(zip_iterator) + +class Generator(Iterator): + + __slots__ = () + + def __next__(self): + """Return the next item from the generator. + When exhausted, raise StopIteration. + """ + return self.send(None) + + @abstractmethod + def send(self, value): + """Send a value into the generator. + Return next yielded value or raise StopIteration. + """ + raise StopIteration + + @abstractmethod + def throw(self, typ, val=None, tb=None): + """Raise an exception in the generator. + Return next yielded value or raise StopIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + def close(self): + """Raise GeneratorExit inside generator. + """ + try: + self.throw(GeneratorExit) + except (GeneratorExit, StopIteration): + pass + else: + raise RuntimeError("generator ignored GeneratorExit") + + @classmethod + def __subclasshook__(cls, C): + if cls is Generator: + mro = C.__mro__ + for method in ('__iter__', '__next__', 'send', 'throw', 'close'): + for base in mro: + if method in base.__dict__: + break + else: + return NotImplemented + return True + return NotImplemented + + +Generator.register(generator) + + class Sized(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -14,7 +14,7 @@ from collections import UserDict from collections import ChainMap from collections import deque -from collections.abc import Hashable, Iterable, Iterator +from collections.abc import Hashable, Iterable, Iterator, Generator from collections.abc import Sized, Container, Callable from collections.abc import Set, MutableSet from collections.abc import Mapping, MutableMapping, KeysView, ItemsView @@ -522,6 +522,77 @@ return self.assertNotIsInstance(NextOnly(), Iterator) + def test_Generator(self): + class NonGen1: + def __iter__(self): return self + def __next__(self): return None + def close(self): pass + def throw(self, typ, val=None, tb=None): pass + + class NonGen2: + def __iter__(self): return self + def __next__(self): return None + def close(self): pass + def send(self, value): return value + + class NonGen3: + def close(self): pass + def send(self, value): return value + def throw(self, typ, val=None, tb=None): pass + + non_samples = [ + None, 42, 3.14, 1j, b"", "", (), [], {}, set(), + iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()] + for x in non_samples: + self.assertNotIsInstance(x, Generator) + self.assertFalse(issubclass(type(x), Generator), repr(type(x))) + + class Gen: + def __iter__(self): return self + def __next__(self): return None + def close(self): pass + def send(self, value): return value + def throw(self, typ, val=None, tb=None): pass + + class MinimalGen(Generator): + def send(self, value): + return value + def throw(self, typ, val=None, tb=None): + super().throw(typ, val, tb) + + def gen(): + yield 1 + + samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()] + for x in samples: + self.assertIsInstance(x, Iterator) + self.assertIsInstance(x, Generator) + self.assertTrue(issubclass(type(x), Generator), repr(type(x))) + self.validate_abstract_methods(Generator, 'send', 'throw') + + # mixin tests + mgen = MinimalGen() + self.assertIs(mgen, iter(mgen)) + self.assertIs(mgen.send(None), next(mgen)) + self.assertEqual(2, mgen.send(2)) + self.assertIsNone(mgen.close()) + self.assertRaises(ValueError, mgen.throw, ValueError) + self.assertRaisesRegex(ValueError, "^huhu$", + mgen.throw, ValueError, ValueError("huhu")) + self.assertRaises(StopIteration, mgen.throw, StopIteration()) + + class FailOnClose(Generator): + def send(self, value): return value + def throw(self, *args): raise ValueError + + self.assertRaises(ValueError, FailOnClose().close) + + class IgnoreGeneratorExit(Generator): + def send(self, value): return value + def throw(self, *args): pass + + self.assertRaises(RuntimeError, IgnoreGeneratorExit().close) + def test_Sized(self): non_samples = [None, 42, 3.14, 1j, (lambda: (yield))(), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. +- Issue #24018: Add a collections.Generator abstract base class. + Contributed by Stefan Behnel. + - Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. Tkinter's getdouble() now supports any numbers (in particular int). -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat May 9 10:40:22 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 09 May 2015 08:40:22 +0000 Subject: [Python-checkins] Daily reference leaks (ba5d7041e2f5): sum=59 Message-ID: <20150509084022.14374.95993@psf.io> results for ba5d7041e2f5 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 test_multiprocessing_spawn leaked [38, 0, 0] references, sum=38 test_multiprocessing_spawn leaked [18, 0, 0] memory blocks, sum=18 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogscF9I2', '--timeout', '7200'] From python-checkins at python.org Sat May 9 17:44:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 09 May 2015 15:44:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_PEP_479=3A_Change_StopIter?= =?utf-8?q?ation_handling_inside_generators=2E?= Message-ID: <20150509154436.11924.75374@psf.io> https://hg.python.org/cpython/rev/36a8d935c322 changeset: 95932:36a8d935c322 user: Yury Selivanov date: Sat May 09 11:44:30 2015 -0400 summary: PEP 479: Change StopIteration handling inside generators. Closes issue #22906. files: Doc/howto/functional.rst | 8 ++-- Doc/library/__future__.rst | 3 ++ Doc/library/exceptions.rst | 8 +++++ Doc/reference/expressions.rst | 12 ++++---- Include/code.h | 1 + Include/compile.h | 1 + Include/pythonrun.h | 3 +- Lib/__future__.py | 6 ++++ Lib/contextlib.py | 11 ++++++- Lib/difflib.py | 3 +- Lib/test/test_contextlib.py | 34 +++++++++++++++++++++++ Misc/NEWS | 2 + Objects/genobject.c | 24 ++++++++++++++++ Python/future.c | 2 + 14 files changed, 103 insertions(+), 15 deletions(-) diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst --- a/Doc/howto/functional.rst +++ b/Doc/howto/functional.rst @@ -481,10 +481,10 @@ You could equally write ``for i in generate_ints(5)``, or ``a,b,c = generate_ints(3)``. -Inside a generator function, ``return value`` is semantically equivalent to -``raise StopIteration(value)``. If no value is returned or the bottom of the -function is reached, the procession of values ends and the generator cannot -return any further values. +Inside a generator function, ``return value`` causes ``StopIteration(value)`` +to be raised from the :meth:`~generator.__next__` method. Once this happens, or +the bottom of the function is reached, the procession of values ends and the +generator cannot yield any further values. You could achieve the effect of generators manually by writing your own class and storing all the local variables of the generator as instance variables. For diff --git a/Doc/library/__future__.rst b/Doc/library/__future__.rst --- a/Doc/library/__future__.rst +++ b/Doc/library/__future__.rst @@ -87,6 +87,9 @@ | unicode_literals | 2.6.0a2 | 3.0 | :pep:`3112`: | | | | | *Bytes literals in Python 3000* | +------------------+-------------+--------------+---------------------------------------------+ +| generator_stop | 3.5.0b1 | 3.7 | :pep:`479`: | +| | | | *StopIteration handling inside generators* | ++------------------+-------------+--------------+---------------------------------------------+ .. seealso:: diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -310,10 +310,18 @@ raised, and the value returned by the function is used as the :attr:`value` parameter to the constructor of the exception. + If a generator function defined in the presence of a ``from __future__ + import generator_stop`` directive raises :exc:`StopIteration`, it will be + converted into a :exc:`RuntimeError` (retaining the :exc:`StopIteration` + as the new exception's cause). + .. versionchanged:: 3.3 Added ``value`` attribute and the ability for generator functions to use it to return a value. + .. versionchanged:: 3.5 + Introduced the RuntimeError transformation. + .. exception:: SyntaxError Raised when the parser encounters a syntax error. This may occur in an diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -443,12 +443,12 @@ .. method:: generator.close() Raises a :exc:`GeneratorExit` at the point where the generator function was - paused. If the generator function then raises :exc:`StopIteration` (by - exiting normally, or due to already being closed) or :exc:`GeneratorExit` (by - not catching the exception), close returns to its caller. If the generator - yields a value, a :exc:`RuntimeError` is raised. If the generator raises any - other exception, it is propagated to the caller. :meth:`close` does nothing - if the generator has already exited due to an exception or normal exit. + paused. If the generator function then exits gracefully, is already closed, + or raises :exc:`GeneratorExit` (by not catching the exception), close + returns to its caller. If the generator yields a value, a + :exc:`RuntimeError` is raised. If the generator raises any other exception, + it is propagated to the caller. :meth:`close` does nothing if the generator + has already exited due to an exception or normal exit. .. index:: single: yield; examples diff --git a/Include/code.h b/Include/code.h --- a/Include/code.h +++ b/Include/code.h @@ -62,6 +62,7 @@ #define CO_FUTURE_UNICODE_LITERALS 0x20000 #define CO_FUTURE_BARRY_AS_BDFL 0x40000 +#define CO_FUTURE_GENERATOR_STOP 0x80000 /* This value is found in the co_cell2arg array when the associated cell variable does not correspond to an argument. The maximum number of diff --git a/Include/compile.h b/Include/compile.h --- a/Include/compile.h +++ b/Include/compile.h @@ -27,6 +27,7 @@ #define FUTURE_PRINT_FUNCTION "print_function" #define FUTURE_UNICODE_LITERALS "unicode_literals" #define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL" +#define FUTURE_GENERATOR_STOP "generator_stop" struct _mod; /* Declare the existence of this type */ #define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar) diff --git a/Include/pythonrun.h b/Include/pythonrun.h --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -9,7 +9,8 @@ #define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \ CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \ - CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL) + CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \ + CO_FUTURE_GENERATOR_STOP) #define PyCF_MASK_OBSOLETE (CO_NESTED) #define PyCF_SOURCE_IS_UTF8 0x0100 #define PyCF_DONT_IMPLY_DEDENT 0x0200 diff --git a/Lib/__future__.py b/Lib/__future__.py --- a/Lib/__future__.py +++ b/Lib/__future__.py @@ -56,6 +56,7 @@ "print_function", "unicode_literals", "barry_as_FLUFL", + "generator_stop", ] __all__ = ["all_feature_names"] + all_feature_names @@ -72,6 +73,7 @@ CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals CO_FUTURE_BARRY_AS_BDFL = 0x40000 +CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators class _Feature: def __init__(self, optionalRelease, mandatoryRelease, compiler_flag): @@ -132,3 +134,7 @@ barry_as_FLUFL = _Feature((3, 1, 0, "alpha", 2), (3, 9, 0, "alpha", 0), CO_FUTURE_BARRY_AS_BDFL) + +generator_stop = _Feature((3, 5, 0, "beta", 1), + (3, 7, 0, "alpha", 0), + CO_FUTURE_GENERATOR_STOP) diff --git a/Lib/contextlib.py b/Lib/contextlib.py --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -77,10 +77,17 @@ self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration as exc: - # Suppress the exception *unless* it's the same exception that + # Suppress StopIteration *unless* it's the same exception that # was passed to throw(). This prevents a StopIteration - # raised inside the "with" statement from being suppressed + # raised inside the "with" statement from being suppressed. return exc is not value + except RuntimeError as exc: + # Likewise, avoid suppressing if a StopIteration exception + # was passed to throw() and later wrapped into a RuntimeError + # (see PEP 479). + if exc.__cause__ is value: + return False + raise except: # only re-raise if it's *not* the exception that was # passed to throw(), because __exit__() must not raise diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1596,8 +1596,7 @@ # them up without doing anything else with them. line_pair_iterator = _line_pair_iterator() if context is None: - while True: - yield next(line_pair_iterator) + yield from line_pair_iterator # Handle case where user wants context differencing. We must do some # storage of lines until we know for sure that they are to be yielded. else: diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -83,6 +83,40 @@ raise ZeroDivisionError(999) self.assertEqual(state, [1, 42, 999]) + def test_contextmanager_except_stopiter(self): + stop_exc = StopIteration('spam') + @contextmanager + def woohoo(): + yield + try: + with woohoo(): + raise stop_exc + except Exception as ex: + self.assertIs(ex, stop_exc) + else: + self.fail('StopIteration was suppressed') + + def test_contextmanager_except_pep479(self): + code = """\ +from __future__ import generator_stop +from contextlib import contextmanager + at contextmanager +def woohoo(): + yield +""" + locals = {} + exec(code, locals, locals) + woohoo = locals['woohoo'] + + stop_exc = StopIteration('spam') + try: + with woohoo(): + raise stop_exc + except Exception as ex: + self.assertIs(ex, stop_exc) + else: + self.fail('StopIteration was suppressed') + def _create_contextmanager_attribs(self): def attribs(**kw): def decorate(func): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,8 @@ - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. +- Issue #22906: PEP 479: Change StopIteration handling inside generators. + Library ------- diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -130,6 +130,30 @@ } Py_CLEAR(result); } + else if (!result) { + /* Check for __future__ generator_stop and conditionally turn + * a leaking StopIteration into RuntimeError (with its cause + * set appropriately). */ + if ((((PyCodeObject *)gen->gi_code)->co_flags & + CO_FUTURE_GENERATOR_STOP) + && PyErr_ExceptionMatches(PyExc_StopIteration)) + { + PyObject *exc, *val, *val2, *tb; + PyErr_Fetch(&exc, &val, &tb); + PyErr_NormalizeException(&exc, &val, &tb); + if (tb != NULL) + PyException_SetTraceback(val, tb); + Py_DECREF(exc); + Py_XDECREF(tb); + PyErr_SetString(PyExc_RuntimeError, + "generator raised StopIteration"); + PyErr_Fetch(&exc, &val2, &tb); + PyErr_NormalizeException(&exc, &val2, &tb); + PyException_SetCause(val2, val); + PyException_SetContext(val2, val); + PyErr_Restore(exc, val2, tb); + } + } if (!result || f->f_stacktop == NULL) { /* generator can't be rerun, so release the frame */ diff --git a/Python/future.c b/Python/future.c --- a/Python/future.c +++ b/Python/future.c @@ -40,6 +40,8 @@ continue; } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL; + } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) { + ff->ff_features |= CO_FUTURE_GENERATOR_STOP; } else if (strcmp(feature, "braces") == 0) { PyErr_SetString(PyExc_SyntaxError, "not a chance"); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 17:48:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 09 May 2015 15:48:46 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_pep-478_and_pep-479=2E?= Message-ID: <20150509154846.84482.3450@psf.io> https://hg.python.org/peps/rev/cc5a1fe7134d changeset: 5836:cc5a1fe7134d user: Yury Selivanov date: Sat May 09 11:48:43 2015 -0400 summary: Update pep-478 and pep-479. files: pep-0478.txt | 1 + pep-0479.txt | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -60,6 +60,7 @@ * PEP 465, a new matrix multiplication operator * PEP 461, %-formatting for binary strings * PEP 471, os.scandir() +* PEP 479, change StopIteration handling inside generators Accepted PEPs: diff --git a/pep-0479.txt b/pep-0479.txt --- a/pep-0479.txt +++ b/pep-0479.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Chris Angelico , Guido van Rossum -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 15-Nov-2014 @@ -62,7 +62,7 @@ stumble on these cases by accident:: import contextlib - + @contextlib.contextmanager def transaction(): print('begin') @@ -73,7 +73,7 @@ raise else: print('commit') - + def do_it(): print('Refactored initial setup') yield # Body of with-statement is executed here @@ -86,7 +86,7 @@ # return raise StopIteration # This is wrong print('Should not be reached') - + for i in gene(): print('main: i =', i) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 9 18:07:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 09 May 2015 16:07:30 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_pep-478=2E?= Message-ID: <20150509160730.84506.72511@psf.io> https://hg.python.org/peps/rev/9abfa0d2eafc changeset: 5837:9abfa0d2eafc user: Yury Selivanov date: Sat May 09 12:07:27 2015 -0400 summary: Update pep-478. files: pep-0478.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -61,14 +61,14 @@ * PEP 461, %-formatting for binary strings * PEP 471, os.scandir() * PEP 479, change StopIteration handling inside generators +* PEP 441, improved Python zip application support +* PEP 448, additional unpacking generalizations +* PEP 486, make the Python Launcher aware of virtual environments Accepted PEPs: -* PEP 441, improved Python zip application support -* PEP 448, additional unpacking generalizations * PEP 475, retrying system calls that fail with EINTR * PEP 485, math.isclose(), a function for testing approximate equality -* PEP 486, make the Python Launcher aware of virtual environments * PEP 492, coroutines with async and await syntax Proposed changes for 3.5: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 9 19:54:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 09 May 2015 17:54:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_22906=3A_Add_test_fi?= =?utf-8?b?bGUu?= Message-ID: <20150509175402.8129.59961@psf.io> https://hg.python.org/cpython/rev/d15c26085591 changeset: 95933:d15c26085591 user: Yury Selivanov date: Sat May 09 13:53:57 2015 -0400 summary: Issue 22906: Add test file. files: Lib/test/test_pep479.py | 34 +++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_pep479.py b/Lib/test/test_pep479.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_pep479.py @@ -0,0 +1,34 @@ +from __future__ import generator_stop + +import unittest + + +class TestPEP479(unittest.TestCase): + def test_stopiteration_wrapping(self): + def f(): + raise StopIteration + def g(): + yield f() + with self.assertRaisesRegex(RuntimeError, + "generator raised StopIteration"): + next(g()) + + def test_stopiteration_wrapping_context(self): + def f(): + raise StopIteration + def g(): + yield f() + + try: + next(g()) + except RuntimeError as exc: + self.assertIs(type(exc.__cause__), StopIteration) + self.assertIs(type(exc.__context__), StopIteration) + self.assertTrue(exc.__suppress_context__) + else: + self.fail('__cause__, __context__, or __suppress_context__ ' + 'were not properly set') + + +if __name__ == '__main__': + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 20:09:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 09 May 2015 18:09:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_22906=3A_Increment_r?= =?utf-8?q?efcount_after_PyException=5FSetContext?= Message-ID: <20150509180913.98669.78241@psf.io> https://hg.python.org/cpython/rev/5d8bc813d270 changeset: 95934:5d8bc813d270 user: Yury Selivanov date: Sat May 09 14:04:17 2015 -0400 summary: Issue 22906: Increment refcount after PyException_SetContext files: Objects/genobject.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -151,6 +151,7 @@ PyErr_NormalizeException(&exc, &val2, &tb); PyException_SetCause(val2, val); PyException_SetContext(val2, val); + Py_INCREF(val); PyErr_Restore(exc, val2, tb); } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 9 20:37:42 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 09 May 2015 18:37:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_news_entry_for_issue_2?= =?utf-8?q?4018=2E?= Message-ID: <20150509183742.1928.99764@psf.io> https://hg.python.org/cpython/rev/f7cc54086cd2 changeset: 95935:f7cc54086cd2 user: Guido van Rossum date: Sat May 09 11:37:23 2015 -0700 summary: Fix news entry for issue 24018. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,7 +41,7 @@ - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. -- Issue #24018: Add a collections.Generator abstract base class. +- Issue #24018: Add a collections.abc.Generator abstract base class. Contributed by Stefan Behnel. - Issue #23880: Tkinter's getint() and getdouble() now support Tcl_Obj. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 10 07:25:14 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 10 May 2015 05:25:14 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Redistributor_recommendations?= =?utf-8?q?_for_PEP_476?= Message-ID: <20150510052514.98677.29223@psf.io> https://hg.python.org/peps/rev/85bc7f13b295 changeset: 5838:85bc7f13b295 user: Nick Coghlan date: Sun May 10 15:25:07 2015 +1000 summary: Redistributor recommendations for PEP 476 files: pep-0493.txt | 158 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 158 insertions(+), 0 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt new file mode 100644 --- /dev/null +++ b/pep-0493.txt @@ -0,0 +1,158 @@ +PEP: 493 +Title: HTTPS verification recommendations for Python 2.7 redistributors +Version: $Revision$ +Last-Modified: $Date$ +Author: Nick Coghlan , Robert Kuska +Status: Draft +Type: Informational +Content-Type: text/x-rst +Created: 10-May-2015 + +Abstract +======== + +PEP 476 updated Python's default handling of HTTPS certificates to be +appropriate for communication over the public internet. The Python 2.7 long +term maintenance series was judged to be in scope for this change, with the +new behaviour introduced in the Python 2.7.9 maintenance release. + +This PEP provides recommendations to downstream redistributors wishing to +provide a smoother migration experience when helping their users to manage +this change in Python's default behaviour. + +.. note:: + + Note that this PEP is not currently accepted, so it is a *proposed* + recommendation, rather than an active one. + +Rationale +========= + +PEP 476 changed Python's default behaviour to better match the needs and +expectations of developers operating over the public internet, a category +which appears to include most new Python developers. It is the position of +the authors of this PEP that this was a correct decision. + +However, it is also the case that this change *does* cause problems for +infrastructure administrators operating private intranets that rely on +self-signed certificates, or otherwise encounter problems with the new default +certificate verification settings. + +The long term answer for such environments is to update their internal +certificate management to at least match the standards set by the public +internet, but in the meantime, it is desirable to offer these administrators +a way to continue receiving maintenance updates to the Python 2.7 series, +without having to gate that on upgrades to their certificate management +infrastructure. + +PEP 476 did attempt to address this question, by covering how to revert the +new settings process wide by monkeypatching the ``ssl`` module to restore the +old behaviour. Unfortunately, the ``sitecustomize.py`` based technique proposed +to allow system administrators to disable the feature by default in their +Standard Operating Environment definition has been determined not to work in +at least some cases. The specific case of interest to the authors of this PEP +is the one where a commercial redistributor aims to provide their users with +a smoother migration path than the standard one provided by consuming the +upstream CPython 2.7 distribution directly [#]. + +.. [#] https://bugzilla.redhat.com/show_bug.cgi?id=1173041 + +Rather than allowing a plethora of mutually incompatibile migration techniques +to bloom, this PEP proposes a recommended approach for redistributors to take +when addressing this problem on behalf of their users that provides the +following capabilities: + +* infrastructure administrators restoring the old behaviour as part of their + standard system configuration +* redistributors restoring the old behaviour as part of their standard + platform configuration +* infrastructure administators optionally and explicitly opting in to accepting + a change in default behaviour at a future point in time as determined by their + chosen redistributor + +It aims to do this without introducing any new attack vectors that allow +the security configuration to be downgraded back to the older less secure +defaults. + +This design is being proposed as a recommendation for redistributors, rather +than as a new upstream feature, as it is needed primarily to support legacy +environments migrating from older versions of Python 2.7 (The PEP authors +aren't *opposed* to this capability existing as an upstream feature, we just +don't need that ourselves - our aim is to avoid different redistributors +doing different things, not to push the change upstream). + +Recommendation +============== + +To smooth the migration path to verifying HTTPS certificates by default, it is +recommended that redistributors: + +* patch the ``ssl`` module to read a global configuration file when the module + is imported +* default to verifying certificates if this configuration file is not present +* support the following three modes of operation in that configuration file: + + * ensure HTTPS certificate verification is enabled + * ensure HTTPS certificate verification is disabled + * delegate the decision to the redistributor modifying upstream Python + +An example patch is available at [#]. + +.. [#] https://bugs.python.org/issue23857 + +Recommended file location +------------------------- + +TBD separately for \*nix and Windows + +Recommended file format +----------------------- + +ConfigParser ini-style format, other details TBD + +Security Considerations +======================= + +The specific recommendations here are designed to work for privileged, security +sensitive processes, being run in the following locked down configuration: + +* run from a locked down administrator controlled directory rather than a normal + user directory (preventing ``sys.path[0]`` based privilege escalation attacks) +* run using the ``-E`` switch (preventing ``PYTHON*`` environment variable based + privilege escalation attacks) +* run using the ``-s`` switch (preventing user site directory based privilege + escalation attacks) +* run using the ``-S`` switch (preventing ``sitecustomize`` based privilege + escalation attacks) + +The intent is that the *only* reason HTTPS verification should be getting +turned off globally is because: + +* an end user is running a redistributor supported version of CPython rather + than running upstream CPython directly +* that redistributor has decided to provide a smoother migration path to + verifying HTTPS certificates by default than that being provided by the + upstream project +* either the redistributor or the local infrastructure administrator has + determined that it is appropriate to override the default upstream behaviour + (at least for the time being) + +Using an administrator controlled configuration file rather than an environment +variable not only provides compatibility with the ``-E`` switch, but also +ensures that in any situation where an attacker gains sufficient access to allow +them to modify the configuration file, they're likely already in a position to +attack the system certificate store directly. + +Copyright +========= + +This document has been placed into the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Sun May 10 10:42:04 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 10 May 2015 08:42:04 +0000 Subject: [Python-checkins] Daily reference leaks (f7cc54086cd2): sum=6 Message-ID: <20150510084204.84484.98687@psf.io> results for f7cc54086cd2 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog82uBlO', '--timeout', '7200'] From python-checkins at python.org Sun May 10 19:16:44 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 10 May 2015 17:16:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_tag_v2?= =?utf-8?q?=2E7=2E10rc1_for_changeset_80ccce248ba2?= Message-ID: <20150510171644.7806.63963@psf.io> https://hg.python.org/cpython/rev/b99d50fde755 changeset: 95938:b99d50fde755 branch: 2.7 user: Benjamin Peterson date: Sun May 10 13:14:43 2015 -0400 summary: Added tag v2.7.10rc1 for changeset 80ccce248ba2 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -168,3 +168,4 @@ ee879c0ffa11caaa34bf01537e1c4411dd948552 v2.7.8 40eada278702349a2b2f334aa9d91fa7090ea1e3 v2.7.9rc1 648dcafa7e5f40da31079bc7a7f0c445f1ea4ab9 v2.7.9 +80ccce248ba2657ed5da3ccf7999f35b78827f5e v2.7.10rc1 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 10 19:16:47 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 10 May 2015 17:16:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_bump_version_t?= =?utf-8?q?o_2=2E7=2E10rc1?= Message-ID: <20150510171644.8966.10377@psf.io> https://hg.python.org/cpython/rev/80ccce248ba2 changeset: 95937:80ccce248ba2 branch: 2.7 tag: v2.7.10rc1 user: Benjamin Peterson date: Sun May 10 13:14:16 2015 -0400 summary: bump version to 2.7.10rc1 files: Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 8 ++++---- README | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -24,10 +24,10 @@ #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 10 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 0 +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "2.7.10rc0" +#define PY_VERSION "2.7.10rc1" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.9" +__version__ = "2.7.10rc1" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "2.7.9" +IDLE_VERSION = "2.7.10rc1" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,10 +2,10 @@ Python News +++++++++++ -What's New in Python 2.7.10? -============================ - -*Release date: XXXX-XX-XX* +What's New in Python 2.7.10 release candidate 1? +================================================ + +*Release date: 2015-05-10* Core and Builtins ----------------- diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 2.7.9 -============================ +This is Python version 2.7.10 +============================= Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 10 19:16:47 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 10 May 2015 17:16:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_add_news_secti?= =?utf-8?q?on_for_2=2E7=2E11?= Message-ID: <20150510171645.76604.33437@psf.io> https://hg.python.org/cpython/rev/4f2fc30d483f changeset: 95939:4f2fc30d483f branch: 2.7 user: Benjamin Peterson date: Sun May 10 13:16:20 2015 -0400 summary: add news section for 2.7.11 files: Misc/NEWS | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 2.7.11? +============================ + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 2.7.10 release candidate 1? ================================================ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 10 19:16:44 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 10 May 2015 17:16:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_update_pydoc-t?= =?utf-8?q?opics?= Message-ID: <20150510171644.1917.61923@psf.io> https://hg.python.org/cpython/rev/90d8da31abd7 changeset: 95936:90d8da31abd7 branch: 2.7 parent: 95928:d6f6eded80d8 user: Benjamin Peterson date: Sun May 10 13:13:10 2015 -0400 summary: update pydoc-topics files: Lib/pydoc_data/topics.py | 90 ++++++++++++++-------------- 1 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,80 +1,80 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Tue Nov 25 18:24:45 2014 +# Autogenerated by Sphinx on Sun May 10 13:12:18 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', - 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, "IndexError" is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to (small) integers.\n If either bound is negative, the sequence\'s length is added to it.\n The resulting bounds are clipped to lie between zero and the\n sequence\'s length, inclusive. Finally, the sequence object is asked\n to replace the slice with the items of the assigned sequence. The\n length of the slice may be different from the length of the assigned\n sequence, thus changing the length of the target sequence, if the\n object allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', - 'atom-literals': u"\nLiterals\n********\n\nPython supports string literals and various numeric literals:\n\n literal ::= stringliteral | integer | longinteger\n | floatnumber | imagnumber\n\nEvaluation of a literal yields an object of the given type (string,\ninteger, long integer, floating point number, complex number) with the\ngiven value. The value may be approximated in the case of floating\npoint and imaginary (complex) literals. See section *Literals* for\ndetails.\n\nAll literals correspond to immutable data types, and hence the\nobject's identity is less important than its value. Multiple\nevaluations of literals with the same value (either the same\noccurrence in the program text or a different occurrence) may obtain\nthe same object or a different object with the same value.\n", - 'attribute-access': u'\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control in new-style classes.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should not simply execute "self.name = value" --- this would cause\n a recursive call to itself. Instead, it should insert the value in\n the dictionary of instance attributes, e.g., "self.__dict__[name] =\n value". For new-style classes, rather than accessing the instance\n dictionary, it should call the base class method with the same\n name, for example, "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\n\nMore attribute access for new-style classes\n===========================================\n\nThe following methods only apply to new-style classes.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup for new-style\n classes*.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called. Note that descriptors are only invoked for new\nstyle objects or classes (ones that subclass "object()" or "type()").\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to a new-style object instance, "a.x" is transformed\n into the call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a new-style class, "A.x" is transformed into the\n call: "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of both old and new-style classes have a\ndictionary for attribute storage. This wastes space for objects\nhaving very few instance variables. The space consumption can become\nacute when creating large numbers of instances.\n\nThe default can be overridden by defining *__slots__* in a new-style\nclass definition. The *__slots__* declaration takes a sequence of\ninstance variables and reserves just enough space in each instance to\nhold a value for each variable. Space is saved because *__dict__* is\nnot created for each instance.\n\n__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n new-style class, *__slots__* reserves space for the declared\n variables and prevents the automatic creation of *__dict__* and\n *__weakref__* for each instance.\n\n New in version 2.2.\n\nNotes on using *__slots__*\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__dict__\'" to the\n *__slots__* declaration would not enable the assignment of new\n attributes not specifically listed in the sequence of instance\n variable names.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__weakref__\'" to the\n *__slots__* declaration would not enable support for weak\n references.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "long", "str" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n Changed in version 2.6: Previously, *__class__* assignment raised an\n error if either new or old class had *__slots__*.\n', + 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section Primaries for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section The standard type\nhierarchy).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, "IndexError" is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to (small) integers.\n If either bound is negative, the sequence\'s length is added to it.\n The resulting bounds are clipped to lie between zero and the\n sequence\'s length, inclusive. Finally, the sequence object is asked\n to replace the slice with the items of the assigned sequence. The\n length of the slice may be different from the length of the assigned\n sequence, thus changing the length of the target sequence, if the\n object allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section Primaries for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same caveat about\nclass and instance attributes applies as for regular assignments.\n', + 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section Identifiers\nand keywords for lexical definition and section Naming and binding for\ndocumentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', + 'atom-literals': u"\nLiterals\n********\n\nPython supports string literals and various numeric literals:\n\n literal ::= stringliteral | integer | longinteger\n | floatnumber | imagnumber\n\nEvaluation of a literal yields an object of the given type (string,\ninteger, long integer, floating point number, complex number) with the\ngiven value. The value may be approximated in the case of floating\npoint and imaginary (complex) literals. See section Literals for\ndetails.\n\nAll literals correspond to immutable data types, and hence the\nobject's identity is less important than its value. Multiple\nevaluations of literals with the same value (either the same\noccurrence in the program text or a different occurrence) may obtain\nthe same object or a different object with the same value.\n", + 'attribute-access': u'\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control in new-style classes.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should not simply execute "self.name = value" --- this would cause\n a recursive call to itself. Instead, it should insert the value in\n the dictionary of instance attributes, e.g., "self.__dict__[name] =\n value". For new-style classes, rather than accessing the instance\n dictionary, it should call the base class method with the same\n name, for example, "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\n\nMore attribute access for new-style classes\n===========================================\n\nThe following methods only apply to new-style classes.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See Special method lookup for new-style\n classes.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called. Note that descriptors are only invoked for new\nstyle objects or classes (ones that subclass "object()" or "type()").\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to a new-style object instance, "a.x" is transformed\n into the call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a new-style class, "A.x" is transformed into the\n call: "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of both old and new-style classes have a\ndictionary for attribute storage. This wastes space for objects\nhaving very few instance variables. The space consumption can become\nacute when creating large numbers of instances.\n\nThe default can be overridden by defining *__slots__* in a new-style\nclass definition. The *__slots__* declaration takes a sequence of\ninstance variables and reserves just enough space in each instance to\nhold a value for each variable. Space is saved because *__dict__* is\nnot created for each instance.\n\n__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n new-style class, *__slots__* reserves space for the declared\n variables and prevents the automatic creation of *__dict__* and\n *__weakref__* for each instance.\n\n New in version 2.2.\n\nNotes on using *__slots__*\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__dict__\'" to the\n *__slots__* declaration would not enable the assignment of new\n attributes not specifically listed in the sequence of instance\n variable names.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__weakref__\'" to the\n *__slots__* declaration would not enable support for weak\n references.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (Implementing Descriptors) for each variable name. As a\n result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "long", "str" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n Changed in version 2.6: Previously, *__class__* assignment raised an\n error if either new or old class had *__slots__*.\n', 'attribute-references': u'\nAttribute references\n********************\n\nAn attribute reference is a primary followed by a period and a name:\n\n attributeref ::= primary "." identifier\n\nThe primary must evaluate to an object of a type that supports\nattribute references, e.g., a module, list, or an instance. This\nobject is then asked to produce the attribute whose name is the\nidentifier. If this attribute is not available, the exception\n"AttributeError" is raised. Otherwise, the type and value of the\nobject produced is determined by the object. Multiple evaluations of\nthe same attribute reference may yield different objects.\n', - 'augassign': u'\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'binary': u'\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe "*" (multiplication) operator yields the product of its arguments.\nThe arguments must either both be numbers, or one argument must be an\ninteger (plain or long) and the other must be a sequence. In the\nformer case, the numbers are converted to a common type and then\nmultiplied together. In the latter case, sequence repetition is\nperformed; a negative repetition factor yields an empty sequence.\n\nThe "/" (division) and "//" (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Plain or long integer division yields an\ninteger of the same type; the result is that of mathematical division\nwith the \'floor\' function applied to the result. Division by zero\nraises the "ZeroDivisionError" exception.\n\nThe "%" (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n"ZeroDivisionError" exception. The arguments may be floating point\nnumbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 +\n0.34".) The modulo operator always yields a result with the same sign\nas its second operand (or zero); the absolute value of the result is\nstrictly smaller than the absolute value of the second operand [2].\n\nThe integer division and modulo operators are connected by the\nfollowing identity: "x == (x/y)*y + (x%y)". Integer division and\nmodulo are also connected with the built-in function "divmod()":\n"divmod(x, y) == (x/y, x%y)". These identities don\'t hold for\nfloating point numbers; there similar identities hold approximately\nwhere "x/y" is replaced by "floor(x/y)" or "floor(x/y) - 1" [3].\n\nIn addition to performing the modulo operation on numbers, the "%"\noperator is also overloaded by string and unicode objects to perform\nstring formatting (also known as interpolation). The syntax for string\nformatting is described in the Python Library Reference, section\n*String Formatting Operations*.\n\nDeprecated since version 2.3: The floor division operator, the modulo\noperator, and the "divmod()" function are no longer defined for\ncomplex numbers. Instead, convert to a floating point number using\nthe "abs()" function if appropriate.\n\nThe "+" (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe "-" (subtraction) operator yields the difference of its arguments.\nThe numeric arguments are first converted to a common type.\n', + 'augassign': u'\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section Primaries for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same caveat about\nclass and instance attributes applies as for regular assignments.\n', + 'binary': u'\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe "*" (multiplication) operator yields the product of its arguments.\nThe arguments must either both be numbers, or one argument must be an\ninteger (plain or long) and the other must be a sequence. In the\nformer case, the numbers are converted to a common type and then\nmultiplied together. In the latter case, sequence repetition is\nperformed; a negative repetition factor yields an empty sequence.\n\nThe "/" (division) and "//" (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Plain or long integer division yields an\ninteger of the same type; the result is that of mathematical division\nwith the \'floor\' function applied to the result. Division by zero\nraises the "ZeroDivisionError" exception.\n\nThe "%" (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n"ZeroDivisionError" exception. The arguments may be floating point\nnumbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 +\n0.34".) The modulo operator always yields a result with the same sign\nas its second operand (or zero); the absolute value of the result is\nstrictly smaller than the absolute value of the second operand [2].\n\nThe integer division and modulo operators are connected by the\nfollowing identity: "x == (x/y)*y + (x%y)". Integer division and\nmodulo are also connected with the built-in function "divmod()":\n"divmod(x, y) == (x/y, x%y)". These identities don\'t hold for\nfloating point numbers; there similar identities hold approximately\nwhere "x/y" is replaced by "floor(x/y)" or "floor(x/y) - 1" [3].\n\nIn addition to performing the modulo operation on numbers, the "%"\noperator is also overloaded by string and unicode objects to perform\nstring formatting (also known as interpolation). The syntax for string\nformatting is described in the Python Library Reference, section\nString Formatting Operations.\n\nDeprecated since version 2.3: The floor division operator, the modulo\noperator, and the "divmod()" function are no longer defined for\ncomplex numbers. Instead, convert to a floating point number using\nthe "abs()" function if appropriate.\n\nThe "+" (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe "-" (subtraction) operator yields the difference of its arguments.\nThe numeric arguments are first converted to a common type.\n', 'bitwise': u'\nBinary bitwise operations\n*************************\n\nEach of the three bitwise operations has a different priority level:\n\n and_expr ::= shift_expr | and_expr "&" shift_expr\n xor_expr ::= and_expr | xor_expr "^" and_expr\n or_expr ::= xor_expr | or_expr "|" xor_expr\n\nThe "&" operator yields the bitwise AND of its arguments, which must\nbe plain or long integers. The arguments are converted to a common\ntype.\n\nThe "^" operator yields the bitwise XOR (exclusive OR) of its\narguments, which must be plain or long integers. The arguments are\nconverted to a common type.\n\nThe "|" operator yields the bitwise (inclusive) OR of its arguments,\nwhich must be plain or long integers. The arguments are converted to\na common type.\n', - 'bltin-code-objects': u'\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin "compile()" function and can be extracted from function objects\nthrough their "func_code" attribute. See also the "code" module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the "exec" statement or the built-in "eval()"\nfunction.\n\nSee *The standard type hierarchy* for more information.\n', - 'bltin-ellipsis-object': u'\nThe Ellipsis Object\n*******************\n\nThis object is used by extended slice notation (see *Slicings*). It\nsupports no special operations. There is exactly one ellipsis object,\nnamed "Ellipsis" (a built-in name).\n\nIt is written as "Ellipsis". When in a subscript, it can also be\nwritten as "...", for example "seq[...]".\n', + 'bltin-code-objects': u'\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin "compile()" function and can be extracted from function objects\nthrough their "func_code" attribute. See also the "code" module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the "exec" statement or the built-in "eval()"\nfunction.\n\nSee The standard type hierarchy for more information.\n', + 'bltin-ellipsis-object': u'\nThe Ellipsis Object\n*******************\n\nThis object is used by extended slice notation (see Slicings). It\nsupports no special operations. There is exactly one ellipsis object,\nnamed "Ellipsis" (a built-in name).\n\nIt is written as "Ellipsis". When in a subscript, it can also be\nwritten as "...", for example "seq[...]".\n', 'bltin-null-object': u'\nThe Null Object\n***************\n\nThis object is returned by functions that don\'t explicitly return a\nvalue. It supports no special operations. There is exactly one null\nobject, named "None" (a built-in name).\n\nIt is written as "None".\n', 'bltin-type-objects': u'\nType Objects\n************\n\nType objects represent the various object types. An object\'s type is\naccessed by the built-in function "type()". There are no special\noperations on types. The standard module "types" defines names for\nall standard built-in types.\n\nTypes are written like this: "".\n', 'booleans': u'\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: "False", "None", numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. (See the "__nonzero__()" special method for a way to change\nthis.)\n\nThe operator "not" yields "True" if its argument is false, "False"\notherwise.\n\nThe expression "x and y" first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression "x or y" first evaluates *x*; if *x* is true, its value\nis returned; otherwise, *y* is evaluated and the resulting value is\nreturned.\n\n(Note that neither "and" nor "or" restrict the value and type they\nreturn to "False" and "True", but rather return the last evaluated\nargument. This is sometimes useful, e.g., if "s" is a string that\nshould be replaced by a default value if it is empty, the expression\n"s or \'foo\'" yields the desired value. Because "not" has to invent a\nvalue anyway, it does not bother to return a value of the same type as\nits argument, so e.g., "not \'foo\'" yields "False", not "\'\'".)\n', 'break': u'\nThe "break" statement\n*********************\n\n break_stmt ::= "break"\n\n"break" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition within that\nloop.\n\nIt terminates the nearest enclosing loop, skipping the optional "else"\nclause if the loop has one.\n\nIf a "for" loop is terminated by "break", the loop control target\nkeeps its current value.\n\nWhen "break" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nloop.\n', 'callable-types': u'\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n', - 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","]\n | expression genexpr_for] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and certain class instances\nthemselves are callable; extensions may define additional callable\nobject types). All argument expressions are evaluated before the call\nis attempted. Please refer to section *Function definitions* for the\nsyntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print a, b\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames. Formal parameters using the syntax "(sublist)" cannot be used\nas keyword argument names; the outermost sublist corresponds to a\nsingle unnamed argument slot, and the argument value is assigned to\nthe sublist using the usual tuple assignment rules after all other\nparameter processing is done.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', - 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= "class" classname [inheritance] ":" suite\n inheritance ::= "(" [expression_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. It first evaluates the\ninheritance list, if present. Each item in the inheritance list\nshould evaluate to a class object or class type which allows\nsubclassing. The class\'s suite is then executed in a new execution\nframe (see section *Naming and binding*), using a newly created local\nnamespace and the original global namespace. (Usually, the suite\ncontains only function definitions.) When the class\'s suite finishes\nexecution, its execution frame is discarded but its local namespace is\nsaved. [4] A class object is then created using the inheritance list\nfor the base classes and the saved local namespace for the attribute\ndictionary. The class name is bound to this class object in the\noriginal local namespace.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass variables; they are shared by all instances. To create instance\nvariables, they can be set in a method with "self.name = value". Both\nclass and instance variables are accessible through the notation\n""self.name"", and an instance variable hides a class variable with\nthe same name when accessed in this way. Class variables can be used\nas defaults for instance variables, but using mutable values there can\nlead to unexpected results. For *new-style class*es, descriptors can\nbe used to create instance variables with different implementation\ndetails.\n\nClass definitions, like function definitions, may be wrapped by one or\nmore *decorator* expressions. The evaluation rules for the decorator\nexpressions are the same as for functions. The result must be a class\nobject, which is then bound to the class name.\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', - 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe forms "<>" and "!=" are equivalent; for consistency with C, "!="\nis preferred; where "!=" is mentioned below "<>" is also accepted.\nThe "<>" spelling is considered obsolescent.\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, objects of\ndifferent types *always* compare unequal, and are ordered consistently\nbut arbitrarily. You can control comparison behavior of objects of\nnon-built-in types by defining a "__cmp__" method or rich comparison\nmethods like "__gt__", described in section *Special method names*.\n\n(This unusual definition of comparison was used to simplify the\ndefinition of operations like sorting and the "in" and "not in"\noperators. In the future, the comparison rules for objects of\ndifferent types are likely to change.)\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. Unicode and 8-bit strings are fully interoperable in\n this behavior. [4]\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "cmp([1,2,x], [1,2,y])" returns\n the same as "cmp(x,y)". If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, "[1,2] <\n [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if their sorted\n (key, value) lists compare equal. [5] Outcomes other than equality\n are resolved consistently, but are not otherwise defined. [6]\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nThe operators "in" and "not in" test for collection membership. "x in\ns" evaluates to true if *x* is a member of the collection *s*, and\nfalse otherwise. "x not in s" returns the negation of "x in s". The\ncollection membership test has traditionally been bound to sequences;\nan object is a member of a collection if the collection is a sequence\nand contains an element equal to that object. However, it make sense\nfor many other object types to support membership tests without being\na sequence. In particular, dictionaries (for keys) and sets support\nmembership testing.\n\nFor the list and tuple types, "x in y" is true if and only if there\nexists an index *i* such that "x == y[i]" is true.\n\nFor the Unicode and string types, "x in y" is true if and only if *x*\nis a substring of *y*. An equivalent test is "y.find(x) != -1".\nNote, *x* and *y* need not be the same type; consequently, "u\'ab\' in\n\'abc\'" will return "True". Empty strings are always considered to be a\nsubstring of any other string, so """ in "abc"" will return "True".\n\nChanged in version 2.3: Previously, *x* was required to be a string of\nlength "1".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [7]\n', - 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements. Function and class definitions are\nalso syntactically compound statements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print x\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print" statements are executed:\n\n if x < y < z: print x; print y; print z\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | decorated\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments, and then the suite is executed. When the items are\nexhausted (which is immediately when the sequence is empty), the suite\nin the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nThe target list is not deleted when the loop is finished, but if the\nsequence is empty, it will not have been assigned to at all by the\nloop. Hint: the built-in function "range()" returns a sequence of\nintegers suitable to emulate the effect of Pascal\'s "for i := a to b\ndo"; e.g., "range(3)" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression [("as" | ",") identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nChanged in version 2.5: In previous versions of Python,\n"try"..."except"..."finally" did not work. "try"..."except" had to be\nnested in "try"..."finally".\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject, or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified in that except clause, if present, and the except\nclause\'s suite is executed. All except clauses must have an\nexecutable block. When the end of this block is reached, execution\ncontinues normally after the entire try statement. (This means that\nif two nested handlers exist for the same exception, and the exception\noccurs in the try clause of the inner handler, the outer handler will\nnot handle the exception.)\n\nBefore an except clause\'s suite is executed, details about the\nexception are assigned to three variables in the "sys" module:\n"sys.exc_type" receives the object identifying the exception;\n"sys.exc_value" receives the exception\'s parameter;\n"sys.exc_traceback" receives a traceback object (see section *The\nstandard type hierarchy*) identifying the point in the program where\nthe exception occurred. These details are also available through the\n"sys.exc_info()" function, which returns a tuple "(exc_type,\nexc_value, exc_traceback)". Use of the corresponding variables is\ndeprecated in favor of this function, since their use is unsafe in a\nthreaded program. As of Python 1.5, the variables are restored to\ntheir previous values (before the call) when returning from a function\nthat handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception, it is re-raised at the end of the\n"finally" clause. If the "finally" clause raises another exception or\nexecutes a "return" or "break" statement, the saved exception is\ndiscarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nNew in version 2.5.\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nNote: In Python 2.5, the "with" statement is only allowed when the\n "with_statement" feature has been enabled. It is always enabled in\n Python 2.6.\n\nChanged in version 2.7: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n decorated ::= decorators (classdef | funcdef)\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" identifier ["," "**" identifier]\n | "**" identifier\n | defparameter [","] )\n defparameter ::= parameter ["=" expression]\n sublist ::= parameter ("," parameter)* [","]\n parameter ::= identifier | "(" sublist ")"\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code:\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to:\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more top-level *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters must also have a default value --- this is a syntactic\nrestriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= "class" classname [inheritance] ":" suite\n inheritance ::= "(" [expression_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. It first evaluates the\ninheritance list, if present. Each item in the inheritance list\nshould evaluate to a class object or class type which allows\nsubclassing. The class\'s suite is then executed in a new execution\nframe (see section *Naming and binding*), using a newly created local\nnamespace and the original global namespace. (Usually, the suite\ncontains only function definitions.) When the class\'s suite finishes\nexecution, its execution frame is discarded but its local namespace is\nsaved. [4] A class object is then created using the inheritance list\nfor the base classes and the saved local namespace for the attribute\ndictionary. The class name is bound to this class object in the\noriginal local namespace.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass variables; they are shared by all instances. To create instance\nvariables, they can be set in a method with "self.name = value". Both\nclass and instance variables are accessible through the notation\n""self.name"", and an instance variable hides a class variable with\nthe same name when accessed in this way. Class variables can be used\nas defaults for instance variables, but using mutable values there can\nlead to unexpected results. For *new-style class*es, descriptors can\nbe used to create instance variables with different implementation\ndetails.\n\nClass definitions, like function definitions, may be wrapped by one or\nmore *decorator* expressions. The evaluation rules for the decorator\nexpressions are the same as for functions. The result must be a class\nobject, which is then bound to the class name.\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', - 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nNew in version 2.5.\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","]\n | expression genexpr_for] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and certain class instances\nthemselves are callable; extensions may define additional callable\nobject types). All argument expressions are evaluated before the call\nis attempted. Please refer to section Function definitions for the\nsyntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print a, b\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames. Formal parameters using the syntax "(sublist)" cannot be used\nas keyword argument names; the outermost sublist corresponds to a\nsingle unnamed argument slot, and the argument value is assigned to\nthe sublist using the usual tuple assignment rules after all other\nparameter processing is done.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n Function definitions. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see Built-in Functions for the\n descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', + 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section The standard\ntype hierarchy):\n\n classdef ::= "class" classname [inheritance] ":" suite\n inheritance ::= "(" [expression_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. It first evaluates the\ninheritance list, if present. Each item in the inheritance list\nshould evaluate to a class object or class type which allows\nsubclassing. The class\'s suite is then executed in a new execution\nframe (see section Naming and binding), using a newly created local\nnamespace and the original global namespace. (Usually, the suite\ncontains only function definitions.) When the class\'s suite finishes\nexecution, its execution frame is discarded but its local namespace is\nsaved. [4] A class object is then created using the inheritance list\nfor the base classes and the saved local namespace for the attribute\ndictionary. The class name is bound to this class object in the\noriginal local namespace.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass variables; they are shared by all instances. To create instance\nvariables, they can be set in a method with "self.name = value". Both\nclass and instance variables are accessible through the notation\n""self.name"", and an instance variable hides a class variable with\nthe same name when accessed in this way. Class variables can be used\nas defaults for instance variables, but using mutable values there can\nlead to unexpected results. For *new-style class*es, descriptors can\nbe used to create instance variables with different implementation\ndetails.\n\nClass definitions, like function definitions, may be wrapped by one or\nmore *decorator* expressions. The evaluation rules for the decorator\nexpressions are the same as for functions. The result must be a class\nobject, which is then bound to the class name.\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe forms "<>" and "!=" are equivalent; for consistency with C, "!="\nis preferred; where "!=" is mentioned below "<>" is also accepted.\nThe "<>" spelling is considered obsolescent.\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, objects of\ndifferent types *always* compare unequal, and are ordered consistently\nbut arbitrarily. You can control comparison behavior of objects of\nnon-built-in types by defining a "__cmp__" method or rich comparison\nmethods like "__gt__", described in section Special method names.\n\n(This unusual definition of comparison was used to simplify the\ndefinition of operations like sorting and the "in" and "not in"\noperators. In the future, the comparison rules for objects of\ndifferent types are likely to change.)\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. Unicode and 8-bit strings are fully interoperable in\n this behavior. [4]\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "cmp([1,2,x], [1,2,y])" returns\n the same as "cmp(x,y)". If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, "[1,2] <\n [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if their sorted\n (key, value) lists compare equal. [5] Outcomes other than equality\n are resolved consistently, but are not otherwise defined. [6]\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nThe operators "in" and "not in" test for collection membership. "x in\ns" evaluates to true if *x* is a member of the collection *s*, and\nfalse otherwise. "x not in s" returns the negation of "x in s". The\ncollection membership test has traditionally been bound to sequences;\nan object is a member of a collection if the collection is a sequence\nand contains an element equal to that object. However, it make sense\nfor many other object types to support membership tests without being\na sequence. In particular, dictionaries (for keys) and sets support\nmembership testing.\n\nFor the list and tuple types, "x in y" is true if and only if there\nexists an index *i* such that "x == y[i]" is true.\n\nFor the Unicode and string types, "x in y" is true if and only if *x*\nis a substring of *y*. An equivalent test is "y.find(x) != -1".\nNote, *x* and *y* need not be the same type; consequently, "u\'ab\' in\n\'abc\'" will return "True". Empty strings are always considered to be a\nsubstring of any other string, so """ in "abc"" will return "True".\n\nChanged in version 2.3: Previously, *x* was required to be a string of\nlength "1".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [7]\n', + 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements. Function and class definitions are\nalso syntactically compound statements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print x\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print" statements are executed:\n\n if x < y < z: print x; print y; print z\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | decorated\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section Boolean operations\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments, and then the suite is executed. When the items are\nexhausted (which is immediately when the sequence is empty), the suite\nin the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nThe target list is not deleted when the loop is finished, but if the\nsequence is empty, it will not have been assigned to at all by the\nloop. Hint: the built-in function "range()" returns a sequence of\nintegers suitable to emulate the effect of Pascal\'s "for i := a to b\ndo"; e.g., "range(3)" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression [("as" | ",") identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nChanged in version 2.5: In previous versions of Python,\n"try"..."except"..."finally" did not work. "try"..."except" had to be\nnested in "try"..."finally".\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject, or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified in that except clause, if present, and the except\nclause\'s suite is executed. All except clauses must have an\nexecutable block. When the end of this block is reached, execution\ncontinues normally after the entire try statement. (This means that\nif two nested handlers exist for the same exception, and the exception\noccurs in the try clause of the inner handler, the outer handler will\nnot handle the exception.)\n\nBefore an except clause\'s suite is executed, details about the\nexception are assigned to three variables in the "sys" module:\n"sys.exc_type" receives the object identifying the exception;\n"sys.exc_value" receives the exception\'s parameter;\n"sys.exc_traceback" receives a traceback object (see section The\nstandard type hierarchy) identifying the point in the program where\nthe exception occurred. These details are also available through the\n"sys.exc_info()" function, which returns a tuple "(exc_type,\nexc_value, exc_traceback)". Use of the corresponding variables is\ndeprecated in favor of this function, since their use is unsafe in a\nthreaded program. As of Python 1.5, the variables are restored to\ntheir previous values (before the call) when returning from a function\nthat handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception, it is re-raised at the end of the\n"finally" clause. If the "finally" clause raises another exception or\nexecutes a "return" or "break" statement, the saved exception is\ndiscarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\nExceptions, and information on using the "raise" statement to generate\nexceptions may be found in section The raise statement.\n\n\nThe "with" statement\n====================\n\nNew in version 2.5.\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section With Statement\nContext Managers). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nNote: In Python 2.5, the "with" statement is only allowed when the\n "with_statement" feature has been enabled. It is always enabled in\n Python 2.6.\n\nChanged in version 2.7: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection The standard type hierarchy):\n\n decorated ::= decorators (classdef | funcdef)\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" identifier ["," "**" identifier]\n | "**" identifier\n | defparameter [","] )\n defparameter ::= parameter ["=" expression]\n sublist ::= parameter ("," parameter)* [","]\n parameter ::= identifier | "(" sublist ")"\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code:\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to:\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more top-level *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters must also have a default value --- this is a syntactic\nrestriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section Calls.\nA function call always assigns values to all parameters mentioned in\nthe parameter list, either from position arguments, from keyword\narguments, or from default values. If the form ""*identifier"" is\npresent, it is initialized to a tuple receiving any excess positional\nparameters, defaulting to the empty tuple. If the form\n""**identifier"" is present, it is initialized to a new dictionary\nreceiving any excess keyword arguments, defaulting to a new empty\ndictionary.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section Lambdas. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section Naming and binding for details.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section The standard\ntype hierarchy):\n\n classdef ::= "class" classname [inheritance] ":" suite\n inheritance ::= "(" [expression_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. It first evaluates the\ninheritance list, if present. Each item in the inheritance list\nshould evaluate to a class object or class type which allows\nsubclassing. The class\'s suite is then executed in a new execution\nframe (see section Naming and binding), using a newly created local\nnamespace and the original global namespace. (Usually, the suite\ncontains only function definitions.) When the class\'s suite finishes\nexecution, its execution frame is discarded but its local namespace is\nsaved. [4] A class object is then created using the inheritance list\nfor the base classes and the saved local namespace for the attribute\ndictionary. The class name is bound to this class object in the\noriginal local namespace.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass variables; they are shared by all instances. To create instance\nvariables, they can be set in a method with "self.name = value". Both\nclass and instance variables are accessible through the notation\n""self.name"", and an instance variable hides a class variable with\nthe same name when accessed in this way. Class variables can be used\nas defaults for instance variables, but using mutable values there can\nlead to unexpected results. For *new-style class*es, descriptors can\nbe used to create instance variables with different implementation\ndetails.\n\nClass definitions, like function definitions, may be wrapped by one or\nmore *decorator* expressions. The evaluation rules for the decorator\nexpressions are the same as for functions. The result must be a class\nobject, which is then bound to the class name.\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nNew in version 2.5.\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section The with\nstatement), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see Context Manager Types.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', 'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', - 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," the arguments\nare coerced using the coercion rules listed at *Coercion rules*. If\nboth arguments are standard numeric types, the following coercions are\napplied:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, if either argument is a long integer, the other is\n converted to long integer;\n\n* otherwise, both must be plain integers and no conversion is\n necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions can define their own\ncoercions.\n', - 'customization': u'\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_traceback" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.exc_traceback" or "sys.last_traceback". Circular references\n which are garbage are detected when the option cycle detector is\n enabled (it\'s on by default), but can only be cleaned up if there\n are no Python-level "__del__()" methods involved. Refer to the\n documentation for the "gc" module for more information about how\n "__del__()" methods are handled by the cycle detector,\n particularly the description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\n See also the *-R* command-line option.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function and by string conversions\n (reverse quotes) to compute the "official" string representation of\n an object. If at all possible, this should look like a valid\n Python expression that could be used to recreate an object with the\n same value (given an appropriate environment). If this is not\n possible, a string of the form "<...some useful description...>"\n should be returned. The return value must be a string object. If a\n class defines "__repr__()" but not "__str__()", then "__repr__()"\n is also used when an "informal" string representation of instances\n of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by the "str()" built-in function and by the "print"\n statement to compute the "informal" string representation of an\n object. This differs from "__repr__()" in that it does not have to\n be a valid Python expression: a more convenient or concise\n representation may be used instead. The return value must be a\n string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n New in version 2.1.\n\n These are the so-called "rich comparison" methods, and are called\n for comparison operators in preference to "__cmp__()" below. The\n correspondence between operator symbols and method names is as\n follows: "xy" call "x.__ne__(y)",\n "x>y" calls "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__cmp__(self, other)\n\n Called by comparison operations if rich comparison (see above) is\n not defined. Should return a negative integer if "self < other",\n zero if "self == other", a positive integer if "self > other". If\n no "__cmp__()", "__eq__()" or "__ne__()" operation is defined,\n class instances are compared by object identity ("address"). See\n also the description of "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys. (Note: the\n restriction that exceptions are not propagated by "__cmp__()" has\n been removed since Python 1.5.)\n\nobject.__rcmp__(self, other)\n\n Changed in version 2.1: No longer supported.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n If a class does not define a "__cmp__()" or "__eq__()" method it\n should not define a "__hash__()" operation either; if it defines\n "__cmp__()" or "__eq__()" but not "__hash__()", its instances will\n not be usable in hashed collections. If a class defines mutable\n objects and implements a "__cmp__()" or "__eq__()" method, it\n should not implement "__hash__()", since hashable collection\n implementations require that a object\'s hash value is immutable (if\n the object\'s hash value changes, it will be in the wrong hash\n bucket).\n\n User-defined classes have "__cmp__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns a result derived from\n "id(x)".\n\n Classes which inherit a "__hash__()" method from a parent class but\n change the meaning of "__cmp__()" or "__eq__()" such that the hash\n value returned is no longer appropriate (e.g. by switching to a\n value-based concept of equality instead of the default identity\n based equality) can explicitly flag themselves as being unhashable\n by setting "__hash__ = None" in the class definition. Doing so\n means that not only will instances of the class raise an\n appropriate "TypeError" when a program attempts to retrieve their\n hash value, but they will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)"\n (unlike classes which define their own "__hash__()" to explicitly\n raise "TypeError").\n\n Changed in version 2.5: "__hash__()" may now also return a long\n integer object; the 32-bit integer is then derived from the hash of\n that object.\n\n Changed in version 2.6: "__hash__" may now be set to "None" to\n explicitly flag instances of a class as unhashable.\n\nobject.__nonzero__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True", or their integer\n equivalents "0" or "1". When this method is not defined,\n "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__nonzero__()", all its instances are\n considered true.\n\nobject.__unicode__(self)\n\n Called to implement "unicode()" built-in; should return a Unicode\n object. When this method is not defined, string conversion is\n attempted, and the result of string conversion is converted to\n Unicode using the system default encoding.\n', + 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," the arguments\nare coerced using the coercion rules listed at Coercion rules. If\nboth arguments are standard numeric types, the following coercions are\napplied:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, if either argument is a long integer, the other is\n converted to long integer;\n\n* otherwise, both must be plain integers and no conversion is\n necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions can define their own\ncoercions.\n', + 'customization': u'\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_traceback" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.exc_traceback" or "sys.last_traceback". Circular references\n which are garbage are detected when the option cycle detector is\n enabled (it\'s on by default), but can only be cleaned up if there\n are no Python-level "__del__()" methods involved. Refer to the\n documentation for the "gc" module for more information about how\n "__del__()" methods are handled by the cycle detector,\n particularly the description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\n See also the "-R" command-line option.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function and by string conversions\n (reverse quotes) to compute the "official" string representation of\n an object. If at all possible, this should look like a valid\n Python expression that could be used to recreate an object with the\n same value (given an appropriate environment). If this is not\n possible, a string of the form "<...some useful description...>"\n should be returned. The return value must be a string object. If a\n class defines "__repr__()" but not "__str__()", then "__repr__()"\n is also used when an "informal" string representation of instances\n of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by the "str()" built-in function and by the "print"\n statement to compute the "informal" string representation of an\n object. This differs from "__repr__()" in that it does not have to\n be a valid Python expression: a more convenient or concise\n representation may be used instead. The return value must be a\n string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n New in version 2.1.\n\n These are the so-called "rich comparison" methods, and are called\n for comparison operators in preference to "__cmp__()" below. The\n correspondence between operator symbols and method names is as\n follows: "xy" call "x.__ne__(y)",\n "x>y" calls "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__cmp__(self, other)\n\n Called by comparison operations if rich comparison (see above) is\n not defined. Should return a negative integer if "self < other",\n zero if "self == other", a positive integer if "self > other". If\n no "__cmp__()", "__eq__()" or "__ne__()" operation is defined,\n class instances are compared by object identity ("address"). See\n also the description of "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys. (Note: the\n restriction that exceptions are not propagated by "__cmp__()" has\n been removed since Python 1.5.)\n\nobject.__rcmp__(self, other)\n\n Changed in version 2.1: No longer supported.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n If a class does not define a "__cmp__()" or "__eq__()" method it\n should not define a "__hash__()" operation either; if it defines\n "__cmp__()" or "__eq__()" but not "__hash__()", its instances will\n not be usable in hashed collections. If a class defines mutable\n objects and implements a "__cmp__()" or "__eq__()" method, it\n should not implement "__hash__()", since hashable collection\n implementations require that a object\'s hash value is immutable (if\n the object\'s hash value changes, it will be in the wrong hash\n bucket).\n\n User-defined classes have "__cmp__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns a result derived from\n "id(x)".\n\n Classes which inherit a "__hash__()" method from a parent class but\n change the meaning of "__cmp__()" or "__eq__()" such that the hash\n value returned is no longer appropriate (e.g. by switching to a\n value-based concept of equality instead of the default identity\n based equality) can explicitly flag themselves as being unhashable\n by setting "__hash__ = None" in the class definition. Doing so\n means that not only will instances of the class raise an\n appropriate "TypeError" when a program attempts to retrieve their\n hash value, but they will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)"\n (unlike classes which define their own "__hash__()" to explicitly\n raise "TypeError").\n\n Changed in version 2.5: "__hash__()" may now also return a long\n integer object; the 32-bit integer is then derived from the hash of\n that object.\n\n Changed in version 2.6: "__hash__" may now be set to "None" to\n explicitly flag instances of a class as unhashable.\n\nobject.__nonzero__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True", or their integer\n equivalents "0" or "1". When this method is not defined,\n "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__nonzero__()", all its instances are\n considered true.\n\nobject.__unicode__(self)\n\n Called to implement "unicode()" built-in; should return a Unicode\n object. When this method is not defined, string conversion is\n attempted, and the result of string conversion is converted to\n Unicode using the system default encoding.\n', 'debugger': u'\n"pdb" --- The Python Debugger\n*****************************\n\n**Source code:** Lib/pdb.py\n\n======================================================================\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible --- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 2.4: Restarting post-mortem behavior added.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "c" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print spam\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print spam\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement[, globals[, locals]])\n\n Execute the *statement* (given as a string) under debugger control.\n The debugger prompt appears before any code is executed; you can\n set breakpoints and type "continue", or you can step through the\n statement using "step" or "next" (all these commands are explained\n below). The optional *globals* and *locals* arguments specify the\n environment in which the code is executed; by default the\n dictionary of the module "__main__" is used. (See the explanation\n of the "exec" statement or the "eval()" built-in function.)\n\npdb.runeval(expression[, globals[, locals]])\n\n Evaluate the *expression* (given as a string) under debugger\n control. When "runeval()" returns, it returns the value of the\n expression. Otherwise this function is similar to "run()".\n\npdb.runcall(function[, argument, ...])\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem([traceback])\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 2.7: The *skip* argument.\n\n run(statement[, globals[, locals]])\n runeval(expression[, globals[, locals]])\n runcall(function[, argument, ...])\n set_trace()\n\n See the documentation for the functions explained above.\n', 'del': u'\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nIt is illegal to delete a name from the local namespace if it occurs\nas a free variable in a nested block.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n', - 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', + 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection The standard type hierarchy. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', 'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nIf "exec" is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n"SyntaxError" unless the exec explicitly specifies the local namespace\nfor the "exec". (In other words, "exec obj" would be illegal, but\n"exec obj in ns" would be legal.)\n\nThe "eval()", "execfile()", and "input()" functions and the "exec"\nstatement do not have access to the full environment for resolving\nnames. Names may be resolved in the local and global namespaces of\nthe caller. Free variables are not resolved in the nearest enclosing\nnamespace, but in the global namespace. [1] The "exec" statement and\nthe "eval()" and "execfile()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', - 'else': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', - 'exceptions': u'\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nExceptions can also be identified by strings, in which case the\n"except" clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', - 'exec': u'\nThe "exec" statement\n********************\n\n exec_stmt ::= "exec" or_expr ["in" expression ["," expression]]\n\nThis statement supports dynamic execution of Python code. The first\nexpression should evaluate to either a Unicode string, a *Latin-1*\nencoded string, an open file object, a code object, or a tuple. If it\nis a string, the string is parsed as a suite of Python statements\nwhich is then executed (unless a syntax error occurs). [1] If it is an\nopen file, the file is parsed until EOF and executed. If it is a code\nobject, it is simply executed. For the interpretation of a tuple, see\nbelow. In all cases, the code that\'s executed is expected to be valid\nas file input (see section *File input*). Be aware that the "return"\nand "yield" statements may not be used outside of function definitions\neven within the context of code passed to the "exec" statement.\n\nIn all cases, if the optional parts are omitted, the code is executed\nin the current scope. If only the first expression after "in" is\nspecified, it should be a dictionary, which will be used for both the\nglobal and the local variables. If two expressions are given, they\nare used for the global and local variables, respectively. If\nprovided, *locals* can be any mapping object. Remember that at module\nlevel, globals and locals are the same dictionary. If two separate\nobjects are given as *globals* and *locals*, the code will be executed\nas if it were embedded in a class definition.\n\nThe first expression may also be a tuple of length 2 or 3. In this\ncase, the optional parts must be omitted. The form "exec(expr,\nglobals)" is equivalent to "exec expr in globals", while the form\n"exec(expr, globals, locals)" is equivalent to "exec expr in globals,\nlocals". The tuple form of "exec" provides compatibility with Python\n3, where "exec" is a function rather than a statement.\n\nChanged in version 2.4: Formerly, *locals* was required to be a\ndictionary.\n\nAs a side effect, an implementation may insert additional keys into\nthe dictionaries given besides those corresponding to variable names\nset by the executed code. For example, the current implementation may\nadd a reference to the dictionary of the built-in module "__builtin__"\nunder the key "__builtins__" (!).\n\n**Programmer\'s hints:** dynamic evaluation of expressions is supported\nby the built-in function "eval()". The built-in functions "globals()"\nand "locals()" return the current global and local dictionary,\nrespectively, which may be useful to pass around for use by "exec".\n\n-[ Footnotes ]-\n\n[1] Note that the parser only accepts the Unix-style end of line\n convention. If you are reading the code from a file, make sure to\n use *universal newlines* mode to convert Windows or Mac-style\n newlines.\n', - 'execmodel': u'\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The file read by the\nbuilt-in function "execfile()" is a code block. The string argument\npassed to the built-in function "eval()" and to the "exec" statement\nis a code block. The expression read and evaluated by the built-in\nfunction "input()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes generator expressions since\nthey are implemented using a function scope. This means that the\nfollowing will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block.\nIf a name is bound at the module level, it is a global variable. (The\nvariables of the module code block are local and global.) If a\nvariable is used in a code block but not defined there, it is a *free\nvariable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, in the\nsecond position of an "except" clause header or after "as" in a "with"\nstatement. The "import" statement of the form "from ... import *"\nbinds all names defined in the imported module, except those beginning\nwith an underscore. This form may only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name). It\nis illegal to unbind a name that is referenced by an enclosing scope;\nthe compiler will report a "SyntaxError".\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the global statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "__builtin__". The global namespace is searched first.\nIf the name is not found there, the builtins namespace is searched.\nThe global statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "__builtin__" (note: no\n\'s\'); when in any other module, "__builtins__" is an alias for the\ndictionary of the "__builtin__" module itself. "__builtins__" can be\nset to a user-created dictionary to create a weak form of restricted\nexecution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "__builtin__" (no \'s\') module and modify its attributes\nappropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nIf "exec" is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n"SyntaxError" unless the exec explicitly specifies the local namespace\nfor the "exec". (In other words, "exec obj" would be illegal, but\n"exec obj in ns" would be legal.)\n\nThe "eval()", "execfile()", and "input()" functions and the "exec"\nstatement do not have access to the full environment for resolving\nnames. Names may be resolved in the local and global namespaces of\nthe caller. Free variables are not resolved in the nearest enclosing\nnamespace, but in the global namespace. [1] The "exec" statement and\nthe "eval()" and "execfile()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nExceptions can also be identified by strings, in which case the\n"except" clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'else': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section Boolean operations\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'exceptions': u'\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nExceptions can also be identified by strings, in which case the\n"except" clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section The try\nstatement and "raise" statement in section The raise statement.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'exec': u'\nThe "exec" statement\n********************\n\n exec_stmt ::= "exec" or_expr ["in" expression ["," expression]]\n\nThis statement supports dynamic execution of Python code. The first\nexpression should evaluate to either a Unicode string, a *Latin-1*\nencoded string, an open file object, a code object, or a tuple. If it\nis a string, the string is parsed as a suite of Python statements\nwhich is then executed (unless a syntax error occurs). [1] If it is an\nopen file, the file is parsed until EOF and executed. If it is a code\nobject, it is simply executed. For the interpretation of a tuple, see\nbelow. In all cases, the code that\'s executed is expected to be valid\nas file input (see section File input). Be aware that the "return"\nand "yield" statements may not be used outside of function definitions\neven within the context of code passed to the "exec" statement.\n\nIn all cases, if the optional parts are omitted, the code is executed\nin the current scope. If only the first expression after "in" is\nspecified, it should be a dictionary, which will be used for both the\nglobal and the local variables. If two expressions are given, they\nare used for the global and local variables, respectively. If\nprovided, *locals* can be any mapping object. Remember that at module\nlevel, globals and locals are the same dictionary. If two separate\nobjects are given as *globals* and *locals*, the code will be executed\nas if it were embedded in a class definition.\n\nThe first expression may also be a tuple of length 2 or 3. In this\ncase, the optional parts must be omitted. The form "exec(expr,\nglobals)" is equivalent to "exec expr in globals", while the form\n"exec(expr, globals, locals)" is equivalent to "exec expr in globals,\nlocals". The tuple form of "exec" provides compatibility with Python\n3, where "exec" is a function rather than a statement.\n\nChanged in version 2.4: Formerly, *locals* was required to be a\ndictionary.\n\nAs a side effect, an implementation may insert additional keys into\nthe dictionaries given besides those corresponding to variable names\nset by the executed code. For example, the current implementation may\nadd a reference to the dictionary of the built-in module "__builtin__"\nunder the key "__builtins__" (!).\n\n**Programmer\'s hints:** dynamic evaluation of expressions is supported\nby the built-in function "eval()". The built-in functions "globals()"\nand "locals()" return the current global and local dictionary,\nrespectively, which may be useful to pass around for use by "exec".\n\n-[ Footnotes ]-\n\n[1] Note that the parser only accepts the Unix-style end of line\n convention. If you are reading the code from a file, make sure to\n use *universal newlines* mode to convert Windows or Mac-style\n newlines.\n', + 'execmodel': u'\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The file read by the\nbuilt-in function "execfile()" is a code block. The string argument\npassed to the built-in function "eval()" and to the "exec" statement\nis a code block. The expression read and evaluated by the built-in\nfunction "input()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes generator expressions since\nthey are implemented using a function scope. This means that the\nfollowing will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block.\nIf a name is bound at the module level, it is a global variable. (The\nvariables of the module code block are local and global.) If a\nvariable is used in a code block but not defined there, it is a *free\nvariable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, in the\nsecond position of an "except" clause header or after "as" in a "with"\nstatement. The "import" statement of the form "from ... import *"\nbinds all names defined in the imported module, except those beginning\nwith an underscore. This form may only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name). It\nis illegal to unbind a name that is referenced by an enclosing scope;\nthe compiler will report a "SyntaxError".\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the global statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "__builtin__". The global namespace is searched first.\nIf the name is not found there, the builtins namespace is searched.\nThe global statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "__builtin__" (note: no\n\'s\'); when in any other module, "__builtins__" is an alias for the\ndictionary of the "__builtin__" module itself. "__builtins__" can be\nset to a user-created dictionary to create a weak form of restricted\nexecution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "__builtin__" (no \'s\') module and modify its attributes\nappropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nIf "exec" is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n"SyntaxError" unless the exec explicitly specifies the local namespace\nfor the "exec". (In other words, "exec obj" would be illegal, but\n"exec obj in ns" would be legal.)\n\nThe "eval()", "execfile()", and "input()" functions and the "exec"\nstatement do not have access to the full environment for resolving\nnames. Names may be resolved in the local and global namespaces of\nthe caller. Free variables are not resolved in the nearest enclosing\nnamespace, but in the global namespace. [1] The "exec" statement and\nthe "eval()" and "execfile()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nExceptions can also be identified by strings, in which case the\n"except" clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section The try\nstatement and "raise" statement in section The raise statement.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', 'exprlists': u'\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n', 'floating': u'\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts of floating point numbers can\nlook like octal integers, but are interpreted using radix 10. For\nexample, "077e010" is legal, and denotes the same number as "77e10".\nThe allowed range of floating point literals is implementation-\ndependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n', 'for': u'\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments, and then the suite is executed. When the items are\nexhausted (which is immediately when the sequence is empty), the suite\nin the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nThe target list is not deleted when the loop is finished, but if the\nsequence is empty, it will not have been assigned to at all by the\nloop. Hint: the built-in function "range()" returns a sequence of\nintegers suitable to emulate the effect of Pascal\'s "for i := a to b\ndo"; e.g., "range(3)" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', - 'formatstrings': u'\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 2.7: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nTwo conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, and "\'!r\'" which calls "repr()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use "{" and "}" as *fill*\nchar while using the "str.format()" method; this limitation however\ndoesn\'t affect the "format()" function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option is only valid for integers, and only for binary,\noctal, or hexadecimal output. If present, it specifies that the\noutput will be prefixed by "\'0b\'", "\'0o\'", or "\'0x\'", respectively.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 2.7: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero ("\'0\'") character enables sign-\naware zero-padding for numeric types. This is equivalent to a *fill*\ncharacter of "\'0\'" with an *alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'". |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n | | rounds the number to "p" significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type "\'e\'" and precision "p-1" |\n | | would have exponent "exp". Then if "-4 <= exp < p", the |\n | | number is formatted with presentation type "\'f\'" and |\n | | precision "p-1-exp". Otherwise, the number is formatted |\n | | with presentation type "\'e\'" and precision "p-1". In both |\n | | cases insignificant trailing zeros are removed from the |\n | | significand, and the decimal point is also removed if |\n | | there are no remaining digits following it. Positive and |\n | | negative infinity, positive and negative zero, and nans, |\n | | are formatted as "inf", "-inf", "0", "-0" and "nan" |\n | | respectively, regardless of the precision. A precision of |\n | | "0" is treated as equivalent to a precision of "1". The |\n | | default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n | | the number gets too large. The representations of infinity |\n | | and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n | | fixed ("\'f\'") format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'g\'". |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 2.7+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point(object):\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19.5\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 88.64%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12):\n ... for base in \'dXob\':\n ... print \'{0:{width}{base}}\'.format(num, base=base, width=width),\n ... print\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', - 'function': u'\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n decorated ::= decorators (classdef | funcdef)\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" identifier ["," "**" identifier]\n | "**" identifier\n | defparameter [","] )\n defparameter ::= parameter ["=" expression]\n sublist ::= parameter ("," parameter)* [","]\n parameter ::= identifier | "(" sublist ")"\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code:\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to:\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more top-level *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters must also have a default value --- this is a syntactic\nrestriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n', + 'formatstrings': u'\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the Format Specification Mini-Language section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 2.7: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nTwo conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, and "\'!r\'" which calls "repr()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the Format examples section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see Format String Syntax). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use "{" and "}" as *fill*\nchar while using the "str.format()" method; this limitation however\ndoesn\'t affect the "format()" function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option is only valid for integers, and only for binary,\noctal, or hexadecimal output. If present, it specifies that the\noutput will be prefixed by "\'0b\'", "\'0o\'", or "\'0x\'", respectively.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 2.7: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero ("\'0\'") character enables sign-\naware zero-padding for numeric types. This is equivalent to a *fill*\ncharacter of "\'0\'" with an *alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'". |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n | | rounds the number to "p" significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type "\'e\'" and precision "p-1" |\n | | would have exponent "exp". Then if "-4 <= exp < p", the |\n | | number is formatted with presentation type "\'f\'" and |\n | | precision "p-1-exp". Otherwise, the number is formatted |\n | | with presentation type "\'e\'" and precision "p-1". In both |\n | | cases insignificant trailing zeros are removed from the |\n | | significand, and the decimal point is also removed if |\n | | there are no remaining digits following it. Positive and |\n | | negative infinity, positive and negative zero, and nans, |\n | | are formatted as "inf", "-inf", "0", "-0" and "nan" |\n | | respectively, regardless of the precision. A precision of |\n | | "0" is treated as equivalent to a precision of "1". The |\n | | default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n | | the number gets too large. The representations of infinity |\n | | and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n | | fixed ("\'f\'") format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'g\'". |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 2.7+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point(object):\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19.5\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 88.64%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12):\n ... for base in \'dXob\':\n ... print \'{0:{width}{base}}\'.format(num, base=base, width=width),\n ... print\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', + 'function': u'\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection The standard type hierarchy):\n\n decorated ::= decorators (classdef | funcdef)\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" identifier ["," "**" identifier]\n | "**" identifier\n | defparameter [","] )\n defparameter ::= parameter ["=" expression]\n sublist ::= parameter ("," parameter)* [","]\n parameter ::= identifier | "(" sublist ")"\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code:\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to:\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more top-level *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters must also have a default value --- this is a syntactic\nrestriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section Calls.\nA function call always assigns values to all parameters mentioned in\nthe parameter list, either from position arguments, from keyword\narguments, or from default values. If the form ""*identifier"" is\npresent, it is initialized to a tuple receiving any excess positional\nparameters, defaulting to the empty tuple. If the form\n""**identifier"" is present, it is initialized to a new dictionary\nreceiving any excess keyword arguments, defaulting to a new empty\ndictionary.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section Lambdas. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section Naming and binding for details.\n', 'global': u'\nThe "global" statement\n**********************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe "global" statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without "global", although free variables may refer to\nglobals without being declared global.\n\nNames listed in a "global" statement must not be used in the same code\nblock textually preceding that "global" statement.\n\nNames listed in a "global" statement must not be defined as formal\nparameters or in a "for" loop control target, "class" definition,\nfunction definition, or "import" statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the "global" is a directive to the parser. It\napplies only to code parsed at the same time as the "global"\nstatement. In particular, a "global" statement contained in an "exec"\nstatement does not affect the code block *containing* the "exec"\nstatement, and code contained in an "exec" statement is unaffected by\n"global" statements in the code containing the "exec" statement. The\nsame applies to the "eval()", "execfile()" and "compile()" functions.\n', - 'id-classes': u'\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "__builtin__" module. When\n not in interactive mode, "_" has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'identifiers': u'\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions:\n\n identifier ::= (letter|"_") (letter | digit | "_")*\n letter ::= lowercase | uppercase\n lowercase ::= "a"..."z"\n uppercase ::= "A"..."Z"\n digit ::= "0"..."9"\n\nIdentifiers are unlimited in length. Case is significant.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n and del from not while\n as elif global or with\n assert else if pass yield\n break except import print\n class exec in raise\n continue finally is return\n def for lambda try\n\nChanged in version 2.4: "None" became a constant and is now recognized\nby the compiler as a name for the built-in object "None". Although it\nis not a keyword, you cannot assign a different object to it.\n\nChanged in version 2.5: Using "as" and "with" as identifiers triggers\na warning. To use them as keywords, enable the "with_statement"\nfuture feature .\n\nChanged in version 2.6: "as" and "with" are full keywords.\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "__builtin__" module. When\n not in interactive mode, "_" has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'if': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'id-classes': u'\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "__builtin__" module. When\n not in interactive mode, "_" has no special meaning and is not\n defined. See section The import statement.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the Special method names section and\n elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section Identifiers (Names).\n', + 'identifiers': u'\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions:\n\n identifier ::= (letter|"_") (letter | digit | "_")*\n letter ::= lowercase | uppercase\n lowercase ::= "a"..."z"\n uppercase ::= "A"..."Z"\n digit ::= "0"..."9"\n\nIdentifiers are unlimited in length. Case is significant.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n and del from not while\n as elif global or with\n assert else if pass yield\n break except import print\n class exec in raise\n continue finally is return\n def for lambda try\n\nChanged in version 2.4: "None" became a constant and is now recognized\nby the compiler as a name for the built-in object "None". Although it\nis not a keyword, you cannot assign a different object to it.\n\nChanged in version 2.5: Using "as" and "with" as identifiers triggers\na warning. To use them as keywords, enable the "with_statement"\nfuture feature .\n\nChanged in version 2.6: "as" and "with" are full keywords.\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "__builtin__" module. When\n not in interactive mode, "_" has no special meaning and is not\n defined. See section The import statement.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the Special method names section and\n elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section Identifiers (Names).\n', + 'if': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section Boolean operations\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', 'imaginary': u'\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', - 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nImport statements are executed in two steps: (1) find a module, and\ninitialize it if necessary; (2) define a name or names in the local\nnamespace (of the scope where the "import" statement occurs). The\nstatement comes in two forms differing on whether it uses the "from"\nkeyword. The first form (without "from") repeats these steps for each\nidentifier in the list. The form with "from" performs step (1) once,\nand then performs step (2) repeatedly.\n\nTo understand how step (1) occurs, one must first understand how\nPython handles hierarchical naming of modules. To help organize\nmodules and provide a hierarchy in naming, Python has a concept of\npackages. A package can contain other packages and modules while\nmodules cannot contain other modules or packages. From a file system\nperspective, packages are directories and modules are files.\n\nOnce the name of the module is known (unless otherwise specified, the\nterm "module" will refer to both packages and modules), searching for\nthe module or package can begin. The first place checked is\n"sys.modules", the cache of all modules that have been imported\npreviously. If the module is found there then it is used in step (2)\nof import.\n\nIf the module is not found in the cache, then "sys.meta_path" is\nsearched (the specification for "sys.meta_path" can be found in **PEP\n302**). The object is a list of *finder* objects which are queried in\norder as to whether they know how to load the module by calling their\n"find_module()" method with the name of the module. If the module\nhappens to be contained within a package (as denoted by the existence\nof a dot in the name), then a second argument to "find_module()" is\ngiven as the value of the "__path__" attribute from the parent package\n(everything up to the last dot in the name of the module being\nimported). If a finder can find the module it returns a *loader*\n(discussed later) or returns "None".\n\nIf none of the finders on "sys.meta_path" are able to find the module\nthen some implicitly defined finders are queried. Implementations of\nPython vary in what implicit meta path finders are defined. The one\nthey all do define, though, is one that handles "sys.path_hooks",\n"sys.path_importer_cache", and "sys.path".\n\nThe implicit finder searches for the requested module in the "paths"\nspecified in one of two places ("paths" do not have to be file system\npaths). If the module being imported is supposed to be contained\nwithin a package then the second argument passed to "find_module()",\n"__path__" on the parent package, is used as the source of paths. If\nthe module is not contained in a package then "sys.path" is used as\nthe source of paths.\n\nOnce the source of paths is chosen it is iterated over to find a\nfinder that can handle that path. The dict at\n"sys.path_importer_cache" caches finders for paths and is checked for\na finder. If the path does not have a finder cached then\n"sys.path_hooks" is searched by calling each object in the list with a\nsingle argument of the path, returning a finder or raises\n"ImportError". If a finder is returned then it is cached in\n"sys.path_importer_cache" and then used for that path entry. If no\nfinder can be found but the path exists then a value of "None" is\nstored in "sys.path_importer_cache" to signify that an implicit, file-\nbased finder that handles modules stored as individual files should be\nused for that path. If the path does not exist then a finder which\nalways returns "None" is placed in the cache for the path.\n\nIf no finder can find the module then "ImportError" is raised.\nOtherwise some finder returned a loader whose "load_module()" method\nis called with the name of the module to load (see **PEP 302** for the\noriginal definition of loaders). A loader has several responsibilities\nto perform on a module it loads. First, if the module already exists\nin "sys.modules" (a possibility if the loader is called outside of the\nimport machinery) then it is to use that module for initialization and\nnot a new module. But if the module does not exist in "sys.modules"\nthen it is to be added to that dict before initialization begins. If\nan error occurs during loading of the module and it was added to\n"sys.modules" it is to be removed from the dict. If an error occurs\nbut the module was already in "sys.modules" it is left in the dict.\n\nThe loader must set several attributes on the module. "__name__" is to\nbe set to the name of the module. "__file__" is to be the "path" to\nthe file unless the module is built-in (and thus listed in\n"sys.builtin_module_names") in which case the attribute is not set. If\nwhat is being imported is a package then "__path__" is to be set to a\nlist of paths to be searched when looking for modules and packages\ncontained within the package being imported. "__package__" is optional\nbut should be set to the name of package that contains the module or\npackage (the empty string is used for module not contained in a\npackage). "__loader__" is also optional but should be set to the\nloader object that is loading the module.\n\nIf an error occurs during loading then the loader raises "ImportError"\nif some other exception is not already being propagated. Otherwise the\nloader returns the module that was loaded and initialized.\n\nWhen step (1) finishes without raising an exception, step (2) can\nbegin.\n\nThe first form of "import" statement binds the module name in the\nlocal namespace to the module object, and then goes on to import the\nnext identifier, if any. If the module name is followed by "as", the\nname following "as" is used as the local name for the module.\n\nThe "from" form does not bind the module name: it goes through the\nlist of identifiers, looks each one of them up in the module found in\nstep (1), and binds the name in the local namespace to the object thus\nfound. As with the first form of "import", an alternate local name\ncan be supplied by specifying ""as" localname". If a name is not\nfound, "ImportError" is raised. If the list of identifiers is\nreplaced by a star ("\'*\'"), all public names defined in the module are\nbound in the local namespace of the "import" statement..\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe "from" form with "*" may only occur in a module scope. If the\nwild card form of import --- "import *" --- is used in a function and\nthe function contains or is a nested block with free variables, the\ncompiler will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 2.6 are "unicode_literals",\n"print_function", "absolute_import", "division", "generators",\n"nested_scopes" and "with_statement". "generators", "with_statement",\n"nested_scopes" are redundant in Python version 2.6 and above because\nthey are always enabled.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by an "exec" statement or calls to the built-in\nfunctions "compile()" and "execfile()" that occur in a module "M"\ncontaining a future statement will, by default, use the new syntax or\nsemantics associated with the future statement. This can, starting\nwith Python 2.2 be controlled by optional arguments to "compile()" ---\nsee the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', - 'in': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe forms "<>" and "!=" are equivalent; for consistency with C, "!="\nis preferred; where "!=" is mentioned below "<>" is also accepted.\nThe "<>" spelling is considered obsolescent.\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, objects of\ndifferent types *always* compare unequal, and are ordered consistently\nbut arbitrarily. You can control comparison behavior of objects of\nnon-built-in types by defining a "__cmp__" method or rich comparison\nmethods like "__gt__", described in section *Special method names*.\n\n(This unusual definition of comparison was used to simplify the\ndefinition of operations like sorting and the "in" and "not in"\noperators. In the future, the comparison rules for objects of\ndifferent types are likely to change.)\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. Unicode and 8-bit strings are fully interoperable in\n this behavior. [4]\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "cmp([1,2,x], [1,2,y])" returns\n the same as "cmp(x,y)". If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, "[1,2] <\n [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if their sorted\n (key, value) lists compare equal. [5] Outcomes other than equality\n are resolved consistently, but are not otherwise defined. [6]\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nThe operators "in" and "not in" test for collection membership. "x in\ns" evaluates to true if *x* is a member of the collection *s*, and\nfalse otherwise. "x not in s" returns the negation of "x in s". The\ncollection membership test has traditionally been bound to sequences;\nan object is a member of a collection if the collection is a sequence\nand contains an element equal to that object. However, it make sense\nfor many other object types to support membership tests without being\na sequence. In particular, dictionaries (for keys) and sets support\nmembership testing.\n\nFor the list and tuple types, "x in y" is true if and only if there\nexists an index *i* such that "x == y[i]" is true.\n\nFor the Unicode and string types, "x in y" is true if and only if *x*\nis a substring of *y*. An equivalent test is "y.find(x) != -1".\nNote, *x* and *y* need not be the same type; consequently, "u\'ab\' in\n\'abc\'" will return "True". Empty strings are always considered to be a\nsubstring of any other string, so """ in "abc"" will return "True".\n\nChanged in version 2.3: Previously, *x* was required to be a string of\nlength "1".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [7]\n', + 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nImport statements are executed in two steps: (1) find a module, and\ninitialize it if necessary; (2) define a name or names in the local\nnamespace (of the scope where the "import" statement occurs). The\nstatement comes in two forms differing on whether it uses the "from"\nkeyword. The first form (without "from") repeats these steps for each\nidentifier in the list. The form with "from" performs step (1) once,\nand then performs step (2) repeatedly.\n\nTo understand how step (1) occurs, one must first understand how\nPython handles hierarchical naming of modules. To help organize\nmodules and provide a hierarchy in naming, Python has a concept of\npackages. A package can contain other packages and modules while\nmodules cannot contain other modules or packages. From a file system\nperspective, packages are directories and modules are files.\n\nOnce the name of the module is known (unless otherwise specified, the\nterm "module" will refer to both packages and modules), searching for\nthe module or package can begin. The first place checked is\n"sys.modules", the cache of all modules that have been imported\npreviously. If the module is found there then it is used in step (2)\nof import.\n\nIf the module is not found in the cache, then "sys.meta_path" is\nsearched (the specification for "sys.meta_path" can be found in **PEP\n302**). The object is a list of *finder* objects which are queried in\norder as to whether they know how to load the module by calling their\n"find_module()" method with the name of the module. If the module\nhappens to be contained within a package (as denoted by the existence\nof a dot in the name), then a second argument to "find_module()" is\ngiven as the value of the "__path__" attribute from the parent package\n(everything up to the last dot in the name of the module being\nimported). If a finder can find the module it returns a *loader*\n(discussed later) or returns "None".\n\nIf none of the finders on "sys.meta_path" are able to find the module\nthen some implicitly defined finders are queried. Implementations of\nPython vary in what implicit meta path finders are defined. The one\nthey all do define, though, is one that handles "sys.path_hooks",\n"sys.path_importer_cache", and "sys.path".\n\nThe implicit finder searches for the requested module in the "paths"\nspecified in one of two places ("paths" do not have to be file system\npaths). If the module being imported is supposed to be contained\nwithin a package then the second argument passed to "find_module()",\n"__path__" on the parent package, is used as the source of paths. If\nthe module is not contained in a package then "sys.path" is used as\nthe source of paths.\n\nOnce the source of paths is chosen it is iterated over to find a\nfinder that can handle that path. The dict at\n"sys.path_importer_cache" caches finders for paths and is checked for\na finder. If the path does not have a finder cached then\n"sys.path_hooks" is searched by calling each object in the list with a\nsingle argument of the path, returning a finder or raises\n"ImportError". If a finder is returned then it is cached in\n"sys.path_importer_cache" and then used for that path entry. If no\nfinder can be found but the path exists then a value of "None" is\nstored in "sys.path_importer_cache" to signify that an implicit, file-\nbased finder that handles modules stored as individual files should be\nused for that path. If the path does not exist then a finder which\nalways returns "None" is placed in the cache for the path.\n\nIf no finder can find the module then "ImportError" is raised.\nOtherwise some finder returned a loader whose "load_module()" method\nis called with the name of the module to load (see **PEP 302** for the\noriginal definition of loaders). A loader has several responsibilities\nto perform on a module it loads. First, if the module already exists\nin "sys.modules" (a possibility if the loader is called outside of the\nimport machinery) then it is to use that module for initialization and\nnot a new module. But if the module does not exist in "sys.modules"\nthen it is to be added to that dict before initialization begins. If\nan error occurs during loading of the module and it was added to\n"sys.modules" it is to be removed from the dict. If an error occurs\nbut the module was already in "sys.modules" it is left in the dict.\n\nThe loader must set several attributes on the module. "__name__" is to\nbe set to the name of the module. "__file__" is to be the "path" to\nthe file unless the module is built-in (and thus listed in\n"sys.builtin_module_names") in which case the attribute is not set. If\nwhat is being imported is a package then "__path__" is to be set to a\nlist of paths to be searched when looking for modules and packages\ncontained within the package being imported. "__package__" is optional\nbut should be set to the name of package that contains the module or\npackage (the empty string is used for module not contained in a\npackage). "__loader__" is also optional but should be set to the\nloader object that is loading the module.\n\nIf an error occurs during loading then the loader raises "ImportError"\nif some other exception is not already being propagated. Otherwise the\nloader returns the module that was loaded and initialized.\n\nWhen step (1) finishes without raising an exception, step (2) can\nbegin.\n\nThe first form of "import" statement binds the module name in the\nlocal namespace to the module object, and then goes on to import the\nnext identifier, if any. If the module name is followed by "as", the\nname following "as" is used as the local name for the module.\n\nThe "from" form does not bind the module name: it goes through the\nlist of identifiers, looks each one of them up in the module found in\nstep (1), and binds the name in the local namespace to the object thus\nfound. As with the first form of "import", an alternate local name\ncan be supplied by specifying ""as" localname". If a name is not\nfound, "ImportError" is raised. If the list of identifiers is\nreplaced by a star ("\'*\'"), all public names defined in the module are\nbound in the local namespace of the "import" statement..\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe "from" form with "*" may only occur in a module scope. If the\nwild card form of import --- "import *" --- is used in a function and\nthe function contains or is a nested block with free variables, the\ncompiler will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 2.6 are "unicode_literals",\n"print_function", "absolute_import", "division", "generators",\n"nested_scopes" and "with_statement". "generators", "with_statement",\n"nested_scopes" are redundant in Python version 2.6 and above because\nthey are always enabled.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by an "exec" statement or calls to the built-in\nfunctions "compile()" and "execfile()" that occur in a module "M"\ncontaining a future statement will, by default, use the new syntax or\nsemantics associated with the future statement. This can, starting\nwith Python 2.2 be controlled by optional arguments to "compile()" ---\nsee the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the "-i" option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', + 'in': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe forms "<>" and "!=" are equivalent; for consistency with C, "!="\nis preferred; where "!=" is mentioned below "<>" is also accepted.\nThe "<>" spelling is considered obsolescent.\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, objects of\ndifferent types *always* compare unequal, and are ordered consistently\nbut arbitrarily. You can control comparison behavior of objects of\nnon-built-in types by defining a "__cmp__" method or rich comparison\nmethods like "__gt__", described in section Special method names.\n\n(This unusual definition of comparison was used to simplify the\ndefinition of operations like sorting and the "in" and "not in"\noperators. In the future, the comparison rules for objects of\ndifferent types are likely to change.)\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. Unicode and 8-bit strings are fully interoperable in\n this behavior. [4]\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "cmp([1,2,x], [1,2,y])" returns\n the same as "cmp(x,y)". If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, "[1,2] <\n [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if their sorted\n (key, value) lists compare equal. [5] Outcomes other than equality\n are resolved consistently, but are not otherwise defined. [6]\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nThe operators "in" and "not in" test for collection membership. "x in\ns" evaluates to true if *x* is a member of the collection *s*, and\nfalse otherwise. "x not in s" returns the negation of "x in s". The\ncollection membership test has traditionally been bound to sequences;\nan object is a member of a collection if the collection is a sequence\nand contains an element equal to that object. However, it make sense\nfor many other object types to support membership tests without being\na sequence. In particular, dictionaries (for keys) and sets support\nmembership testing.\n\nFor the list and tuple types, "x in y" is true if and only if there\nexists an index *i* such that "x == y[i]" is true.\n\nFor the Unicode and string types, "x in y" is true if and only if *x*\nis a substring of *y*. An equivalent test is "y.find(x) != -1".\nNote, *x* and *y* need not be the same type; consequently, "u\'ab\' in\n\'abc\'" will return "True". Empty strings are always considered to be a\nsubstring of any other string, so """ in "abc"" will return "True".\n\nChanged in version 2.3: Previously, *x* was required to be a string of\nlength "1".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [7]\n', 'integers': u'\nInteger and long integer literals\n*********************************\n\nInteger and long integer literals are described by the following\nlexical definitions:\n\n longinteger ::= integer ("l" | "L")\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"\n octinteger ::= "0" ("o" | "O") octdigit+ | "0" octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n nonzerodigit ::= "1"..."9"\n octdigit ::= "0"..."7"\n bindigit ::= "0" | "1"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n\nAlthough both lower case "\'l\'" and upper case "\'L\'" are allowed as\nsuffix for long integers, it is strongly recommended to always use\n"\'L\'", since the letter "\'l\'" looks too much like the digit "\'1\'".\n\nPlain integer literals that are above the largest representable plain\ninteger (e.g., 2147483647 when using 32-bit arithmetic) are accepted\nas if they were long integers instead. [1] There is no limit for long\ninteger literals apart from what can be stored in available memory.\n\nSome examples of plain integer literals (first row) and long integer\nliterals (second and third rows):\n\n 7 2147483647 0177\n 3L 79228162514264337593543950336L 0377L 0x100000000L\n 79228162514264337593543950336 0xdeadbeef\n', - 'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n old_lambda_expr ::= "lambda" [parameter_list]: old_expression\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def name(arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements.\n', + 'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n old_lambda_expr ::= "lambda" [parameter_list]: old_expression\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def name(arguments):\n return expression\n\nSee section Function definitions for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements.\n', 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | list_comprehension] "]"\n list_comprehension ::= expression list_for\n list_for ::= "for" target_list "in" old_expression_list [list_iter]\n old_expression_list ::= old_expression [("," old_expression)+ [","]]\n old_expression ::= or_test | old_lambda_expr\n list_iter ::= list_for | list_if\n list_if ::= "if" old_expression [list_iter]\n\nA list display yields a new list object. Its contents are specified\nby providing either a list of expressions or a list comprehension.\nWhen a comma-separated list of expressions is supplied, its elements\nare evaluated from left to right and placed into the list object in\nthat order. When a list comprehension is supplied, it consists of a\nsingle expression followed by at least one "for" clause and zero or\nmore "for" or "if" clauses. In this case, the elements of the new\nlist are those that would be produced by considering each of the "for"\nor "if" clauses a block, nesting from left to right, and evaluating\nthe expression to produce a list element each time the innermost block\nis reached [1].\n', 'naming': u'\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The file read by the\nbuilt-in function "execfile()" is a code block. The string argument\npassed to the built-in function "eval()" and to the "exec" statement\nis a code block. The expression read and evaluated by the built-in\nfunction "input()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes generator expressions since\nthey are implemented using a function scope. This means that the\nfollowing will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block.\nIf a name is bound at the module level, it is a global variable. (The\nvariables of the module code block are local and global.) If a\nvariable is used in a code block but not defined there, it is a *free\nvariable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, in the\nsecond position of an "except" clause header or after "as" in a "with"\nstatement. The "import" statement of the form "from ... import *"\nbinds all names defined in the imported module, except those beginning\nwith an underscore. This form may only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name). It\nis illegal to unbind a name that is referenced by an enclosing scope;\nthe compiler will report a "SyntaxError".\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the global statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "__builtin__". The global namespace is searched first.\nIf the name is not found there, the builtins namespace is searched.\nThe global statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "__builtin__" (note: no\n\'s\'); when in any other module, "__builtins__" is an alias for the\ndictionary of the "__builtin__" module itself. "__builtins__" can be\nset to a user-created dictionary to create a weak form of restricted\nexecution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "__builtin__" (no \'s\') module and modify its attributes\nappropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nIf "exec" is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n"SyntaxError" unless the exec explicitly specifies the local namespace\nfor the "exec". (In other words, "exec obj" would be illegal, but\n"exec obj in ns" would be legal.)\n\nThe "eval()", "execfile()", and "input()" functions and the "exec"\nstatement do not have access to the full environment for resolving\nnames. Names may be resolved in the local and global namespaces of\nthe caller. Free variables are not resolved in the nearest enclosing\nnamespace, but in the global namespace. [1] The "exec" statement and\nthe "eval()" and "execfile()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', 'numbers': u'\nNumeric literals\n****************\n\nThere are four types of numeric literals: plain integers, long\nintegers, floating point numbers, and imaginary numbers. There are no\ncomplex literals (complex numbers can be formed by adding a real\nnumber and an imaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', 'numeric-types': u'\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "//", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()" (described\n below). Note that "__pow__()" should be defined to accept an\n optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__div__(self, other)\nobject.__truediv__(self, other)\n\n The division operator ("/") is implemented by these methods. The\n "__truediv__()" method is used when "__future__.division" is in\n effect, otherwise "__div__()" is used. If only one of these two\n methods is defined, the object will not support division in the\n alternate context; "TypeError" will be raised instead.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rdiv__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__idiv__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__long__(self)\nobject.__float__(self)\n\n Called to implement the built-in functions "complex()", "int()",\n "long()", and "float()". Should return a value of the appropriate\n type.\n\nobject.__oct__(self)\nobject.__hex__(self)\n\n Called to implement the built-in functions "oct()" and "hex()".\n Should return a string value.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing). Must return\n an integer (int or long).\n\n New in version 2.5.\n\nobject.__coerce__(self, other)\n\n Called to implement "mixed-mode" numeric arithmetic. Should either\n return a 2-tuple containing *self* and *other* converted to a\n common numeric type, or "None" if conversion is impossible. When\n the common type would be the type of "other", it is sufficient to\n return "None", since the interpreter will also ask the other object\n to attempt a coercion (but sometimes, if the implementation of the\n other type cannot be changed, it is useful to do the conversion to\n the other type here). A return value of "NotImplemented" is\n equivalent to returning "None".\n', 'objects': u'\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity (currently implemented as its address). An\nobject\'s *type* is also unchangeable. [1] An object\'s type determines\nthe operations that the object supports (e.g., "does it have a\nlength?") and also defines the possible values for objects of that\ntype. The "type()" function returns an object\'s type (which is an\nobject itself). The *value* of some objects can change. Objects\nwhose value can change are said to be *mutable*; objects whose value\nis unchangeable once they are created are called *immutable*. (The\nvalue of an immutable container object that contains a reference to a\nmutable object can change when the latter\'s value is changed; however\nthe container is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (ex:\nalways close files).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement provides a convenient way to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n', - 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "<>", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "/", "//", "%" | Multiplication, division, remainder |\n| | [8] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [9] |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "`expressions...`" | display, dictionary display, string |\n| | conversion |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] In Python 2.3 and later releases, a list comprehension "leaks"\n the control variables of each "for" it contains into the\n containing scope. However, this behavior is deprecated, and\n relying on it will not work in Python 3.\n\n[2] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[3] If x is very close to an exact integer multiple of y, it\'s\n possible for "floor(x/y)" to be one larger than "(x-x%y)/y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[4] While comparisons between unicode strings make sense at the\n byte level, they may be counter-intuitive to users. For example,\n the strings "u"\\u00C7"" and "u"\\u0043\\u0327"" compare differently,\n even though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[5] The implementation computes this efficiently, without\n constructing lists or sorting.\n\n[6] Earlier versions of Python used lexicographic comparison of\n the sorted (key, value) lists, but this was very expensive for the\n common case of comparing for equality. An even earlier version of\n Python compared dictionaries by identity only, but this caused\n surprises because people expected to be able to test a dictionary\n for emptiness by comparing it to "{}".\n\n[7] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[8] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[9] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', + 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section Comparisons --- and exponentiation, which groups from\nright to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "<>", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "/", "//", "%" | Multiplication, division, remainder |\n| | [8] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [9] |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "`expressions...`" | display, dictionary display, string |\n| | conversion |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] In Python 2.3 and later releases, a list comprehension "leaks"\n the control variables of each "for" it contains into the\n containing scope. However, this behavior is deprecated, and\n relying on it will not work in Python 3.\n\n[2] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[3] If x is very close to an exact integer multiple of y, it\'s\n possible for "floor(x/y)" to be one larger than "(x-x%y)/y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[4] While comparisons between unicode strings make sense at the\n byte level, they may be counter-intuitive to users. For example,\n the strings "u"\\u00C7"" and "u"\\u0043\\u0327"" compare differently,\n even though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[5] The implementation computes this efficiently, without\n constructing lists or sorting.\n\n[6] Earlier versions of Python used lexicographic comparison of\n the sorted (key, value) lists, but this was very expensive for the\n common case of comparing for equality. An even earlier version of\n Python compared dictionaries by identity only, but this caused\n surprises because people expected to be able to test a dictionary\n for emptiness by comparing it to "{}".\n\n[7] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[8] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[9] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', 'pass': u'\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type. The result type is that of the\narguments after coercion.\n\nWith mixed operand types, the coercion rules for binary arithmetic\noperators apply. For int and long int operands, the result has the\nsame type as the operands (after coercion) unless the second argument\nis negative; in that case, all arguments are converted to float and a\nfloat result is delivered. For example, "10**2" returns "100", but\n"10**-2" returns "0.01". (This last feature was added in Python 2.2.\nIn Python 2.1 and before, if both arguments were of integer types and\nthe second argument was negative, an exception was raised).\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a\n"ValueError".\n', 'print': u'\nThe "print" statement\n*********************\n\n print_stmt ::= "print" ([expression ("," expression)* [","]]\n | ">>" expression [("," expression)+ [","]])\n\n"print" evaluates each expression in turn and writes the resulting\nobject to standard output (see below). If an object is not a string,\nit is first converted to a string using the rules for string\nconversions. The (resulting or original) string is then written. A\nspace is written before each object is (converted and) written, unless\nthe output system believes it is positioned at the beginning of a\nline. This is the case (1) when no characters have yet been written\nto standard output, (2) when the last character written to standard\noutput is a whitespace character except "\' \'", or (3) when the last\nwrite operation on standard output was not a "print" statement. (In\nsome cases it may be functional to write an empty string to standard\noutput for this reason.)\n\nNote: Objects which act like file objects but which are not the\n built-in file objects often do not properly emulate this aspect of\n the file object\'s behavior, so it is best not to rely on this.\n\nA "\'\\n\'" character is written at the end, unless the "print" statement\nends with a comma. This is the only action if the statement contains\njust the keyword "print".\n\nStandard output is defined as the file object named "stdout" in the\nbuilt-in module "sys". If no such object exists, or if it does not\nhave a "write()" method, a "RuntimeError" exception is raised.\n\n"print" also has an extended form, defined by the second portion of\nthe syntax described above. This form is sometimes referred to as\n""print" chevron." In this form, the first expression after the ">>"\nmust evaluate to a "file-like" object, specifically an object that has\na "write()" method as described above. With this extended form, the\nsubsequent expressions are printed to this file object. If the first\nexpression evaluates to "None", then "sys.stdout" is used as the file\nfor output.\n', - 'raise': u'\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["," expression ["," expression]]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "TypeError" exception is raised indicating that\nthis is an error (if running under IDLE, a "Queue.Empty" exception is\nraised instead).\n\nOtherwise, "raise" evaluates the expressions to get three objects,\nusing "None" as the value of omitted expressions. The first two\nobjects are used to determine the *type* and *value* of the exception.\n\nIf the first object is an instance, the type of the exception is the\nclass of the instance, the instance itself is the value, and the\nsecond object must be "None".\n\nIf the first object is a class, it becomes the type of the exception.\nThe second object is used to determine the exception value: If it is\nan instance of the class, the instance becomes the exception value. If\nthe second object is a tuple, it is used as the argument list for the\nclass constructor; if it is "None", an empty argument list is used,\nand any other object is treated as a single argument to the\nconstructor. The instance so created by calling the constructor is\nused as the exception value.\n\nIf a third object is present and not "None", it must be a traceback\nobject (see section *The standard type hierarchy*), and it is\nsubstituted instead of the current location as the place where the\nexception occurred. If the third object is present and not a\ntraceback object or "None", a "TypeError" exception is raised. The\nthree-expression form of "raise" is useful to re-raise an exception\ntransparently in an except clause, but "raise" with no expressions\nshould be preferred if the exception to be re-raised was the most\nrecently active exception in the current scope.\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', + 'raise': u'\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["," expression ["," expression]]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "TypeError" exception is raised indicating that\nthis is an error (if running under IDLE, a "Queue.Empty" exception is\nraised instead).\n\nOtherwise, "raise" evaluates the expressions to get three objects,\nusing "None" as the value of omitted expressions. The first two\nobjects are used to determine the *type* and *value* of the exception.\n\nIf the first object is an instance, the type of the exception is the\nclass of the instance, the instance itself is the value, and the\nsecond object must be "None".\n\nIf the first object is a class, it becomes the type of the exception.\nThe second object is used to determine the exception value: If it is\nan instance of the class, the instance becomes the exception value. If\nthe second object is a tuple, it is used as the argument list for the\nclass constructor; if it is "None", an empty argument list is used,\nand any other object is treated as a single argument to the\nconstructor. The instance so created by calling the constructor is\nused as the exception value.\n\nIf a third object is present and not "None", it must be a traceback\nobject (see section The standard type hierarchy), and it is\nsubstituted instead of the current location as the place where the\nexception occurred. If the third object is present and not a\ntraceback object or "None", a "TypeError" exception is raised. The\nthree-expression form of "raise" is useful to re-raise an exception\ntransparently in an except clause, but "raise" with no expressions\nshould be preferred if the exception to be re-raised was the most\nrecently active exception in the current scope.\n\nAdditional information on exceptions can be found in section\nExceptions, and information about handling exceptions is in section\nThe try statement.\n', 'return': u'\nThe "return" statement\n**********************\n\n return_stmt ::= "return" [expression_list]\n\n"return" may only occur syntactically nested in a function definition,\nnot within a nested class definition.\n\nIf an expression list is present, it is evaluated, else "None" is\nsubstituted.\n\n"return" leaves the current function call with the expression list (or\n"None") as return value.\n\nWhen "return" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nfunction.\n\nIn a generator function, the "return" statement is not allowed to\ninclude an "expression_list". In that context, a bare "return"\nindicates that the generator is done and will cause "StopIteration" to\nbe raised.\n', - 'sequence-types': u'\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. (For backwards compatibility, the method\n"__getslice__()" (see below) can also be defined to handle simple, but\nnot extended slices.) It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "has_key()", "get()",\n"clear()", "setdefault()", "iterkeys()", "itervalues()",\n"iteritems()", "pop()", "popitem()", "copy()", and "update()" behaving\nsimilar to those for Python\'s standard dictionary objects. The\n"UserDict" module provides a "DictMixin" class to help create those\nmethods from a base set of "__getitem__()", "__setitem__()",\n"__delitem__()", and "keys()". Mutable sequences should provide\nmethods "append()", "count()", "index()", "extend()", "insert()",\n"pop()", "remove()", "reverse()" and "sort()", like Python standard\nlist objects. Finally, sequence types should implement addition\n(meaning concatenation) and multiplication (meaning repetition) by\ndefining the methods "__add__()", "__radd__()", "__iadd__()",\n"__mul__()", "__rmul__()" and "__imul__()" described below; they\nshould not define "__coerce__()" or other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should be equivalent of "has_key()"; for sequences,\nit should search through the values. It is further recommended that\nboth mappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "iterkeys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__nonzero__()" method and whose "__len__()"\n method returns zero is considered to be false in a Boolean context.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "iterkeys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\n New in version 2.6.\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n', + 'sequence-types': u'\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. (For backwards compatibility, the method\n"__getslice__()" (see below) can also be defined to handle simple, but\nnot extended slices.) It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "has_key()", "get()",\n"clear()", "setdefault()", "iterkeys()", "itervalues()",\n"iteritems()", "pop()", "popitem()", "copy()", and "update()" behaving\nsimilar to those for Python\'s standard dictionary objects. The\n"UserDict" module provides a "DictMixin" class to help create those\nmethods from a base set of "__getitem__()", "__setitem__()",\n"__delitem__()", and "keys()". Mutable sequences should provide\nmethods "append()", "count()", "index()", "extend()", "insert()",\n"pop()", "remove()", "reverse()" and "sort()", like Python standard\nlist objects. Finally, sequence types should implement addition\n(meaning concatenation) and multiplication (meaning repetition) by\ndefining the methods "__add__()", "__radd__()", "__iadd__()",\n"__mul__()", "__rmul__()" and "__imul__()" described below; they\nshould not define "__coerce__()" or other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should be equivalent of "has_key()"; for sequences,\nit should search through the values. It is further recommended that\nboth mappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "iterkeys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__nonzero__()" method and whose "__len__()"\n method returns zero is considered to be false in a Boolean context.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "iterkeys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see Iterator Types.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\n New in version 2.6.\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see this section in the\n language reference.\n', 'shifting': u'\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept plain or long integers as arguments. The\narguments are converted to a common type. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as division by "pow(2, n)". A\nleft shift by *n* bits is defined as multiplication with "pow(2, n)".\nNegative shift counts raise a "ValueError" exception.\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', - 'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= simple_slicing | extended_slicing\n simple_slicing ::= primary "[" short_slice "]"\n extended_slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice | ellipsis\n proper_slice ::= short_slice | long_slice\n short_slice ::= [lower_bound] ":" [upper_bound]\n long_slice ::= short_slice ":" [stride]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n ellipsis ::= "..."\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice nor ellipses). Similarly, when the slice\nlist has exactly one short slice and no trailing comma, the\ninterpretation as a simple slicing takes priority over that as an\nextended slicing.\n\nThe semantics for a simple slicing are as follows. The primary must\nevaluate to a sequence object. The lower and upper bound expressions,\nif present, must evaluate to plain integers; defaults are zero and the\n"sys.maxint", respectively. If either bound is negative, the\nsequence\'s length is added to it. The slicing now selects all items\nwith index *k* such that "i <= k < j" where *i* and *j* are the\nspecified lower and upper bounds. This may be an empty sequence. It\nis not an error if *i* or *j* lie outside the range of valid indexes\n(such items don\'t exist so they aren\'t selected).\n\nThe semantics for an extended slicing are as follows. The primary\nmust evaluate to a mapping object, and it is indexed with a key that\nis constructed from the slice list, as follows. If the slice list\ncontains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of an ellipsis slice\nitem is the built-in "Ellipsis" object. The conversion of a proper\nslice is a slice object (see section *The standard type hierarchy*)\nwhose "start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n', - 'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\nobject.__methods__\n\n Deprecated since version 2.2: Use the built-in function "dir()" to\n get a list of an object\'s attributes. This attribute is no longer\n available.\n\nobject.__members__\n\n Deprecated since version 2.2: Use the built-in function "dir()" to\n get a list of an object\'s attributes. This attribute is no longer\n available.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nThe following attributes are only supported by *new-style class*es.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each new-style class keeps a list of weak references to its\n immediate subclasses. This method returns a list of all those\n references still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n\n[6] The advantage of leaving the newline on is that returning an\n empty string is then an unambiguous EOF indication. It is also\n possible (in cases where it might matter, for example, if you want\n to make an exact copy of a file while scanning its lines) to tell\n whether the last line of a file ended in a newline or not (yes\n this happens!).\n', - 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "x.__getitem__(i)" for old-style\nclasses and "type(x).__getitem__(x, i)" for new-style classes. Except\nwhere mentioned, attempts to execute an operation raise an exception\nwhen no appropriate method is defined (typically "AttributeError" or\n"TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_traceback" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.exc_traceback" or "sys.last_traceback". Circular references\n which are garbage are detected when the option cycle detector is\n enabled (it\'s on by default), but can only be cleaned up if there\n are no Python-level "__del__()" methods involved. Refer to the\n documentation for the "gc" module for more information about how\n "__del__()" methods are handled by the cycle detector,\n particularly the description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\n See also the *-R* command-line option.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function and by string conversions\n (reverse quotes) to compute the "official" string representation of\n an object. If at all possible, this should look like a valid\n Python expression that could be used to recreate an object with the\n same value (given an appropriate environment). If this is not\n possible, a string of the form "<...some useful description...>"\n should be returned. The return value must be a string object. If a\n class defines "__repr__()" but not "__str__()", then "__repr__()"\n is also used when an "informal" string representation of instances\n of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by the "str()" built-in function and by the "print"\n statement to compute the "informal" string representation of an\n object. This differs from "__repr__()" in that it does not have to\n be a valid Python expression: a more convenient or concise\n representation may be used instead. The return value must be a\n string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n New in version 2.1.\n\n These are the so-called "rich comparison" methods, and are called\n for comparison operators in preference to "__cmp__()" below. The\n correspondence between operator symbols and method names is as\n follows: "xy" call "x.__ne__(y)",\n "x>y" calls "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__cmp__(self, other)\n\n Called by comparison operations if rich comparison (see above) is\n not defined. Should return a negative integer if "self < other",\n zero if "self == other", a positive integer if "self > other". If\n no "__cmp__()", "__eq__()" or "__ne__()" operation is defined,\n class instances are compared by object identity ("address"). See\n also the description of "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys. (Note: the\n restriction that exceptions are not propagated by "__cmp__()" has\n been removed since Python 1.5.)\n\nobject.__rcmp__(self, other)\n\n Changed in version 2.1: No longer supported.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n If a class does not define a "__cmp__()" or "__eq__()" method it\n should not define a "__hash__()" operation either; if it defines\n "__cmp__()" or "__eq__()" but not "__hash__()", its instances will\n not be usable in hashed collections. If a class defines mutable\n objects and implements a "__cmp__()" or "__eq__()" method, it\n should not implement "__hash__()", since hashable collection\n implementations require that a object\'s hash value is immutable (if\n the object\'s hash value changes, it will be in the wrong hash\n bucket).\n\n User-defined classes have "__cmp__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns a result derived from\n "id(x)".\n\n Classes which inherit a "__hash__()" method from a parent class but\n change the meaning of "__cmp__()" or "__eq__()" such that the hash\n value returned is no longer appropriate (e.g. by switching to a\n value-based concept of equality instead of the default identity\n based equality) can explicitly flag themselves as being unhashable\n by setting "__hash__ = None" in the class definition. Doing so\n means that not only will instances of the class raise an\n appropriate "TypeError" when a program attempts to retrieve their\n hash value, but they will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)"\n (unlike classes which define their own "__hash__()" to explicitly\n raise "TypeError").\n\n Changed in version 2.5: "__hash__()" may now also return a long\n integer object; the 32-bit integer is then derived from the hash of\n that object.\n\n Changed in version 2.6: "__hash__" may now be set to "None" to\n explicitly flag instances of a class as unhashable.\n\nobject.__nonzero__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True", or their integer\n equivalents "0" or "1". When this method is not defined,\n "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__nonzero__()", all its instances are\n considered true.\n\nobject.__unicode__(self)\n\n Called to implement "unicode()" built-in; should return a Unicode\n object. When this method is not defined, string conversion is\n attempted, and the result of string conversion is converted to\n Unicode using the system default encoding.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control in new-style classes.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should not simply execute "self.name = value" --- this would cause\n a recursive call to itself. Instead, it should insert the value in\n the dictionary of instance attributes, e.g., "self.__dict__[name] =\n value". For new-style classes, rather than accessing the instance\n dictionary, it should call the base class method with the same\n name, for example, "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\n\nMore attribute access for new-style classes\n-------------------------------------------\n\nThe following methods only apply to new-style classes.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup for new-style\n classes*.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called. Note that descriptors are only invoked for new\nstyle objects or classes (ones that subclass "object()" or "type()").\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to a new-style object instance, "a.x" is transformed\n into the call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a new-style class, "A.x" is transformed into the\n call: "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of both old and new-style classes have a\ndictionary for attribute storage. This wastes space for objects\nhaving very few instance variables. The space consumption can become\nacute when creating large numbers of instances.\n\nThe default can be overridden by defining *__slots__* in a new-style\nclass definition. The *__slots__* declaration takes a sequence of\ninstance variables and reserves just enough space in each instance to\nhold a value for each variable. Space is saved because *__dict__* is\nnot created for each instance.\n\n__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n new-style class, *__slots__* reserves space for the declared\n variables and prevents the automatic creation of *__dict__* and\n *__weakref__* for each instance.\n\n New in version 2.2.\n\nNotes on using *__slots__*\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__dict__\'" to the\n *__slots__* declaration would not enable the assignment of new\n attributes not specifically listed in the sequence of instance\n variable names.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__weakref__\'" to the\n *__slots__* declaration would not enable support for weak\n references.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "long", "str" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n Changed in version 2.6: Previously, *__class__* assignment raised an\n error if either new or old class had *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, new-style classes are constructed using "type()". A class\ndefinition is read into a separate namespace and the value of class\nname is bound to the result of "type(name, bases, dict)".\n\nWhen the class definition is read, if *__metaclass__* is defined then\nthe callable assigned to it will be called instead of "type()". This\nallows classes or functions to be written which monitor or alter the\nclass creation process:\n\n* Modifying the class dictionary prior to the class being created.\n\n* Returning an instance of another class -- essentially performing\n the role of a factory function.\n\nThese steps will have to be performed in the metaclass\'s "__new__()"\nmethod -- "type.__new__()" can then be called from this method to\ncreate a class with different properties. This example adds a new\nelement to the class dictionary before creating the class:\n\n class metacls(type):\n def __new__(mcs, name, bases, dict):\n dict[\'foo\'] = \'metacls was here\'\n return type.__new__(mcs, name, bases, dict)\n\nYou can of course also override other class methods (or add new\nmethods); for example defining a custom "__call__()" method in the\nmetaclass allows custom behavior when the class is called, e.g. not\nalways creating a new instance.\n\n__metaclass__\n\n This variable can be any callable accepting arguments for "name",\n "bases", and "dict". Upon class creation, the callable is used\n instead of the built-in "type()".\n\n New in version 2.2.\n\nThe appropriate metaclass is determined by the following precedence\nrules:\n\n* If "dict[\'__metaclass__\']" exists, it is used.\n\n* Otherwise, if there is at least one base class, its metaclass is\n used (this looks for a *__class__* attribute first and if not found,\n uses its type).\n\n* Otherwise, if a global variable named __metaclass__ exists, it is\n used.\n\n* Otherwise, the old-style, classic metaclass (types.ClassType) is\n used.\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored including logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\n\nCustomizing instance and subclass checks\n========================================\n\nNew in version 2.6.\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. (For backwards compatibility, the method\n"__getslice__()" (see below) can also be defined to handle simple, but\nnot extended slices.) It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "has_key()", "get()",\n"clear()", "setdefault()", "iterkeys()", "itervalues()",\n"iteritems()", "pop()", "popitem()", "copy()", and "update()" behaving\nsimilar to those for Python\'s standard dictionary objects. The\n"UserDict" module provides a "DictMixin" class to help create those\nmethods from a base set of "__getitem__()", "__setitem__()",\n"__delitem__()", and "keys()". Mutable sequences should provide\nmethods "append()", "count()", "index()", "extend()", "insert()",\n"pop()", "remove()", "reverse()" and "sort()", like Python standard\nlist objects. Finally, sequence types should implement addition\n(meaning concatenation) and multiplication (meaning repetition) by\ndefining the methods "__add__()", "__radd__()", "__iadd__()",\n"__mul__()", "__rmul__()" and "__imul__()" described below; they\nshould not define "__coerce__()" or other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should be equivalent of "has_key()"; for sequences,\nit should search through the values. It is further recommended that\nboth mappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "iterkeys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__nonzero__()" method and whose "__len__()"\n method returns zero is considered to be false in a Boolean context.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "iterkeys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\n New in version 2.6.\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nAdditional methods for emulation of sequence types\n==================================================\n\nThe following optional methods can be defined to further emulate\nsequence objects. Immutable sequences methods should at most only\ndefine "__getslice__()"; mutable sequences might define all three\nmethods.\n\nobject.__getslice__(self, i, j)\n\n Deprecated since version 2.0: Support slice objects as parameters\n to the "__getitem__()" method. (However, built-in types in CPython\n currently still implement "__getslice__()". Therefore, you have to\n override it in derived classes when implementing slicing.)\n\n Called to implement evaluation of "self[i:j]". The returned object\n should be of the same type as *self*. Note that missing *i* or *j*\n in the slice expression are replaced by zero or "sys.maxint",\n respectively. If negative indexes are used in the slice, the\n length of the sequence is added to that index. If the instance does\n not implement the "__len__()" method, an "AttributeError" is\n raised. No guarantee is made that indexes adjusted this way are not\n still negative. Indexes which are greater than the length of the\n sequence are not modified. If no "__getslice__()" is found, a slice\n object is created instead, and passed to "__getitem__()" instead.\n\nobject.__setslice__(self, i, j, sequence)\n\n Called to implement assignment to "self[i:j]". Same notes for *i*\n and *j* as for "__getslice__()".\n\n This method is deprecated. If no "__setslice__()" is found, or for\n extended slicing of the form "self[i:j:k]", a slice object is\n created, and passed to "__setitem__()", instead of "__setslice__()"\n being called.\n\nobject.__delslice__(self, i, j)\n\n Called to implement deletion of "self[i:j]". Same notes for *i* and\n *j* as for "__getslice__()". This method is deprecated. If no\n "__delslice__()" is found, or for extended slicing of the form\n "self[i:j:k]", a slice object is created, and passed to\n "__delitem__()", instead of "__delslice__()" being called.\n\nNotice that these methods are only invoked when a single slice with a\nsingle colon is used, and the slice method is available. For slice\noperations involving extended slice notation, or in absence of the\nslice methods, "__getitem__()", "__setitem__()" or "__delitem__()" is\ncalled with a slice object as argument.\n\nThe following example demonstrate how to make your program or module\ncompatible with earlier versions of Python (assuming that methods\n"__getitem__()", "__setitem__()" and "__delitem__()" support slice\nobjects as arguments):\n\n class MyClass:\n ...\n def __getitem__(self, index):\n ...\n def __setitem__(self, index, value):\n ...\n def __delitem__(self, index):\n ...\n\n if sys.version_info < (2, 0):\n # They won\'t be defined if version is at least 2.0 final\n\n def __getslice__(self, i, j):\n return self[max(0, i):max(0, j):]\n def __setslice__(self, i, j, seq):\n self[max(0, i):max(0, j):] = seq\n def __delslice__(self, i, j):\n del self[max(0, i):max(0, j):]\n ...\n\nNote the calls to "max()"; these are necessary because of the handling\nof negative indices before the "__*slice__()" methods are called.\nWhen negative indexes are used, the "__*item__()" methods receive them\nas provided, but the "__*slice__()" methods get a "cooked" form of the\nindex values. For each negative index value, the length of the\nsequence is added to the index before calling the method (which may\nstill result in a negative index); this is the customary handling of\nnegative indexes by the built-in sequence types, and the "__*item__()"\nmethods are expected to do this as well. However, since they should\nalready be doing that, negative indexes cannot be passed in; they must\nbe constrained to the bounds of the sequence before being passed to\nthe "__*item__()" methods. Calling "max(0, i)" conveniently returns\nthe proper value.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "//", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()" (described\n below). Note that "__pow__()" should be defined to accept an\n optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__div__(self, other)\nobject.__truediv__(self, other)\n\n The division operator ("/") is implemented by these methods. The\n "__truediv__()" method is used when "__future__.division" is in\n effect, otherwise "__div__()" is used. If only one of these two\n methods is defined, the object will not support division in the\n alternate context; "TypeError" will be raised instead.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rdiv__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__idiv__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__long__(self)\nobject.__float__(self)\n\n Called to implement the built-in functions "complex()", "int()",\n "long()", and "float()". Should return a value of the appropriate\n type.\n\nobject.__oct__(self)\nobject.__hex__(self)\n\n Called to implement the built-in functions "oct()" and "hex()".\n Should return a string value.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing). Must return\n an integer (int or long).\n\n New in version 2.5.\n\nobject.__coerce__(self, other)\n\n Called to implement "mixed-mode" numeric arithmetic. Should either\n return a 2-tuple containing *self* and *other* converted to a\n common numeric type, or "None" if conversion is impossible. When\n the common type would be the type of "other", it is sufficient to\n return "None", since the interpreter will also ask the other object\n to attempt a coercion (but sometimes, if the implementation of the\n other type cannot be changed, it is useful to do the conversion to\n the other type here). A return value of "NotImplemented" is\n equivalent to returning "None".\n\n\nCoercion rules\n==============\n\nThis section used to document the rules for coercion. As the language\nhas evolved, the coercion rules have become hard to document\nprecisely; documenting what one version of one particular\nimplementation does is undesirable. Instead, here are some informal\nguidelines regarding coercion. In Python 3, coercion will not be\nsupported.\n\n* If the left operand of a % operator is a string or Unicode object,\n no coercion takes place and the string formatting operation is\n invoked instead.\n\n* It is no longer recommended to define a coercion operation. Mixed-\n mode operations on types that don\'t define coercion pass the\n original arguments to the operation.\n\n* New-style classes (those derived from "object") never invoke the\n "__coerce__()" method in response to a binary operator; the only\n time "__coerce__()" is invoked is when the built-in function\n "coerce()" is called.\n\n* For most intents and purposes, an operator that returns\n "NotImplemented" is treated the same as one that is not implemented\n at all.\n\n* Below, "__op__()" and "__rop__()" are used to signify the generic\n method names corresponding to an operator; "__iop__()" is used for\n the corresponding in-place operator. For example, for the operator\n \'"+"\', "__add__()" and "__radd__()" are used for the left and right\n variant of the binary operator, and "__iadd__()" for the in-place\n variant.\n\n* For objects *x* and *y*, first "x.__op__(y)" is tried. If this is\n not implemented or returns "NotImplemented", "y.__rop__(x)" is\n tried. If this is also not implemented or returns "NotImplemented",\n a "TypeError" exception is raised. But see the following exception:\n\n* Exception to the previous item: if the left operand is an instance\n of a built-in type or a new-style class, and the right operand is an\n instance of a proper subclass of that type or class and overrides\n the base\'s "__rop__()" method, the right operand\'s "__rop__()"\n method is tried *before* the left operand\'s "__op__()" method.\n\n This is done so that a subclass can completely override binary\n operators. Otherwise, the left operand\'s "__op__()" method would\n always accept the right operand: when an instance of a given class\n is expected, an instance of a subclass of that class is always\n acceptable.\n\n* When either operand type defines a coercion, this coercion is\n called before that type\'s "__op__()" or "__rop__()" method is\n called, but no sooner. If the coercion returns an object of a\n different type for the operand whose coercion is invoked, part of\n the process is redone using the new object.\n\n* When an in-place operator (like \'"+="\') is used, if the left\n operand implements "__iop__()", it is invoked without any coercion.\n When the operation falls back to "__op__()" and/or "__rop__()", the\n normal coercion rules apply.\n\n* In "x + y", if *x* is a sequence that implements sequence\n concatenation, sequence concatenation is invoked.\n\n* In "x * y", if one operand is a sequence that implements sequence\n repetition, and the other is an integer ("int" or "long"), sequence\n repetition is invoked.\n\n* Rich comparisons (implemented by methods "__eq__()" and so on)\n never use coercion. Three-way comparison (implemented by\n "__cmp__()") does use coercion under the same conditions as other\n binary operations use it.\n\n* In the current implementation, the built-in numeric types "int",\n "long", "float", and "complex" do not use coercion. All these types\n implement a "__coerce__()" method, for use by the built-in\n "coerce()" function.\n\n Changed in version 2.7: The complex type no longer makes implicit\n calls to the "__coerce__()" method for mixed-type binary arithmetic\n operations.\n\n\nWith Statement Context Managers\n===============================\n\nNew in version 2.5.\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup for old-style classes\n===========================================\n\nFor old-style classes, special methods are always looked up in exactly\nthe same way as any other method or attribute. This is the case\nregardless of whether the method is being looked up explicitly as in\n"x.__getitem__(i)" or implicitly as in "x[i]".\n\nThis behaviour means that special methods may exhibit different\nbehaviour for different instances of a single old-style class if the\nappropriate special attributes are set differently:\n\n >>> class C:\n ... pass\n ...\n >>> c1 = C()\n >>> c2 = C()\n >>> c1.__len__ = lambda: 5\n >>> c2.__len__ = lambda: 9\n >>> len(c1)\n 5\n >>> len(c2)\n 9\n\n\nSpecial method lookup for new-style classes\n===========================================\n\nFor new-style classes, implicit invocations of special methods are\nonly guaranteed to work correctly if defined on an object\'s type, not\nin the object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception (unlike the equivalent example\nwith old-style classes):\n\n >>> class C(object):\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print "Metaclass getattribute invoked"\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object):\n ... __metaclass__ = Meta\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print "Class getattribute invoked"\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', - 'string-methods': u'\nString Methods\n**************\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n"bytearray" objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange* section. To output formatted strings use\ntemplate strings or the "%" operator described in the *String\nFormatting Operations* section. Also, see the "re" module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n "\'strict\'", meaning that encoding errors raise "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'" and any other\n name registered via "codecs.register_error()", see section *Codec\n Base Classes*.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n "\'strict\'", meaning that encoding errors raise a "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'",\n "\'xmlcharrefreplace\'", "\'backslashreplace\'" and any other name\n registered via "codecs.register_error()", see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for "\'xmlcharrefreplace\'" and\n "\'backslashreplace\'" and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the "%" formatting described in *String\n Formatting Operations* in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the "maketrans()" helper function in the "string"\n module to create a translation table. For string objects, set the\n *table* argument to "None" for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a "None" *table* argument.\n\n For Unicode objects, the "translate()" method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or "None". Unmapped characters\n are left untouched. Characters mapped to "None" are deleted. Note,\n a more flexible approach is to create a custom character mapping\n codec using the "codecs" module (see "encodings.cp1251" for an\n example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return "True" if there are only numeric characters in S, "False"\n otherwise. Numeric characters include digit characters, and all\n characters that have the Unicode numeric value property, e.g.\n U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return "True" if there are only decimal characters in S, "False"\n otherwise. Decimal characters include digit characters, and all\n characters that can be used to form decimal-radix numbers, e.g.\n U+0660, ARABIC-INDIC DIGIT ZERO.\n', - 'strings': u'\nString literals\n***************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"\n | "b" | "B" | "br" | "Br" | "bR" | "BR"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'"\n | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | escapeseq\n longstringitem ::= longstringchar | escapeseq\n shortstringchar ::= \n longstringchar ::= \n escapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" and the rest of\nthe string literal. The source character set is defined by the\nencoding declaration; it is ASCII if no encoding declaration is given\nin the source file; see section *Encoding declarations*.\n\nIn plain English: String literals can be enclosed in matching single\nquotes ("\'") or double quotes ("""). They can also be enclosed in\nmatching groups of three single or double quotes (these are generally\nreferred to as *triple-quoted strings*). The backslash ("\\")\ncharacter is used to escape characters that otherwise have a special\nmeaning, such as newline, backslash itself, or the quote character.\nString literals may optionally be prefixed with a letter "\'r\'" or\n"\'R\'"; such strings are called *raw strings* and use different rules\nfor interpreting backslash escape sequences. A prefix of "\'u\'" or\n"\'U\'" makes the string a Unicode string. Unicode strings use the\nUnicode character set as defined by the Unicode Consortium and ISO\n10646. Some additional escape sequences, described below, are\navailable in Unicode strings. A prefix of "\'b\'" or "\'B\'" is ignored in\nPython 2; it indicates that the literal should become a bytes literal\nin Python 3 (e.g. when code is automatically converted with 2to3). A\n"\'u\'" or "\'b\'" prefix may be followed by an "\'r\'" prefix.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\N{name}" | Character named *name* in the | |\n| | Unicode database (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (1) |\n| | *xxxx* (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (2) |\n| | *xxxxxxxx* (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (3,5) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (4,5) |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence.\n\n2. Any Unicode character can be encoded this way, but characters\n outside the Basic Multilingual Plane (BMP) will be encoded using a\n surrogate pair if Python is compiled to use 16-bit code units (the\n default).\n\n3. As in Standard C, up to three octal digits are accepted.\n\n4. Unlike in Standard C, exactly two hex digits are required.\n\n5. In a string literal, hexadecimal and octal escapes denote the\n byte with the given value; it is not necessary that the byte\n encodes a character in the source character set. In a Unicode\n literal, these escapes denote a Unicode character with the given\n value.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences marked as "(Unicode only)"\nin the table above fall into the category of unrecognized escapes for\nnon-Unicode string literals.\n\nWhen an "\'r\'" or "\'R\'" prefix is present, a character following a\nbackslash is included in the string without change, and *all\nbackslashes are left in the string*. For example, the string literal\n"r"\\n"" consists of two characters: a backslash and a lowercase "\'n\'".\nString quotes can be escaped with a backslash, but the backslash\nremains in the string; for example, "r"\\""" is a valid string literal\nconsisting of two characters: a backslash and a double quote; "r"\\""\nis not a valid string literal (even a raw string cannot end in an odd\nnumber of backslashes). Specifically, *a raw string cannot end in a\nsingle backslash* (since the backslash would escape the following\nquote character). Note also that a single backslash followed by a\nnewline is interpreted as those two characters as part of the string,\n*not* as a line continuation.\n\nWhen an "\'r\'" or "\'R\'" prefix is used in conjunction with a "\'u\'" or\n"\'U\'" prefix, then the "\\uXXXX" and "\\UXXXXXXXX" escape sequences are\nprocessed while *all other backslashes are left in the string*. For\nexample, the string literal "ur"\\u0062\\n"" consists of three Unicode\ncharacters: \'LATIN SMALL LETTER B\', \'REVERSE SOLIDUS\', and \'LATIN\nSMALL LETTER N\'. Backslashes can be escaped with a preceding\nbackslash; however, both remain in the string. As a result, "\\uXXXX"\nescape sequences are only recognized when there are an odd number of\nbackslashes.\n', + 'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= simple_slicing | extended_slicing\n simple_slicing ::= primary "[" short_slice "]"\n extended_slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice | ellipsis\n proper_slice ::= short_slice | long_slice\n short_slice ::= [lower_bound] ":" [upper_bound]\n long_slice ::= short_slice ":" [stride]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n ellipsis ::= "..."\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice nor ellipses). Similarly, when the slice\nlist has exactly one short slice and no trailing comma, the\ninterpretation as a simple slicing takes priority over that as an\nextended slicing.\n\nThe semantics for a simple slicing are as follows. The primary must\nevaluate to a sequence object. The lower and upper bound expressions,\nif present, must evaluate to plain integers; defaults are zero and the\n"sys.maxint", respectively. If either bound is negative, the\nsequence\'s length is added to it. The slicing now selects all items\nwith index *k* such that "i <= k < j" where *i* and *j* are the\nspecified lower and upper bounds. This may be an empty sequence. It\nis not an error if *i* or *j* lie outside the range of valid indexes\n(such items don\'t exist so they aren\'t selected).\n\nThe semantics for an extended slicing are as follows. The primary\nmust evaluate to a mapping object, and it is indexed with a key that\nis constructed from the slice list, as follows. If the slice list\ncontains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of an ellipsis slice\nitem is the built-in "Ellipsis" object. The conversion of a proper\nslice is a slice object (see section The standard type hierarchy)\nwhose "start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n', + 'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\nobject.__methods__\n\n Deprecated since version 2.2: Use the built-in function "dir()" to\n get a list of an object\'s attributes. This attribute is no longer\n available.\n\nobject.__members__\n\n Deprecated since version 2.2: Use the built-in function "dir()" to\n get a list of an object\'s attributes. This attribute is no longer\n available.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nThe following attributes are only supported by *new-style class*es.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each new-style class keeps a list of weak references to its\n immediate subclasses. This method returns a list of all those\n references still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (Basic customization).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n\n[6] The advantage of leaving the newline on is that returning an\n empty string is then an unambiguous EOF indication. It is also\n possible (in cases where it might matter, for example, if you want\n to make an exact copy of a file while scanning its lines) to tell\n whether the last line of a file ended in a newline or not (yes\n this happens!).\n', + 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "x.__getitem__(i)" for old-style\nclasses and "type(x).__getitem__(x, i)" for new-style classes. Except\nwhere mentioned, attempts to execute an operation raise an exception\nwhen no appropriate method is defined (typically "AttributeError" or\n"TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_traceback" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.exc_traceback" or "sys.last_traceback". Circular references\n which are garbage are detected when the option cycle detector is\n enabled (it\'s on by default), but can only be cleaned up if there\n are no Python-level "__del__()" methods involved. Refer to the\n documentation for the "gc" module for more information about how\n "__del__()" methods are handled by the cycle detector,\n particularly the description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\n See also the "-R" command-line option.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function and by string conversions\n (reverse quotes) to compute the "official" string representation of\n an object. If at all possible, this should look like a valid\n Python expression that could be used to recreate an object with the\n same value (given an appropriate environment). If this is not\n possible, a string of the form "<...some useful description...>"\n should be returned. The return value must be a string object. If a\n class defines "__repr__()" but not "__str__()", then "__repr__()"\n is also used when an "informal" string representation of instances\n of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by the "str()" built-in function and by the "print"\n statement to compute the "informal" string representation of an\n object. This differs from "__repr__()" in that it does not have to\n be a valid Python expression: a more convenient or concise\n representation may be used instead. The return value must be a\n string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n New in version 2.1.\n\n These are the so-called "rich comparison" methods, and are called\n for comparison operators in preference to "__cmp__()" below. The\n correspondence between operator symbols and method names is as\n follows: "xy" call "x.__ne__(y)",\n "x>y" calls "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__cmp__(self, other)\n\n Called by comparison operations if rich comparison (see above) is\n not defined. Should return a negative integer if "self < other",\n zero if "self == other", a positive integer if "self > other". If\n no "__cmp__()", "__eq__()" or "__ne__()" operation is defined,\n class instances are compared by object identity ("address"). See\n also the description of "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys. (Note: the\n restriction that exceptions are not propagated by "__cmp__()" has\n been removed since Python 1.5.)\n\nobject.__rcmp__(self, other)\n\n Changed in version 2.1: No longer supported.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n If a class does not define a "__cmp__()" or "__eq__()" method it\n should not define a "__hash__()" operation either; if it defines\n "__cmp__()" or "__eq__()" but not "__hash__()", its instances will\n not be usable in hashed collections. If a class defines mutable\n objects and implements a "__cmp__()" or "__eq__()" method, it\n should not implement "__hash__()", since hashable collection\n implementations require that a object\'s hash value is immutable (if\n the object\'s hash value changes, it will be in the wrong hash\n bucket).\n\n User-defined classes have "__cmp__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns a result derived from\n "id(x)".\n\n Classes which inherit a "__hash__()" method from a parent class but\n change the meaning of "__cmp__()" or "__eq__()" such that the hash\n value returned is no longer appropriate (e.g. by switching to a\n value-based concept of equality instead of the default identity\n based equality) can explicitly flag themselves as being unhashable\n by setting "__hash__ = None" in the class definition. Doing so\n means that not only will instances of the class raise an\n appropriate "TypeError" when a program attempts to retrieve their\n hash value, but they will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)"\n (unlike classes which define their own "__hash__()" to explicitly\n raise "TypeError").\n\n Changed in version 2.5: "__hash__()" may now also return a long\n integer object; the 32-bit integer is then derived from the hash of\n that object.\n\n Changed in version 2.6: "__hash__" may now be set to "None" to\n explicitly flag instances of a class as unhashable.\n\nobject.__nonzero__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True", or their integer\n equivalents "0" or "1". When this method is not defined,\n "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__nonzero__()", all its instances are\n considered true.\n\nobject.__unicode__(self)\n\n Called to implement "unicode()" built-in; should return a Unicode\n object. When this method is not defined, string conversion is\n attempted, and the result of string conversion is converted to\n Unicode using the system default encoding.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control in new-style classes.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should not simply execute "self.name = value" --- this would cause\n a recursive call to itself. Instead, it should insert the value in\n the dictionary of instance attributes, e.g., "self.__dict__[name] =\n value". For new-style classes, rather than accessing the instance\n dictionary, it should call the base class method with the same\n name, for example, "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\n\nMore attribute access for new-style classes\n-------------------------------------------\n\nThe following methods only apply to new-style classes.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See Special method lookup for new-style\n classes.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called. Note that descriptors are only invoked for new\nstyle objects or classes (ones that subclass "object()" or "type()").\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to a new-style object instance, "a.x" is transformed\n into the call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a new-style class, "A.x" is transformed into the\n call: "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of both old and new-style classes have a\ndictionary for attribute storage. This wastes space for objects\nhaving very few instance variables. The space consumption can become\nacute when creating large numbers of instances.\n\nThe default can be overridden by defining *__slots__* in a new-style\nclass definition. The *__slots__* declaration takes a sequence of\ninstance variables and reserves just enough space in each instance to\nhold a value for each variable. Space is saved because *__dict__* is\nnot created for each instance.\n\n__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n new-style class, *__slots__* reserves space for the declared\n variables and prevents the automatic creation of *__dict__* and\n *__weakref__* for each instance.\n\n New in version 2.2.\n\nNotes on using *__slots__*\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__dict__\'" to the\n *__slots__* declaration would not enable the assignment of new\n attributes not specifically listed in the sequence of instance\n variable names.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n Changed in version 2.3: Previously, adding "\'__weakref__\'" to the\n *__slots__* declaration would not enable support for weak\n references.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (Implementing Descriptors) for each variable name. As a\n result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "long", "str" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n Changed in version 2.6: Previously, *__class__* assignment raised an\n error if either new or old class had *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, new-style classes are constructed using "type()". A class\ndefinition is read into a separate namespace and the value of class\nname is bound to the result of "type(name, bases, dict)".\n\nWhen the class definition is read, if *__metaclass__* is defined then\nthe callable assigned to it will be called instead of "type()". This\nallows classes or functions to be written which monitor or alter the\nclass creation process:\n\n* Modifying the class dictionary prior to the class being created.\n\n* Returning an instance of another class -- essentially performing\n the role of a factory function.\n\nThese steps will have to be performed in the metaclass\'s "__new__()"\nmethod -- "type.__new__()" can then be called from this method to\ncreate a class with different properties. This example adds a new\nelement to the class dictionary before creating the class:\n\n class metacls(type):\n def __new__(mcs, name, bases, dict):\n dict[\'foo\'] = \'metacls was here\'\n return type.__new__(mcs, name, bases, dict)\n\nYou can of course also override other class methods (or add new\nmethods); for example defining a custom "__call__()" method in the\nmetaclass allows custom behavior when the class is called, e.g. not\nalways creating a new instance.\n\n__metaclass__\n\n This variable can be any callable accepting arguments for "name",\n "bases", and "dict". Upon class creation, the callable is used\n instead of the built-in "type()".\n\n New in version 2.2.\n\nThe appropriate metaclass is determined by the following precedence\nrules:\n\n* If "dict[\'__metaclass__\']" exists, it is used.\n\n* Otherwise, if there is at least one base class, its metaclass is\n used (this looks for a *__class__* attribute first and if not found,\n uses its type).\n\n* Otherwise, if a global variable named __metaclass__ exists, it is\n used.\n\n* Otherwise, the old-style, classic metaclass (types.ClassType) is\n used.\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored including logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\n\nCustomizing instance and subclass checks\n========================================\n\nNew in version 2.6.\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. (For backwards compatibility, the method\n"__getslice__()" (see below) can also be defined to handle simple, but\nnot extended slices.) It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "has_key()", "get()",\n"clear()", "setdefault()", "iterkeys()", "itervalues()",\n"iteritems()", "pop()", "popitem()", "copy()", and "update()" behaving\nsimilar to those for Python\'s standard dictionary objects. The\n"UserDict" module provides a "DictMixin" class to help create those\nmethods from a base set of "__getitem__()", "__setitem__()",\n"__delitem__()", and "keys()". Mutable sequences should provide\nmethods "append()", "count()", "index()", "extend()", "insert()",\n"pop()", "remove()", "reverse()" and "sort()", like Python standard\nlist objects. Finally, sequence types should implement addition\n(meaning concatenation) and multiplication (meaning repetition) by\ndefining the methods "__add__()", "__radd__()", "__iadd__()",\n"__mul__()", "__rmul__()" and "__imul__()" described below; they\nshould not define "__coerce__()" or other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should be equivalent of "has_key()"; for sequences,\nit should search through the values. It is further recommended that\nboth mappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "iterkeys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__nonzero__()" method and whose "__len__()"\n method returns zero is considered to be false in a Boolean context.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "iterkeys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see Iterator Types.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\n New in version 2.6.\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see this section in the\n language reference.\n\n\nAdditional methods for emulation of sequence types\n==================================================\n\nThe following optional methods can be defined to further emulate\nsequence objects. Immutable sequences methods should at most only\ndefine "__getslice__()"; mutable sequences might define all three\nmethods.\n\nobject.__getslice__(self, i, j)\n\n Deprecated since version 2.0: Support slice objects as parameters\n to the "__getitem__()" method. (However, built-in types in CPython\n currently still implement "__getslice__()". Therefore, you have to\n override it in derived classes when implementing slicing.)\n\n Called to implement evaluation of "self[i:j]". The returned object\n should be of the same type as *self*. Note that missing *i* or *j*\n in the slice expression are replaced by zero or "sys.maxsize",\n respectively. If negative indexes are used in the slice, the\n length of the sequence is added to that index. If the instance does\n not implement the "__len__()" method, an "AttributeError" is\n raised. No guarantee is made that indexes adjusted this way are not\n still negative. Indexes which are greater than the length of the\n sequence are not modified. If no "__getslice__()" is found, a slice\n object is created instead, and passed to "__getitem__()" instead.\n\nobject.__setslice__(self, i, j, sequence)\n\n Called to implement assignment to "self[i:j]". Same notes for *i*\n and *j* as for "__getslice__()".\n\n This method is deprecated. If no "__setslice__()" is found, or for\n extended slicing of the form "self[i:j:k]", a slice object is\n created, and passed to "__setitem__()", instead of "__setslice__()"\n being called.\n\nobject.__delslice__(self, i, j)\n\n Called to implement deletion of "self[i:j]". Same notes for *i* and\n *j* as for "__getslice__()". This method is deprecated. If no\n "__delslice__()" is found, or for extended slicing of the form\n "self[i:j:k]", a slice object is created, and passed to\n "__delitem__()", instead of "__delslice__()" being called.\n\nNotice that these methods are only invoked when a single slice with a\nsingle colon is used, and the slice method is available. For slice\noperations involving extended slice notation, or in absence of the\nslice methods, "__getitem__()", "__setitem__()" or "__delitem__()" is\ncalled with a slice object as argument.\n\nThe following example demonstrate how to make your program or module\ncompatible with earlier versions of Python (assuming that methods\n"__getitem__()", "__setitem__()" and "__delitem__()" support slice\nobjects as arguments):\n\n class MyClass:\n ...\n def __getitem__(self, index):\n ...\n def __setitem__(self, index, value):\n ...\n def __delitem__(self, index):\n ...\n\n if sys.version_info < (2, 0):\n # They won\'t be defined if version is at least 2.0 final\n\n def __getslice__(self, i, j):\n return self[max(0, i):max(0, j):]\n def __setslice__(self, i, j, seq):\n self[max(0, i):max(0, j):] = seq\n def __delslice__(self, i, j):\n del self[max(0, i):max(0, j):]\n ...\n\nNote the calls to "max()"; these are necessary because of the handling\nof negative indices before the "__*slice__()" methods are called.\nWhen negative indexes are used, the "__*item__()" methods receive them\nas provided, but the "__*slice__()" methods get a "cooked" form of the\nindex values. For each negative index value, the length of the\nsequence is added to the index before calling the method (which may\nstill result in a negative index); this is the customary handling of\nnegative indexes by the built-in sequence types, and the "__*item__()"\nmethods are expected to do this as well. However, since they should\nalready be doing that, negative indexes cannot be passed in; they must\nbe constrained to the bounds of the sequence before being passed to\nthe "__*item__()" methods. Calling "max(0, i)" conveniently returns\nthe proper value.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "//", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()" (described\n below). Note that "__pow__()" should be defined to accept an\n optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__div__(self, other)\nobject.__truediv__(self, other)\n\n The division operator ("/") is implemented by these methods. The\n "__truediv__()" method is used when "__future__.division" is in\n effect, otherwise "__div__()" is used. If only one of these two\n methods is defined, the object will not support division in the\n alternate context; "TypeError" will be raised instead.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rdiv__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "%", "divmod()", "pow()", "**",\n "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__idiv__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__long__(self)\nobject.__float__(self)\n\n Called to implement the built-in functions "complex()", "int()",\n "long()", and "float()". Should return a value of the appropriate\n type.\n\nobject.__oct__(self)\nobject.__hex__(self)\n\n Called to implement the built-in functions "oct()" and "hex()".\n Should return a string value.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing). Must return\n an integer (int or long).\n\n New in version 2.5.\n\nobject.__coerce__(self, other)\n\n Called to implement "mixed-mode" numeric arithmetic. Should either\n return a 2-tuple containing *self* and *other* converted to a\n common numeric type, or "None" if conversion is impossible. When\n the common type would be the type of "other", it is sufficient to\n return "None", since the interpreter will also ask the other object\n to attempt a coercion (but sometimes, if the implementation of the\n other type cannot be changed, it is useful to do the conversion to\n the other type here). A return value of "NotImplemented" is\n equivalent to returning "None".\n\n\nCoercion rules\n==============\n\nThis section used to document the rules for coercion. As the language\nhas evolved, the coercion rules have become hard to document\nprecisely; documenting what one version of one particular\nimplementation does is undesirable. Instead, here are some informal\nguidelines regarding coercion. In Python 3, coercion will not be\nsupported.\n\n* If the left operand of a % operator is a string or Unicode object,\n no coercion takes place and the string formatting operation is\n invoked instead.\n\n* It is no longer recommended to define a coercion operation. Mixed-\n mode operations on types that don\'t define coercion pass the\n original arguments to the operation.\n\n* New-style classes (those derived from "object") never invoke the\n "__coerce__()" method in response to a binary operator; the only\n time "__coerce__()" is invoked is when the built-in function\n "coerce()" is called.\n\n* For most intents and purposes, an operator that returns\n "NotImplemented" is treated the same as one that is not implemented\n at all.\n\n* Below, "__op__()" and "__rop__()" are used to signify the generic\n method names corresponding to an operator; "__iop__()" is used for\n the corresponding in-place operator. For example, for the operator\n \'"+"\', "__add__()" and "__radd__()" are used for the left and right\n variant of the binary operator, and "__iadd__()" for the in-place\n variant.\n\n* For objects *x* and *y*, first "x.__op__(y)" is tried. If this is\n not implemented or returns "NotImplemented", "y.__rop__(x)" is\n tried. If this is also not implemented or returns "NotImplemented",\n a "TypeError" exception is raised. But see the following exception:\n\n* Exception to the previous item: if the left operand is an instance\n of a built-in type or a new-style class, and the right operand is an\n instance of a proper subclass of that type or class and overrides\n the base\'s "__rop__()" method, the right operand\'s "__rop__()"\n method is tried *before* the left operand\'s "__op__()" method.\n\n This is done so that a subclass can completely override binary\n operators. Otherwise, the left operand\'s "__op__()" method would\n always accept the right operand: when an instance of a given class\n is expected, an instance of a subclass of that class is always\n acceptable.\n\n* When either operand type defines a coercion, this coercion is\n called before that type\'s "__op__()" or "__rop__()" method is\n called, but no sooner. If the coercion returns an object of a\n different type for the operand whose coercion is invoked, part of\n the process is redone using the new object.\n\n* When an in-place operator (like \'"+="\') is used, if the left\n operand implements "__iop__()", it is invoked without any coercion.\n When the operation falls back to "__op__()" and/or "__rop__()", the\n normal coercion rules apply.\n\n* In "x + y", if *x* is a sequence that implements sequence\n concatenation, sequence concatenation is invoked.\n\n* In "x * y", if one operand is a sequence that implements sequence\n repetition, and the other is an integer ("int" or "long"), sequence\n repetition is invoked.\n\n* Rich comparisons (implemented by methods "__eq__()" and so on)\n never use coercion. Three-way comparison (implemented by\n "__cmp__()") does use coercion under the same conditions as other\n binary operations use it.\n\n* In the current implementation, the built-in numeric types "int",\n "long", "float", and "complex" do not use coercion. All these types\n implement a "__coerce__()" method, for use by the built-in\n "coerce()" function.\n\n Changed in version 2.7: The complex type no longer makes implicit\n calls to the "__coerce__()" method for mixed-type binary arithmetic\n operations.\n\n\nWith Statement Context Managers\n===============================\n\nNew in version 2.5.\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section The with\nstatement), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see Context Manager Types.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup for old-style classes\n===========================================\n\nFor old-style classes, special methods are always looked up in exactly\nthe same way as any other method or attribute. This is the case\nregardless of whether the method is being looked up explicitly as in\n"x.__getitem__(i)" or implicitly as in "x[i]".\n\nThis behaviour means that special methods may exhibit different\nbehaviour for different instances of a single old-style class if the\nappropriate special attributes are set differently:\n\n >>> class C:\n ... pass\n ...\n >>> c1 = C()\n >>> c2 = C()\n >>> c1.__len__ = lambda: 5\n >>> c2.__len__ = lambda: 9\n >>> len(c1)\n 5\n >>> len(c2)\n 9\n\n\nSpecial method lookup for new-style classes\n===========================================\n\nFor new-style classes, implicit invocations of special methods are\nonly guaranteed to work correctly if defined on an object\'s type, not\nin the object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception (unlike the equivalent example\nwith old-style classes):\n\n >>> class C(object):\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print "Metaclass getattribute invoked"\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object):\n ... __metaclass__ = Meta\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print "Class getattribute invoked"\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', + 'string-methods': u'\nString Methods\n**************\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n"bytearray" objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange section. To output formatted strings use\ntemplate strings or the "%" operator described in the String\nFormatting Operations section. Also, see the "re" module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n "\'strict\'", meaning that encoding errors raise "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'" and any other\n name registered via "codecs.register_error()", see section Codec\n Base Classes.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n "\'strict\'", meaning that encoding errors raise a "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'",\n "\'xmlcharrefreplace\'", "\'backslashreplace\'" and any other name\n registered via "codecs.register_error()", see section Codec Base\n Classes. For a list of possible encodings, see section Standard\n Encodings.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for "\'xmlcharrefreplace\'" and\n "\'backslashreplace\'" and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See Format String Syntax for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the "%" formatting described in String\n Formatting Operations in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the "maketrans()" helper function in the "string"\n module to create a translation table. For string objects, set the\n *table* argument to "None" for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a "None" *table* argument.\n\n For Unicode objects, the "translate()" method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or "None". Unmapped characters\n are left untouched. Characters mapped to "None" are deleted. Note,\n a more flexible approach is to create a custom character mapping\n codec using the "codecs" module (see "encodings.cp1251" for an\n example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return "True" if there are only numeric characters in S, "False"\n otherwise. Numeric characters include digit characters, and all\n characters that have the Unicode numeric value property, e.g.\n U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return "True" if there are only decimal characters in S, "False"\n otherwise. Decimal characters include digit characters, and all\n characters that can be used to form decimal-radix numbers, e.g.\n U+0660, ARABIC-INDIC DIGIT ZERO.\n', + 'strings': u'\nString literals\n***************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"\n | "b" | "B" | "br" | "Br" | "bR" | "BR"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'"\n | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | escapeseq\n longstringitem ::= longstringchar | escapeseq\n shortstringchar ::= \n longstringchar ::= \n escapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" and the rest of\nthe string literal. The source character set is defined by the\nencoding declaration; it is ASCII if no encoding declaration is given\nin the source file; see section Encoding declarations.\n\nIn plain English: String literals can be enclosed in matching single\nquotes ("\'") or double quotes ("""). They can also be enclosed in\nmatching groups of three single or double quotes (these are generally\nreferred to as *triple-quoted strings*). The backslash ("\\")\ncharacter is used to escape characters that otherwise have a special\nmeaning, such as newline, backslash itself, or the quote character.\nString literals may optionally be prefixed with a letter "\'r\'" or\n"\'R\'"; such strings are called *raw strings* and use different rules\nfor interpreting backslash escape sequences. A prefix of "\'u\'" or\n"\'U\'" makes the string a Unicode string. Unicode strings use the\nUnicode character set as defined by the Unicode Consortium and ISO\n10646. Some additional escape sequences, described below, are\navailable in Unicode strings. A prefix of "\'b\'" or "\'B\'" is ignored in\nPython 2; it indicates that the literal should become a bytes literal\nin Python 3 (e.g. when code is automatically converted with 2to3). A\n"\'u\'" or "\'b\'" prefix may be followed by an "\'r\'" prefix.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\N{name}" | Character named *name* in the | |\n| | Unicode database (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (1) |\n| | *xxxx* (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (2) |\n| | *xxxxxxxx* (Unicode only) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (3,5) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (4,5) |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence.\n\n2. Any Unicode character can be encoded this way, but characters\n outside the Basic Multilingual Plane (BMP) will be encoded using a\n surrogate pair if Python is compiled to use 16-bit code units (the\n default).\n\n3. As in Standard C, up to three octal digits are accepted.\n\n4. Unlike in Standard C, exactly two hex digits are required.\n\n5. In a string literal, hexadecimal and octal escapes denote the\n byte with the given value; it is not necessary that the byte\n encodes a character in the source character set. In a Unicode\n literal, these escapes denote a Unicode character with the given\n value.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences marked as "(Unicode only)"\nin the table above fall into the category of unrecognized escapes for\nnon-Unicode string literals.\n\nWhen an "\'r\'" or "\'R\'" prefix is present, a character following a\nbackslash is included in the string without change, and *all\nbackslashes are left in the string*. For example, the string literal\n"r"\\n"" consists of two characters: a backslash and a lowercase "\'n\'".\nString quotes can be escaped with a backslash, but the backslash\nremains in the string; for example, "r"\\""" is a valid string literal\nconsisting of two characters: a backslash and a double quote; "r"\\""\nis not a valid string literal (even a raw string cannot end in an odd\nnumber of backslashes). Specifically, *a raw string cannot end in a\nsingle backslash* (since the backslash would escape the following\nquote character). Note also that a single backslash followed by a\nnewline is interpreted as those two characters as part of the string,\n*not* as a line continuation.\n\nWhen an "\'r\'" or "\'R\'" prefix is used in conjunction with a "\'u\'" or\n"\'U\'" prefix, then the "\\uXXXX" and "\\UXXXXXXXX" escape sequences are\nprocessed while *all other backslashes are left in the string*. For\nexample, the string literal "ur"\\u0062\\n"" consists of three Unicode\ncharacters: \'LATIN SMALL LETTER B\', \'REVERSE SOLIDUS\', and \'LATIN\nSMALL LETTER N\'. Backslashes can be escaped with a preceding\nbackslash; however, both remain in the string. As a result, "\\uXXXX"\nescape sequences are only recognized when there are an odd number of\nbackslashes.\n', 'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object of a sequence or mapping type.\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to a\nplain integer. If this value is negative, the length of the sequence\nis added to it (so that, e.g., "x[-1]" selects the last item of "x".)\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero).\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0L", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__nonzero__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', - 'try': u'\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression [("as" | ",") identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nChanged in version 2.5: In previous versions of Python,\n"try"..."except"..."finally" did not work. "try"..."except" had to be\nnested in "try"..."finally".\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject, or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified in that except clause, if present, and the except\nclause\'s suite is executed. All except clauses must have an\nexecutable block. When the end of this block is reached, execution\ncontinues normally after the entire try statement. (This means that\nif two nested handlers exist for the same exception, and the exception\noccurs in the try clause of the inner handler, the outer handler will\nnot handle the exception.)\n\nBefore an except clause\'s suite is executed, details about the\nexception are assigned to three variables in the "sys" module:\n"sys.exc_type" receives the object identifying the exception;\n"sys.exc_value" receives the exception\'s parameter;\n"sys.exc_traceback" receives a traceback object (see section *The\nstandard type hierarchy*) identifying the point in the program where\nthe exception occurred. These details are also available through the\n"sys.exc_info()" function, which returns a tuple "(exc_type,\nexc_value, exc_traceback)". Use of the corresponding variables is\ndeprecated in favor of this function, since their use is unsafe in a\nthreaded program. As of Python 1.5, the variables are restored to\ntheir previous values (before the call) when returning from a function\nthat handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception, it is re-raised at the end of the\n"finally" clause. If the "finally" clause raises another exception or\nexecutes a "return" or "break" statement, the saved exception is\ndiscarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.).\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "Ellipsis". It is used to indicate the presence of the "..." syntax\n in a slice. Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are three types of integers:\n\n Plain integers\n These represent numbers in the range -2147483648 through\n 2147483647. (The range may be larger on machines with a\n larger natural word size, but not smaller.) When the result\n of an operation would fall outside this range, the result is\n normally returned as a long integer (in some cases, the\n exception "OverflowError" is raised instead). For the\n purpose of shift and mask operations, integers are assumed to\n have a binary, 2\'s complement notation using 32 or more bits,\n and hiding no bits from the user (i.e., all 4294967296\n different bit patterns correspond to different values).\n\n Long integers\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of plain\n integers, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers and the least surprises when\n switching between the plain and long integer domains. Any\n operation, if it yields a result in the plain integer domain,\n will yield the same result in the long integer domain or when\n using mixed operands. The switch between domains is transparent\n to the programmer.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex"\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n The items of a string are characters. There is no separate\n character type; a character is represented by a string of one\n item. Characters represent (at least) 8-bit bytes. The\n built-in functions "chr()" and "ord()" convert between\n characters and nonnegative integers representing the byte\n values. Bytes with the values 0-127 usually represent the\n corresponding ASCII values, but the interpretation of values\n is up to the program. The string data type is also used to\n represent arrays of bytes, e.g., to hold data read from a\n file.\n\n (On systems whose native character set is not ASCII, strings\n may use EBCDIC in their internal representation, provided the\n functions "chr()" and "ord()" implement a mapping between\n ASCII and EBCDIC, and string comparison preserves the ASCII\n order. Or perhaps someone can propose a better rule?)\n\n Unicode\n The items of a Unicode object are Unicode code units. A\n Unicode code unit is represented by a Unicode object of one\n item and can hold either a 16-bit or 32-bit value\n representing a Unicode ordinal (the maximum value for the\n ordinal is given in "sys.maxunicode", and depends on how\n Python is configured at compile time). Surrogate pairs may\n be present in the Unicode object, and will be reported as two\n separate items. The built-in functions "unichr()" and\n "ord()" convert between code units and nonnegative integers\n representing the Unicode ordinals as defined in the Unicode\n Standard 3.0. Conversion from and to other encodings are\n possible through the Unicode method "encode()" and the built-\n in function "unicode()".\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm", "gdbm", and "bsddb" provide\n additional examples of mapping types.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +-------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +=========================+=================================+=============+\n | "__doc__" "func_doc" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | "__name__" "func_name" | The function\'s name. | Writable |\n +-------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | "func_defaults" | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value. | |\n +-------------------------+---------------------------------+-------------+\n | "__code__" "func_code" | The code object representing | Writable |\n | | the compiled function body. | |\n +-------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | "func_globals" | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +-------------------------+---------------------------------+-------------+\n | "__dict__" "func_dict" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +-------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | "func_closure" | contain bindings for the | |\n | | function\'s free variables. | |\n +-------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Changed in version 2.4: "func_name" is now writable.\n\n Changed in version 2.6: The double-underscore attributes\n "__closure__", "__code__", "__defaults__", and "__globals__"\n were introduced as aliases for the corresponding "func_*"\n attributes for forwards compatibility with Python 3.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n User-defined methods\n A user-defined method object combines a class, a class instance\n (or "None") and any callable object (normally a user-defined\n function).\n\n Special read-only attributes: "im_self" is the class instance\n object, "im_func" is the function object; "im_class" is the\n class of "im_self" for bound methods or the class that asked for\n the method for unbound methods; "__doc__" is the method\'s\n documentation (same as "im_func.__doc__"); "__name__" is the\n method name (same as "im_func.__name__"); "__module__" is the\n name of the module the method was defined in, or "None" if\n unavailable.\n\n Changed in version 2.2: "im_self" used to refer to the class\n that defined the method.\n\n Changed in version 2.6: For Python 3 forward-compatibility,\n "im_func" is also available as "__func__", and "im_self" as\n "__self__".\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object, an unbound\n user-defined method object, or a class method object. When the\n attribute is a user-defined method object, a new method object\n is only created if the class from which it is being retrieved is\n the same as, or a derived class of, the class stored in the\n original method object; otherwise, the original method object is\n used as it is.\n\n When a user-defined method object is created by retrieving a\n user-defined function object from a class, its "im_self"\n attribute is "None" and the method object is said to be unbound.\n When one is created by retrieving a user-defined function object\n from a class via one of its instances, its "im_self" attribute\n is the instance, and the method object is said to be bound. In\n either case, the new method\'s "im_class" attribute is the class\n from which the retrieval takes place, and its "im_func"\n attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "im_func"\n attribute of the new instance is not the original method object\n but its "im_func" attribute.\n\n When a user-defined method object is created by retrieving a\n class method object from a class or instance, its "im_self"\n attribute is the class itself, and its "im_func" attribute is\n the function object underlying the class method.\n\n When an unbound user-defined method object is called, the\n underlying function ("im_func") is called, with the restriction\n that the first argument must be an instance of the proper class\n ("im_class") or of a derived class thereof.\n\n When a bound user-defined method object is called, the\n underlying function ("im_func") is called, inserting the class\n instance ("im_self") in front of the argument list. For\n instance, when "C" is a class which contains a definition for a\n function "f()", and "x" is an instance of "C", calling "x.f(1)"\n is equivalent to calling "C.f(x, 1)".\n\n When a user-defined method object is derived from a class method\n object, the "class instance" stored in "im_self" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to (unbound or\n bound) method object happens each time the attribute is\n retrieved from the class or instance. In some cases, a fruitful\n optimization is to assign the attribute to a local variable and\n call that local variable. Also notice that this transformation\n only happens for user-defined functions; other callable objects\n (and all non-callable objects) are retrieved without\n transformation. It is also important to note that user-defined\n functions which are attributes of a class instance are not\n converted to bound methods; this *only* happens when the\n function is an attribute of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "next()" method will cause the function to\n execute until it provides a value using the "yield" statement.\n When the function executes a "return" statement or falls off the\n end, a "StopIteration" exception is raised and the iterator will\n have reached the end of the set of values to be returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Class Types\n Class types, or "new-style classes," are callable. These\n objects normally act as factories for new instances of\n themselves, but variations are possible for class types that\n override "__new__()". The arguments of the call are passed to\n "__new__()" and, in the typical case, to "__init__()" to\n initialize the new instance.\n\n Classic Classes\n Class objects are described below. When a class object is\n called, a new class instance (also described below) is created\n and returned. This implies a call to the class\'s "__init__()"\n method if it has one. Any arguments are passed on to the\n "__init__()" method. If there is no "__init__()" method, the\n class must be called without arguments.\n\n Class instances\n Class instances are described below. Class instances are\n callable only when the class has a "__call__()" method;\n "x(arguments)" is a shorthand for "x.__call__(arguments)".\n\nModules\n Modules are imported by the "import" statement (see section *The\n import statement*). A module object has a namespace implemented by\n a dictionary object (this is the dictionary referenced by the\n func_globals attribute of functions defined in the module).\n Attribute references are translated to lookups in this dictionary,\n e.g., "m.x" is equivalent to "m.__dict__["x"]". A module object\n does not contain the code object used to initialize the module\n (since it isn\'t needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute is not present for C modules that are statically linked\n into the interpreter; for extension modules loaded dynamically from\n a shared library, it is the pathname of the shared library file.\n\nClasses\n Both class types (new-style classes) and class objects (old-\n style/classic classes) are typically created by class definitions\n (see section *Class definitions*). A class has a namespace\n implemented by a dictionary object. Class attribute references are\n translated to lookups in this dictionary, e.g., "C.x" is translated\n to "C.__dict__["x"]" (although for new-style classes in particular\n there are a number of hooks which allow for other means of locating\n attributes). When the attribute name is not found there, the\n attribute search continues in the base classes. For old-style\n classes, the search is depth-first, left-to-right in the order of\n occurrence in the base class list. New-style classes use the more\n complex C3 method resolution order which behaves correctly even in\n the presence of \'diamond\' inheritance structures where there are\n multiple inheritance paths leading back to a common ancestor.\n Additional details on the C3 MRO used by new-style classes can be\n found in the documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n user-defined function object or an unbound user-defined method\n object whose associated class is either "C" or one of its base\n classes, it is transformed into an unbound user-defined method\n object whose "im_class" attribute is "C". When it would yield a\n class method object, it is transformed into a bound user-defined\n method object whose "im_self" attribute is "C". When it would\n yield a static method object, it is transformed into the object\n wrapped by the static method object. See section *Implementing\n Descriptors* for another way in which attributes retrieved from a\n class may differ from those actually contained in its "__dict__"\n (note that only new-style classes support descriptors).\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object or an unbound user-defined method object whose\n associated class is the class (call it "C") of the instance for\n which the attribute reference was initiated or one of its bases, it\n is transformed into a bound user-defined method object whose\n "im_class" attribute is "C" and whose "im_self" attribute is the\n instance. Static method and class method objects are also\n transformed, as if they had been retrieved from class "C"; see\n above under "Classes". See section *Implementing Descriptors* for\n another way in which attributes of a class retrieved via its\n instances may differ from the objects actually stored in the\n class\'s "__dict__". If no class attribute is found, and the\n object\'s class has a "__getattr__()" method, that is called to\n satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nFiles\n A file object represents an open file. File objects are created by\n the "open()" built-in function, and also by "os.popen()",\n "os.fdopen()", and the "makefile()" method of socket objects (and\n perhaps by other functions or methods provided by extension\n modules). The objects "sys.stdin", "sys.stdout" and "sys.stderr"\n are initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams. See *File Objects* for\n complete documentation of file objects.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names;\n "f_restricted" is a flag indicating whether the function is\n executing in restricted execution mode; "f_lasti" gives the\n precise instruction (this is an index into the bytecode string\n of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_exc_type", "f_exc_value",\n "f_exc_traceback" represent the last exception raised in the\n parent frame provided another exception was ever raised in the\n current frame (in all other cases they are None); "f_lineno" is\n the current line number of the frame --- writing to this from\n within a trace function jumps to the given line (only for the\n bottom-most frame). A debugger can implement a Jump command\n (aka Set Next Statement) by writing to f_lineno.\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 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 "sys.exc_traceback",\n and also as the third item of the tuple returned by\n "sys.exc_info()". The latter is the preferred interface, since\n it works correctly when the program is using multiple threads.\n When the program contains no suitable handler, the stack trace\n is written (nicely formatted) to the standard error stream; if\n the interpreter is interactive, it is also made available to the\n user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in 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 the\n precise instruction. The line number and last instruction 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\n Slice objects\n Slice objects are used to represent slices when *extended slice\n syntax* is used. This is a slice using two colons, or multiple\n slices or ellipses separated by commas, e.g., "a[i:j:step]",\n "a[i:j, k:l]", or "a[..., i:j]". They are also created by the\n built-in "slice()" function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the extended slice that the slice\n object would describe if applied to a sequence of *length*\n items. It returns a tuple of three integers; respectively\n these are the *start* and *stop* indices and the *step* or\n stride length of the slice. Missing or out-of-bounds indices\n are handled in a manner consistent with regular slices.\n\n New in version 2.3.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', - 'typesfunctions': u'\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', - 'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for building a dictionary from\n keyword arguments added.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n New in version 2.5: If a subclass of dict defines a method\n "__missing__()", if the key *key* is not present, the "d[key]"\n operation calls that method with the key *key* as argument. The\n "d[key]" operation then returns or raises whatever is returned\n or raised by the "__missing__(key)" call if the key is not\n present. No other operations or methods invoke "__missing__()".\n If "__missing__()" is not defined, "KeyError" is raised.\n "__missing__()" must be a method; it cannot be an instance\n variable. For an example, see "collections.defaultdict".\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n New in version 2.2.\n\n key not in d\n\n Equivalent to "not key in d".\n\n New in version 2.2.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iterkeys()".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n New in version 2.3.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n has_key(key)\n\n Test for the presence of *key* in the dictionary. "has_key()"\n is deprecated in favor of "key in d".\n\n items()\n\n Return a copy of the dictionary\'s list of "(key, value)" pairs.\n\n **CPython implementation detail:** Keys and values are listed in\n an arbitrary order which is non-random, varies across Python\n implementations, and depends on the dictionary\'s history of\n insertions and deletions.\n\n If "items()", "keys()", "values()", "iteritems()", "iterkeys()",\n and "itervalues()" are called with no intervening modifications\n to the dictionary, the lists will directly correspond. This\n allows the creation of "(value, key)" pairs using "zip()":\n "pairs = zip(d.values(), d.keys())". The same relationship\n holds for the "iterkeys()" and "itervalues()" methods: "pairs =\n zip(d.itervalues(), d.iterkeys())" provides the same value for\n "pairs". Another way to create the same list is "pairs = [(v, k)\n for (k, v) in d.iteritems()]".\n\n iteritems()\n\n Return an iterator over the dictionary\'s "(key, value)" pairs.\n See the note for "dict.items()".\n\n Using "iteritems()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n iterkeys()\n\n Return an iterator over the dictionary\'s keys. See the note for\n "dict.items()".\n\n Using "iterkeys()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n itervalues()\n\n Return an iterator over the dictionary\'s values. See the note\n for "dict.items()".\n\n Using "itervalues()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n keys()\n\n Return a copy of the dictionary\'s list of keys. See the note\n for "dict.items()".\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n New in version 2.3.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n Changed in version 2.4: Allowed the argument to be an iterable\n of key/value pairs and allowed keyword arguments.\n\n values()\n\n Return a copy of the dictionary\'s list of values. See the note\n for "dict.items()".\n\n viewitems()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See below for documentation of view objects.\n\n New in version 2.7.\n\n viewkeys()\n\n Return a new view of the dictionary\'s keys. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n viewvalues()\n\n Return a new view of the dictionary\'s values. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.viewkeys()", "dict.viewvalues()" and\n"dict.viewitems()" are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that (key, value) pairs are unique and\nhashable, then the items view is also set-like. (Values views are not\ntreated as set-like since the entries are generally not unique.) Then\nthese set operations are available ("other" refers either to another\nview or a set):\n\ndictview & other\n\n Return the intersection of the dictview and the other object as a\n new set.\n\ndictview | other\n\n Return the union of the dictview and the other object as a new set.\n\ndictview - other\n\n Return the difference between the dictview and the other object\n (all elements in *dictview* that aren\'t in *other*) as a new set.\n\ndictview ^ other\n\n Return the symmetric difference (all elements either in *dictview*\n or *other*, but not in both) of the dictview and the other object\n as a new set.\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.viewkeys()\n >>> values = dishes.viewvalues()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n', - 'typesmethods': u'\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nThe implementation adds two special read-only attributes to class\ninstance methods: "m.im_self" is the object on which the method\noperates, and "m.im_func" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.im_func(m.im_self, arg-1, arg-2, ..., arg-n)".\n\nClass instance methods are either *bound* or *unbound*, referring to\nwhether the method was accessed through an instance or a class,\nrespectively. When a method is unbound, its "im_self" attribute will\nbe "None" and if called, an explicit "self" object must be passed as\nthe first argument. In this case, "self" must be an instance of the\nunbound method\'s class (or a subclass of that class), otherwise a\n"TypeError" is raised.\n\nLike function objects, methods objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.im_func"), setting method\nattributes on either bound or unbound methods is disallowed.\nAttempting to set an attribute on a method results in an\n"AttributeError" being raised. In order to set a method attribute,\nyou need to explicitly set it on the underlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'instancemethod\' object has no attribute \'whoami\'\n >>> c.method.im_func.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', + 'try': u'\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression [("as" | ",") identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nChanged in version 2.5: In previous versions of Python,\n"try"..."except"..."finally" did not work. "try"..."except" had to be\nnested in "try"..."finally".\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject, or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified in that except clause, if present, and the except\nclause\'s suite is executed. All except clauses must have an\nexecutable block. When the end of this block is reached, execution\ncontinues normally after the entire try statement. (This means that\nif two nested handlers exist for the same exception, and the exception\noccurs in the try clause of the inner handler, the outer handler will\nnot handle the exception.)\n\nBefore an except clause\'s suite is executed, details about the\nexception are assigned to three variables in the "sys" module:\n"sys.exc_type" receives the object identifying the exception;\n"sys.exc_value" receives the exception\'s parameter;\n"sys.exc_traceback" receives a traceback object (see section The\nstandard type hierarchy) identifying the point in the program where\nthe exception occurred. These details are also available through the\n"sys.exc_info()" function, which returns a tuple "(exc_type,\nexc_value, exc_traceback)". Use of the corresponding variables is\ndeprecated in favor of this function, since their use is unsafe in a\nthreaded program. As of Python 1.5, the variables are restored to\ntheir previous values (before the call) when returning from a function\nthat handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception, it is re-raised at the end of the\n"finally" clause. If the "finally" clause raises another exception or\nexecutes a "return" or "break" statement, the saved exception is\ndiscarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\nExceptions, and information on using the "raise" statement to generate\nexceptions may be found in section The raise statement.\n', + 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.).\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "Ellipsis". It is used to indicate the presence of the "..." syntax\n in a slice. Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are three types of integers:\n\n Plain integers\n These represent numbers in the range -2147483648 through\n 2147483647. (The range may be larger on machines with a\n larger natural word size, but not smaller.) When the result\n of an operation would fall outside this range, the result is\n normally returned as a long integer (in some cases, the\n exception "OverflowError" is raised instead). For the\n purpose of shift and mask operations, integers are assumed to\n have a binary, 2\'s complement notation using 32 or more bits,\n and hiding no bits from the user (i.e., all 4294967296\n different bit patterns correspond to different values).\n\n Long integers\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of plain\n integers, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers and the least surprises when\n switching between the plain and long integer domains. Any\n operation, if it yields a result in the plain integer domain,\n will yield the same result in the long integer domain or when\n using mixed operands. The switch between domains is transparent\n to the programmer.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex"\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n The items of a string are characters. There is no separate\n character type; a character is represented by a string of one\n item. Characters represent (at least) 8-bit bytes. The\n built-in functions "chr()" and "ord()" convert between\n characters and nonnegative integers representing the byte\n values. Bytes with the values 0-127 usually represent the\n corresponding ASCII values, but the interpretation of values\n is up to the program. The string data type is also used to\n represent arrays of bytes, e.g., to hold data read from a\n file.\n\n (On systems whose native character set is not ASCII, strings\n may use EBCDIC in their internal representation, provided the\n functions "chr()" and "ord()" implement a mapping between\n ASCII and EBCDIC, and string comparison preserves the ASCII\n order. Or perhaps someone can propose a better rule?)\n\n Unicode\n The items of a Unicode object are Unicode code units. A\n Unicode code unit is represented by a Unicode object of one\n item and can hold either a 16-bit or 32-bit value\n representing a Unicode ordinal (the maximum value for the\n ordinal is given in "sys.maxunicode", and depends on how\n Python is configured at compile time). Surrogate pairs may\n be present in the Unicode object, and will be reported as two\n separate items. The built-in functions "unichr()" and\n "ord()" convert between code units and nonnegative integers\n representing the Unicode ordinals as defined in the Unicode\n Standard 3.0. Conversion from and to other encodings are\n possible through the Unicode method "encode()" and the built-\n in function "unicode()".\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section Dictionary displays).\n\n The extension modules "dbm", "gdbm", and "bsddb" provide\n additional examples of mapping types.\n\nCallable types\n These are the types to which the function call operation (see\n section Calls) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section Function definitions). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +-------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +=========================+=================================+=============+\n | "__doc__" "func_doc" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | "__name__" "func_name" | The function\'s name. | Writable |\n +-------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | "func_defaults" | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value. | |\n +-------------------------+---------------------------------+-------------+\n | "__code__" "func_code" | The code object representing | Writable |\n | | the compiled function body. | |\n +-------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | "func_globals" | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +-------------------------+---------------------------------+-------------+\n | "__dict__" "func_dict" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +-------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | "func_closure" | contain bindings for the | |\n | | function\'s free variables. | |\n +-------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Changed in version 2.4: "func_name" is now writable.\n\n Changed in version 2.6: The double-underscore attributes\n "__closure__", "__code__", "__defaults__", and "__globals__"\n were introduced as aliases for the corresponding "func_*"\n attributes for forwards compatibility with Python 3.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n User-defined methods\n A user-defined method object combines a class, a class instance\n (or "None") and any callable object (normally a user-defined\n function).\n\n Special read-only attributes: "im_self" is the class instance\n object, "im_func" is the function object; "im_class" is the\n class of "im_self" for bound methods or the class that asked for\n the method for unbound methods; "__doc__" is the method\'s\n documentation (same as "im_func.__doc__"); "__name__" is the\n method name (same as "im_func.__name__"); "__module__" is the\n name of the module the method was defined in, or "None" if\n unavailable.\n\n Changed in version 2.2: "im_self" used to refer to the class\n that defined the method.\n\n Changed in version 2.6: For Python 3 forward-compatibility,\n "im_func" is also available as "__func__", and "im_self" as\n "__self__".\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object, an unbound\n user-defined method object, or a class method object. When the\n attribute is a user-defined method object, a new method object\n is only created if the class from which it is being retrieved is\n the same as, or a derived class of, the class stored in the\n original method object; otherwise, the original method object is\n used as it is.\n\n When a user-defined method object is created by retrieving a\n user-defined function object from a class, its "im_self"\n attribute is "None" and the method object is said to be unbound.\n When one is created by retrieving a user-defined function object\n from a class via one of its instances, its "im_self" attribute\n is the instance, and the method object is said to be bound. In\n either case, the new method\'s "im_class" attribute is the class\n from which the retrieval takes place, and its "im_func"\n attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "im_func"\n attribute of the new instance is not the original method object\n but its "im_func" attribute.\n\n When a user-defined method object is created by retrieving a\n class method object from a class or instance, its "im_self"\n attribute is the class itself, and its "im_func" attribute is\n the function object underlying the class method.\n\n When an unbound user-defined method object is called, the\n underlying function ("im_func") is called, with the restriction\n that the first argument must be an instance of the proper class\n ("im_class") or of a derived class thereof.\n\n When a bound user-defined method object is called, the\n underlying function ("im_func") is called, inserting the class\n instance ("im_self") in front of the argument list. For\n instance, when "C" is a class which contains a definition for a\n function "f()", and "x" is an instance of "C", calling "x.f(1)"\n is equivalent to calling "C.f(x, 1)".\n\n When a user-defined method object is derived from a class method\n object, the "class instance" stored in "im_self" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to (unbound or\n bound) method object happens each time the attribute is\n retrieved from the class or instance. In some cases, a fruitful\n optimization is to assign the attribute to a local variable and\n call that local variable. Also notice that this transformation\n only happens for user-defined functions; other callable objects\n (and all non-callable objects) are retrieved without\n transformation. It is also important to note that user-defined\n functions which are attributes of a class instance are not\n converted to bound methods; this *only* happens when the\n function is an attribute of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section The yield statement) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "next()" method will cause the function to\n execute until it provides a value using the "yield" statement.\n When the function executes a "return" statement or falls off the\n end, a "StopIteration" exception is raised and the iterator will\n have reached the end of the set of values to be returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Class Types\n Class types, or "new-style classes," are callable. These\n objects normally act as factories for new instances of\n themselves, but variations are possible for class types that\n override "__new__()". The arguments of the call are passed to\n "__new__()" and, in the typical case, to "__init__()" to\n initialize the new instance.\n\n Classic Classes\n Class objects are described below. When a class object is\n called, a new class instance (also described below) is created\n and returned. This implies a call to the class\'s "__init__()"\n method if it has one. Any arguments are passed on to the\n "__init__()" method. If there is no "__init__()" method, the\n class must be called without arguments.\n\n Class instances\n Class instances are described below. Class instances are\n callable only when the class has a "__call__()" method;\n "x(arguments)" is a shorthand for "x.__call__(arguments)".\n\nModules\n Modules are imported by the "import" statement (see section The\n import statement). A module object has a namespace implemented by a\n dictionary object (this is the dictionary referenced by the\n func_globals attribute of functions defined in the module).\n Attribute references are translated to lookups in this dictionary,\n e.g., "m.x" is equivalent to "m.__dict__["x"]". A module object\n does not contain the code object used to initialize the module\n (since it isn\'t needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute is not present for C modules that are statically linked\n into the interpreter; for extension modules loaded dynamically from\n a shared library, it is the pathname of the shared library file.\n\nClasses\n Both class types (new-style classes) and class objects (old-\n style/classic classes) are typically created by class definitions\n (see section Class definitions). A class has a namespace\n implemented by a dictionary object. Class attribute references are\n translated to lookups in this dictionary, e.g., "C.x" is translated\n to "C.__dict__["x"]" (although for new-style classes in particular\n there are a number of hooks which allow for other means of locating\n attributes). When the attribute name is not found there, the\n attribute search continues in the base classes. For old-style\n classes, the search is depth-first, left-to-right in the order of\n occurrence in the base class list. New-style classes use the more\n complex C3 method resolution order which behaves correctly even in\n the presence of \'diamond\' inheritance structures where there are\n multiple inheritance paths leading back to a common ancestor.\n Additional details on the C3 MRO used by new-style classes can be\n found in the documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n user-defined function object or an unbound user-defined method\n object whose associated class is either "C" or one of its base\n classes, it is transformed into an unbound user-defined method\n object whose "im_class" attribute is "C". When it would yield a\n class method object, it is transformed into a bound user-defined\n method object whose "im_self" attribute is "C". When it would\n yield a static method object, it is transformed into the object\n wrapped by the static method object. See section Implementing\n Descriptors for another way in which attributes retrieved from a\n class may differ from those actually contained in its "__dict__"\n (note that only new-style classes support descriptors).\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object or an unbound user-defined method object whose\n associated class is the class (call it "C") of the instance for\n which the attribute reference was initiated or one of its bases, it\n is transformed into a bound user-defined method object whose\n "im_class" attribute is "C" and whose "im_self" attribute is the\n instance. Static method and class method objects are also\n transformed, as if they had been retrieved from class "C"; see\n above under "Classes". See section Implementing Descriptors for\n another way in which attributes of a class retrieved via its\n instances may differ from the objects actually stored in the\n class\'s "__dict__". If no class attribute is found, and the\n object\'s class has a "__getattr__()" method, that is called to\n satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n Special method names.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nFiles\n A file object represents an open file. File objects are created by\n the "open()" built-in function, and also by "os.popen()",\n "os.fdopen()", and the "makefile()" method of socket objects (and\n perhaps by other functions or methods provided by extension\n modules). The objects "sys.stdin", "sys.stdout" and "sys.stderr"\n are initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams. See File Objects for\n complete documentation of file objects.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names;\n "f_restricted" is a flag indicating whether the function is\n executing in restricted execution mode; "f_lasti" gives the\n precise instruction (this is an index into the bytecode string\n of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_exc_type", "f_exc_value",\n "f_exc_traceback" represent the last exception raised in the\n parent frame provided another exception was ever raised in the\n current frame (in all other cases they are None); "f_lineno" is\n the current line number of the frame --- writing to this from\n within a trace function jumps to the given line (only for the\n bottom-most frame). A debugger can implement a Jump command\n (aka Set Next Statement) by writing to f_lineno.\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 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 "sys.exc_traceback", and\n also as the third item of the tuple returned by\n "sys.exc_info()". The latter is the preferred interface, since\n it works correctly when the program is using multiple threads.\n When the program contains no suitable handler, the stack trace\n is written (nicely formatted) to the standard error stream; if\n the interpreter is interactive, it is also made available to the\n user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in 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 the\n precise instruction. The line number and last instruction 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\n Slice objects\n Slice objects are used to represent slices when *extended slice\n syntax* is used. This is a slice using two colons, or multiple\n slices or ellipses separated by commas, e.g., "a[i:j:step]",\n "a[i:j, k:l]", or "a[..., i:j]". They are also created by the\n built-in "slice()" function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the extended slice that the slice\n object would describe if applied to a sequence of *length*\n items. It returns a tuple of three integers; respectively\n these are the *start* and *stop* indices and the *step* or\n stride length of the slice. Missing or out-of-bounds indices\n are handled in a manner consistent with regular slices.\n\n New in version 2.3.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', + 'typesfunctions': u'\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee Function definitions for more information.\n', + 'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for building a dictionary from\n keyword arguments added.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()" and *key*\n is not present, the "d[key]" operation calls that method with\n the key *key* as argument. The "d[key]" operation then returns\n or raises whatever is returned or raised by the\n "__missing__(key)" call. No other operations or methods invoke\n "__missing__()". If "__missing__()" is not defined, "KeyError"\n is raised. "__missing__()" must be a method; it cannot be an\n instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n The example above shows part of the implementation of\n "collections.Counter". A different "__missing__" method is used\n by "collections.defaultdict".\n\n New in version 2.5: Recognition of __missing__ methods of dict\n subclasses.\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n New in version 2.2.\n\n key not in d\n\n Equivalent to "not key in d".\n\n New in version 2.2.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iterkeys()".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n New in version 2.3.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n has_key(key)\n\n Test for the presence of *key* in the dictionary. "has_key()"\n is deprecated in favor of "key in d".\n\n items()\n\n Return a copy of the dictionary\'s list of "(key, value)" pairs.\n\n **CPython implementation detail:** Keys and values are listed in\n an arbitrary order which is non-random, varies across Python\n implementations, and depends on the dictionary\'s history of\n insertions and deletions.\n\n If "items()", "keys()", "values()", "iteritems()", "iterkeys()",\n and "itervalues()" are called with no intervening modifications\n to the dictionary, the lists will directly correspond. This\n allows the creation of "(value, key)" pairs using "zip()":\n "pairs = zip(d.values(), d.keys())". The same relationship\n holds for the "iterkeys()" and "itervalues()" methods: "pairs =\n zip(d.itervalues(), d.iterkeys())" provides the same value for\n "pairs". Another way to create the same list is "pairs = [(v, k)\n for (k, v) in d.iteritems()]".\n\n iteritems()\n\n Return an iterator over the dictionary\'s "(key, value)" pairs.\n See the note for "dict.items()".\n\n Using "iteritems()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n iterkeys()\n\n Return an iterator over the dictionary\'s keys. See the note for\n "dict.items()".\n\n Using "iterkeys()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n itervalues()\n\n Return an iterator over the dictionary\'s values. See the note\n for "dict.items()".\n\n Using "itervalues()" while adding or deleting entries in the\n dictionary may raise a "RuntimeError" or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n keys()\n\n Return a copy of the dictionary\'s list of keys. See the note\n for "dict.items()".\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n New in version 2.3.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n Changed in version 2.4: Allowed the argument to be an iterable\n of key/value pairs and allowed keyword arguments.\n\n values()\n\n Return a copy of the dictionary\'s list of values. See the note\n for "dict.items()".\n\n viewitems()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See below for documentation of view objects.\n\n New in version 2.7.\n\n viewkeys()\n\n Return a new view of the dictionary\'s keys. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n viewvalues()\n\n Return a new view of the dictionary\'s values. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.viewkeys()", "dict.viewvalues()" and\n"dict.viewitems()" are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that (key, value) pairs are unique and\nhashable, then the items view is also set-like. (Values views are not\ntreated as set-like since the entries are generally not unique.) Then\nthese set operations are available ("other" refers either to another\nview or a set):\n\ndictview & other\n\n Return the intersection of the dictview and the other object as a\n new set.\n\ndictview | other\n\n Return the union of the dictview and the other object as a new set.\n\ndictview - other\n\n Return the difference between the dictview and the other object\n (all elements in *dictview* that aren\'t in *other*) as a new set.\n\ndictview ^ other\n\n Return the symmetric difference (all elements either in *dictview*\n or *other*, but not in both) of the dictview and the other object\n as a new set.\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.viewkeys()\n >>> values = dishes.viewvalues()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n', + 'typesmethods': u'\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nThe implementation adds two special read-only attributes to class\ninstance methods: "m.im_self" is the object on which the method\noperates, and "m.im_func" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.im_func(m.im_self, arg-1, arg-2, ..., arg-n)".\n\nClass instance methods are either *bound* or *unbound*, referring to\nwhether the method was accessed through an instance or a class,\nrespectively. When a method is unbound, its "im_self" attribute will\nbe "None" and if called, an explicit "self" object must be passed as\nthe first argument. In this case, "self" must be an instance of the\nunbound method\'s class (or a subclass of that class), otherwise a\n"TypeError" is raised.\n\nLike function objects, methods objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.im_func"), setting method\nattributes on either bound or unbound methods is disallowed.\nAttempting to set an attribute on a method results in an\n"AttributeError" being raised. In order to set a method attribute,\nyou need to explicitly set it on the underlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'instancemethod\' object has no attribute \'whoami\'\n >>> c.method.im_func.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee The standard type hierarchy for more information.\n', 'typesmodules': u'\nModules\n*******\n\nThe only special operation on a module is attribute access: "m.name",\nwhere *m* is a module and *name* accesses a name defined in *m*\'s\nsymbol table. Module attributes can be assigned to. (Note that the\n"import" statement is not, strictly speaking, an operation on a module\nobject; "import foo" does not require a module object named *foo* to\nexist, rather it requires an (external) *definition* for a module\nnamed *foo* somewhere.)\n\nA special attribute of every module is "__dict__". This is the\ndictionary containing the module\'s symbol table. Modifying this\ndictionary will actually change the module\'s symbol table, but direct\nassignment to the "__dict__" attribute is not possible (you can write\n"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but you can\'t\nwrite "m.__dict__ = {}"). Modifying "__dict__" directly is not\nrecommended.\n\nModules built into the interpreter are written like this: "". If loaded from a file, they are written as\n"".\n', - 'typesseq': u'\nSequence Types --- "str", "unicode", "list", "tuple", "bytearray", "buffer", "xrange"\n*************************************************************************************\n\nThere are seven sequence types: strings, Unicode strings, lists,\ntuples, bytearrays, buffers, and xrange objects.\n\nFor other containers see the built in "dict" and "set" classes, and\nthe "collections" module.\n\nString literals are written in single or double quotes: "\'xyzzy\'",\n""frobozz"". See *String literals* for more about string literals.\nUnicode strings are much like strings, but are specified in the syntax\nusing a preceding "\'u\'" character: "u\'abc\'", "u"def"". In addition to\nthe functionality described here, there are also string-specific\nmethods described in the *String Methods* section. Lists are\nconstructed with square brackets, separating items with commas: "[a,\nb, c]". Tuples are constructed by the comma operator (not within\nsquare brackets), with or without enclosing parentheses, but an empty\ntuple must have the enclosing parentheses, such as "a, b, c" or "()".\nA single item tuple must have a trailing comma, such as "(d,)".\n\nBytearray objects are created with the built-in function\n"bytearray()".\n\nBuffer objects are not directly supported by Python syntax, but can be\ncreated by calling the built-in function "buffer()". They don\'t\nsupport concatenation or repetition.\n\nObjects of type xrange are similar to buffers in that there is no\nspecific syntax to create them, but they are created using the\n"xrange()" function. They don\'t support slicing, concatenation or\nrepetition, and using "in", "not in", "min()" or "max()" on them is\ninefficient.\n\nMost sequence types support the following operations. The "in" and\n"not in" operations have the same priorities as the comparison\noperations. The "+" and "*" operations have the same priority as the\ncorresponding numeric operations. [3] Additional methods are provided\nfor *Mutable Sequence Types*.\n\nThis table lists the sequence operations sorted in ascending priority.\nIn the table, *s* and *t* are sequences of the same type; *n*, *i* and\n*j* are integers:\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n| | equal to *x*, else "False" | |\n+--------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n| | equal to *x*, else "True" | |\n+--------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| "s * n, n * s" | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| "len(s)" | length of *s* | |\n+--------------------+----------------------------------+------------+\n| "min(s)" | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| "max(s)" | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| "s.index(x)" | index of the first occurrence of | |\n| | *x* in *s* | |\n+--------------------+----------------------------------+------------+\n| "s.count(x)" | total number of occurrences of | |\n| | *x* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must compare\nequal and the two sequences must be of the same type and have the same\nlength. (For full details see *Comparisons* in the language\nreference.)\n\nNotes:\n\n1. When *s* is a string or Unicode string object the "in" and "not\n in" operations act like a substring test. In Python versions\n before 2.3, *x* had to be a string of length 1. In Python 2.3 and\n beyond, *x* may be a string of any length.\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are (pointers\n to) this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. **CPython implementation detail:** If *s* and *t* are both\n strings, some Python implementations such as CPython can usually\n perform an in-place optimization for assignments of the form "s = s\n + t" or "s += t". When applicable, this optimization makes\n quadratic run-time much less likely. This optimization is both\n version and implementation dependent. For performance sensitive\n code, it is preferable to use the "str.join()" method which assures\n consistent linear concatenation performance across versions and\n implementations.\n\n Changed in version 2.4: Formerly, string concatenation never\n occurred in-place.\n\n\nString Methods\n==============\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n"bytearray" objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange* section. To output formatted strings use\ntemplate strings or the "%" operator described in the *String\nFormatting Operations* section. Also, see the "re" module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n "\'strict\'", meaning that encoding errors raise "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'" and any other\n name registered via "codecs.register_error()", see section *Codec\n Base Classes*.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n "\'strict\'", meaning that encoding errors raise a "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'",\n "\'xmlcharrefreplace\'", "\'backslashreplace\'" and any other name\n registered via "codecs.register_error()", see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for "\'xmlcharrefreplace\'" and\n "\'backslashreplace\'" and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the "%" formatting described in *String\n Formatting Operations* in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the "maketrans()" helper function in the "string"\n module to create a translation table. For string objects, set the\n *table* argument to "None" for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a "None" *table* argument.\n\n For Unicode objects, the "translate()" method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or "None". Unmapped characters\n are left untouched. Characters mapped to "None" are deleted. Note,\n a more flexible approach is to create a custom character mapping\n codec using the "codecs" module (see "encodings.cp1251" for an\n example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return "True" if there are only numeric characters in S, "False"\n otherwise. Numeric characters include digit characters, and all\n characters that have the Unicode numeric value property, e.g.\n U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return "True" if there are only decimal characters in S, "False"\n otherwise. Decimal characters include digit characters, and all\n characters that can be used to form decimal-radix numbers, e.g.\n U+0660, ARABIC-INDIC DIGIT ZERO.\n\n\nString Formatting Operations\n============================\n\nString and Unicode objects have one unique built-in operation: the "%"\noperator (modulo). This is also known as the string *formatting* or\n*interpolation* operator. Given "format % values" (where *format* is\na string or Unicode object), "%" conversion specifications in *format*\nare replaced with zero or more elements of *values*. The effect is\nsimilar to the using "sprintf()" in the C language. If *format* is a\nUnicode object, or if any of the objects being converted using the\n"%s" conversion are Unicode objects, the result will also be a Unicode\nobject.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The "\'%\'" character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence\n of characters (for example, "(somename)").\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an "\'*\'"\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a "\'.\'" (dot) followed by the\n precision. If specified as "\'*\'" (an asterisk), the actual width\n is read from the next element of the tuple in *values*, and the\n value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the "\'%\'" character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print \'%(language)s has %(number)03d quote types.\' % \\\n... {"language": "Python", "number": 2}\nPython has 002 quote types.\n\nIn this case no "*" specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| "\'#\'" | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| "\'0\'" | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| "\'-\'" | The converted value is left adjusted (overrides the "\'0\'" conversion |\n| | if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| "\' \'" | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| "\'+\'" | A sign character ("\'+\'" or "\'-\'") will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier ("h", "l", or "L") may be present, but is ignored as\nit is not necessary for Python -- so e.g. "%ld" is identical to "%d".\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| "\'d\'" | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'i\'" | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'o\'" | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| "\'u\'" | Obsolete type -- it is identical to "\'d\'". | (7) |\n+--------------+-------------------------------------------------------+---------+\n| "\'x\'" | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| "\'X\'" | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| "\'e\'" | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'E\'" | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'f\'" | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'F\'" | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'g\'" | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'G\'" | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'c\'" | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| "\'r\'" | String (converts any Python object using *repr()*). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| "\'s\'" | String (converts any Python object using "str()"). | (6) |\n+--------------+-------------------------------------------------------+---------+\n| "\'%\'" | No argument is converted, results in a "\'%\'" | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero ("\'0\'") to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading "\'0x\'" or "\'0X\'" (depending\n on whether the "\'x\'" or "\'X\'" format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. The "%r" conversion was added in Python 2.0.\n\n The precision determines the maximal number of characters used.\n\n6. If the object or format provided is a "unicode" string, the\n resulting string will also be "unicode".\n\n The precision determines the maximal number of characters used.\n\n7. See **PEP 237**.\n\nSince Python strings have an explicit length, "%s" conversions do not\nassume that "\'\\0\'" is the end of the string.\n\nChanged in version 2.7: "%f" conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by "%g" conversions.\n\nAdditional string operations are defined in standard modules "string"\nand "re".\n\n\nXRange Type\n===========\n\nThe "xrange" type is an immutable sequence which is commonly used for\nlooping. The advantage of the "xrange" type is that an "xrange"\nobject will always take the same amount of memory, no matter the size\nof the range it represents. There are no consistent performance\nadvantages.\n\nXRange objects have very little behavior: they only support indexing,\niteration, and the "len()" function.\n\n\nMutable Sequence Types\n======================\n\nList and "bytearray" objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | same as "s[len(s):len(s)] = [x]" | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(x)" | same as "s[len(s):len(s)] = x" | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.count(x)" | return number of *i*\'s for which | |\n| | "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.index(x[, i[, j]])" | return smallest *k* such that | (4) |\n| | "s[k] == x" and "i <= k < j" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | same as "s[i:i] = [x]" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | same as "x = s[i]; del s[i]; | (6) |\n| | return x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | same as "del s[s.index(x)]" | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])" | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted\n multiple parameters and implicitly joined them into a tuple; this\n no longer works in Python 2.0. Use of this misfeature has been\n deprecated since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises "ValueError" when *x* is not found in *s*. When a\n negative index is passed as the second or third parameter to the\n "index()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, "index()" didn\'t have arguments\n for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n "insert()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The "pop()" method\'s optional argument *i* defaults to "-1", so\n that by default the last item is removed and returned.\n\n7. The "sort()" and "reverse()" methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don\'t return the\n sorted or reversed list.\n\n8. The "sort()" method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: "cmp=lambda x,y:\n cmp(x.lower(), y.lower())". The default value is "None".\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: "key=str.lower". The\n default value is "None".\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n "functools.cmp_to_key()" to convert an old-style *cmp* function to\n a *key* function.\n\n Changed in version 2.3: Support for "None" as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the "sort()" method is guaranteed to\n be stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being\n sorted, the effect of attempting to mutate, or even inspect, the\n list is undefined. The C implementation of Python 2.3 and newer\n makes the list appear empty for the duration, and raises\n "ValueError" if it can detect that the list has been mutated\n during a sort.\n', + 'typesseq': u'\nSequence Types --- "str", "unicode", "list", "tuple", "bytearray", "buffer", "xrange"\n*************************************************************************************\n\nThere are seven sequence types: strings, Unicode strings, lists,\ntuples, bytearrays, buffers, and xrange objects.\n\nFor other containers see the built in "dict" and "set" classes, and\nthe "collections" module.\n\nString literals are written in single or double quotes: "\'xyzzy\'",\n""frobozz"". See String literals for more about string literals.\nUnicode strings are much like strings, but are specified in the syntax\nusing a preceding "\'u\'" character: "u\'abc\'", "u"def"". In addition to\nthe functionality described here, there are also string-specific\nmethods described in the String Methods section. Lists are constructed\nwith square brackets, separating items with commas: "[a, b, c]".\nTuples are constructed by the comma operator (not within square\nbrackets), with or without enclosing parentheses, but an empty tuple\nmust have the enclosing parentheses, such as "a, b, c" or "()". A\nsingle item tuple must have a trailing comma, such as "(d,)".\n\nBytearray objects are created with the built-in function\n"bytearray()".\n\nBuffer objects are not directly supported by Python syntax, but can be\ncreated by calling the built-in function "buffer()". They don\'t\nsupport concatenation or repetition.\n\nObjects of type xrange are similar to buffers in that there is no\nspecific syntax to create them, but they are created using the\n"xrange()" function. They don\'t support slicing, concatenation or\nrepetition, and using "in", "not in", "min()" or "max()" on them is\ninefficient.\n\nMost sequence types support the following operations. The "in" and\n"not in" operations have the same priorities as the comparison\noperations. The "+" and "*" operations have the same priority as the\ncorresponding numeric operations. [3] Additional methods are provided\nfor Mutable Sequence Types.\n\nThis table lists the sequence operations sorted in ascending priority.\nIn the table, *s* and *t* are sequences of the same type; *n*, *i* and\n*j* are integers:\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n| | equal to *x*, else "False" | |\n+--------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n| | equal to *x*, else "True" | |\n+--------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| "s * n, n * s" | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| "len(s)" | length of *s* | |\n+--------------------+----------------------------------+------------+\n| "min(s)" | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| "max(s)" | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| "s.index(x)" | index of the first occurrence of | |\n| | *x* in *s* | |\n+--------------------+----------------------------------+------------+\n| "s.count(x)" | total number of occurrences of | |\n| | *x* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must compare\nequal and the two sequences must be of the same type and have the same\nlength. (For full details see Comparisons in the language reference.)\n\nNotes:\n\n1. When *s* is a string or Unicode string object the "in" and "not\n in" operations act like a substring test. In Python versions\n before 2.3, *x* had to be a string of length 1. In Python 2.3 and\n beyond, *x* may be a string of any length.\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are (pointers\n to) this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. **CPython implementation detail:** If *s* and *t* are both\n strings, some Python implementations such as CPython can usually\n perform an in-place optimization for assignments of the form "s = s\n + t" or "s += t". When applicable, this optimization makes\n quadratic run-time much less likely. This optimization is both\n version and implementation dependent. For performance sensitive\n code, it is preferable to use the "str.join()" method which assures\n consistent linear concatenation performance across versions and\n implementations.\n\n Changed in version 2.4: Formerly, string concatenation never\n occurred in-place.\n\n\nString Methods\n==============\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n"bytearray" objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange section. To output formatted strings use\ntemplate strings or the "%" operator described in the String\nFormatting Operations section. Also, see the "re" module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n "\'strict\'", meaning that encoding errors raise "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'" and any other\n name registered via "codecs.register_error()", see section Codec\n Base Classes.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n "\'strict\'", meaning that encoding errors raise a "UnicodeError".\n Other possible values are "\'ignore\'", "\'replace\'",\n "\'xmlcharrefreplace\'", "\'backslashreplace\'" and any other name\n registered via "codecs.register_error()", see section Codec Base\n Classes. For a list of possible encodings, see section Standard\n Encodings.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for "\'xmlcharrefreplace\'" and\n "\'backslashreplace\'" and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See Format String Syntax for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the "%" formatting described in String\n Formatting Operations in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the "maketrans()" helper function in the "string"\n module to create a translation table. For string objects, set the\n *table* argument to "None" for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a "None" *table* argument.\n\n For Unicode objects, the "translate()" method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or "None". Unmapped characters\n are left untouched. Characters mapped to "None" are deleted. Note,\n a more flexible approach is to create a custom character mapping\n codec using the "codecs" module (see "encodings.cp1251" for an\n example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return "True" if there are only numeric characters in S, "False"\n otherwise. Numeric characters include digit characters, and all\n characters that have the Unicode numeric value property, e.g.\n U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return "True" if there are only decimal characters in S, "False"\n otherwise. Decimal characters include digit characters, and all\n characters that can be used to form decimal-radix numbers, e.g.\n U+0660, ARABIC-INDIC DIGIT ZERO.\n\n\nString Formatting Operations\n============================\n\nString and Unicode objects have one unique built-in operation: the "%"\noperator (modulo). This is also known as the string *formatting* or\n*interpolation* operator. Given "format % values" (where *format* is\na string or Unicode object), "%" conversion specifications in *format*\nare replaced with zero or more elements of *values*. The effect is\nsimilar to the using "sprintf()" in the C language. If *format* is a\nUnicode object, or if any of the objects being converted using the\n"%s" conversion are Unicode objects, the result will also be a Unicode\nobject.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The "\'%\'" character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence\n of characters (for example, "(somename)").\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an "\'*\'"\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a "\'.\'" (dot) followed by the\n precision. If specified as "\'*\'" (an asterisk), the actual width\n is read from the next element of the tuple in *values*, and the\n value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the "\'%\'" character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print \'%(language)s has %(number)03d quote types.\' % \\\n... {"language": "Python", "number": 2}\nPython has 002 quote types.\n\nIn this case no "*" specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| "\'#\'" | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| "\'0\'" | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| "\'-\'" | The converted value is left adjusted (overrides the "\'0\'" conversion |\n| | if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| "\' \'" | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| "\'+\'" | A sign character ("\'+\'" or "\'-\'") will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier ("h", "l", or "L") may be present, but is ignored as\nit is not necessary for Python -- so e.g. "%ld" is identical to "%d".\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| "\'d\'" | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'i\'" | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'o\'" | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| "\'u\'" | Obsolete type -- it is identical to "\'d\'". | (7) |\n+--------------+-------------------------------------------------------+---------+\n| "\'x\'" | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| "\'X\'" | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| "\'e\'" | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'E\'" | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'f\'" | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'F\'" | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| "\'g\'" | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'G\'" | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| "\'c\'" | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| "\'r\'" | String (converts any Python object using repr()). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| "\'s\'" | String (converts any Python object using "str()"). | (6) |\n+--------------+-------------------------------------------------------+---------+\n| "\'%\'" | No argument is converted, results in a "\'%\'" | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero ("\'0\'") to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading "\'0x\'" or "\'0X\'" (depending\n on whether the "\'x\'" or "\'X\'" format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. The "%r" conversion was added in Python 2.0.\n\n The precision determines the maximal number of characters used.\n\n6. If the object or format provided is a "unicode" string, the\n resulting string will also be "unicode".\n\n The precision determines the maximal number of characters used.\n\n7. See **PEP 237**.\n\nSince Python strings have an explicit length, "%s" conversions do not\nassume that "\'\\0\'" is the end of the string.\n\nChanged in version 2.7: "%f" conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by "%g" conversions.\n\nAdditional string operations are defined in standard modules "string"\nand "re".\n\n\nXRange Type\n===========\n\nThe "xrange" type is an immutable sequence which is commonly used for\nlooping. The advantage of the "xrange" type is that an "xrange"\nobject will always take the same amount of memory, no matter the size\nof the range it represents. There are no consistent performance\nadvantages.\n\nXRange objects have very little behavior: they only support indexing,\niteration, and the "len()" function.\n\n\nMutable Sequence Types\n======================\n\nList and "bytearray" objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | same as "s[len(s):len(s)] = [x]" | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(x)" | same as "s[len(s):len(s)] = x" | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.count(x)" | return number of *i*\'s for which | |\n| | "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.index(x[, i[, j]])" | return smallest *k* such that | (4) |\n| | "s[k] == x" and "i <= k < j" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | same as "s[i:i] = [x]" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | same as "x = s[i]; del s[i]; | (6) |\n| | return x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | same as "del s[s.index(x)]" | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])" | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted\n multiple parameters and implicitly joined them into a tuple; this\n no longer works in Python 2.0. Use of this misfeature has been\n deprecated since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises "ValueError" when *x* is not found in *s*. When a\n negative index is passed as the second or third parameter to the\n "index()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, "index()" didn\'t have arguments\n for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n "insert()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The "pop()" method\'s optional argument *i* defaults to "-1", so\n that by default the last item is removed and returned.\n\n7. The "sort()" and "reverse()" methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don\'t return the\n sorted or reversed list.\n\n8. The "sort()" method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: "cmp=lambda x,y:\n cmp(x.lower(), y.lower())". The default value is "None".\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: "key=str.lower". The\n default value is "None".\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n "functools.cmp_to_key()" to convert an old-style *cmp* function to\n a *key* function.\n\n Changed in version 2.3: Support for "None" as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the "sort()" method is guaranteed to\n be stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being\n sorted, the effect of attempting to mutate, or even inspect, the\n list is undefined. The C implementation of Python 2.3 and newer\n makes the list appear empty for the duration, and raises\n "ValueError" if it can detect that the list has been mutated\n during a sort.\n', 'typesseq-mutable': u'\nMutable Sequence Types\n**********************\n\nList and "bytearray" objects support additional operations that allow\nin-place modification of the object. Other mutable sequence types\n(when added to the language) should also support these operations.\nStrings and tuples are immutable sequence types: such objects cannot\nbe modified once created. The following operations are defined on\nmutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | same as "s[len(s):len(s)] = [x]" | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(x)" | same as "s[len(s):len(s)] = x" | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.count(x)" | return number of *i*\'s for which | |\n| | "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.index(x[, i[, j]])" | return smallest *k* such that | (4) |\n| | "s[k] == x" and "i <= k < j" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | same as "s[i:i] = [x]" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | same as "x = s[i]; del s[i]; | (6) |\n| | return x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | same as "del s[s.index(x)]" | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])" | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted\n multiple parameters and implicitly joined them into a tuple; this\n no longer works in Python 2.0. Use of this misfeature has been\n deprecated since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises "ValueError" when *x* is not found in *s*. When a\n negative index is passed as the second or third parameter to the\n "index()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, "index()" didn\'t have arguments\n for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n "insert()" method, the list length is added, as for slice indices.\n If it is still negative, it is truncated to zero, as for slice\n indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The "pop()" method\'s optional argument *i* defaults to "-1", so\n that by default the last item is removed and returned.\n\n7. The "sort()" and "reverse()" methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don\'t return the\n sorted or reversed list.\n\n8. The "sort()" method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: "cmp=lambda x,y:\n cmp(x.lower(), y.lower())". The default value is "None".\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: "key=str.lower". The\n default value is "None".\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n "functools.cmp_to_key()" to convert an old-style *cmp* function to\n a *key* function.\n\n Changed in version 2.3: Support for "None" as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the "sort()" method is guaranteed to\n be stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being\n sorted, the effect of attempting to mutate, or even inspect, the\n list is undefined. The C implementation of Python 2.3 and newer\n makes the list appear empty for the duration, and raises\n "ValueError" if it can detect that the list has been mutated\n during a sort.\n', 'unary': u'\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\nplain or long integer argument. The bitwise inversion of "x" is\ndefined as "-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', 'while': u'\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', - 'with': u'\nThe "with" statement\n********************\n\nNew in version 2.5.\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nNote: In Python 2.5, the "with" statement is only allowed when the\n "with_statement" feature has been enabled. It is always enabled in\n Python 2.6.\n\nChanged in version 2.7: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', - 'yield': u'\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the generator\'s "next()"\nmethod repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nAs of Python version 2.5, the "yield" statement is now allowed in the\n"try" clause of a "try" ... "finally" construct. If the generator is\nnot resumed before it is finalized (by reaching a zero reference count\nor by being garbage collected), the generator-iterator\'s "close()"\nmethod will be called, allowing any pending "finally" clauses to\nexecute.\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nNote: In Python 2.2, the "yield" statement was only allowed when the\n "generators" feature has been enabled. This "__future__" import\n statement was used to enable the feature:\n\n from __future__ import generators\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal that, among other generator enhancements, proposed\n allowing "yield" to appear inside a "try" ... "finally" block.\n'} + 'with': u'\nThe "with" statement\n********************\n\nNew in version 2.5.\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section With Statement\nContext Managers). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nNote: In Python 2.5, the "with" statement is only allowed when the\n "with_statement" feature has been enabled. It is always enabled in\n Python 2.6.\n\nChanged in version 2.7: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'yield': u'\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the generator\'s "next()"\nmethod repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nAs of Python version 2.5, the "yield" statement is now allowed in the\n"try" clause of a "try" ... "finally" construct. If the generator is\nnot resumed before it is finalized (by reaching a zero reference count\nor by being garbage collected), the generator-iterator\'s "close()"\nmethod will be called, allowing any pending "finally" clauses to\nexecute.\n\nFor full details of "yield" semantics, refer to the Yield expressions\nsection.\n\nNote: In Python 2.2, the "yield" statement was only allowed when the\n "generators" feature has been enabled. This "__future__" import\n statement was used to enable the feature:\n\n from __future__ import generators\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal that, among other generator enhancements, proposed\n allowing "yield" to appear inside a "try" ... "finally" block.\n'} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 10 21:10:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 10 May 2015 19:10:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322906=3A_Do_incre?= =?utf-8?q?f_before_SetCause/SetContext?= Message-ID: <20150510191025.8952.92524@psf.io> https://hg.python.org/cpython/rev/787cc3d1d3af changeset: 95940:787cc3d1d3af parent: 95935:f7cc54086cd2 user: Yury Selivanov date: Sun May 10 15:09:46 2015 -0400 summary: Issue #22906: Do incref before SetCause/SetContext files: Objects/genobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -149,9 +149,9 @@ "generator raised StopIteration"); PyErr_Fetch(&exc, &val2, &tb); PyErr_NormalizeException(&exc, &val2, &tb); + Py_INCREF(val); PyException_SetCause(val2, val); PyException_SetContext(val2, val); - Py_INCREF(val); PyErr_Restore(exc, val2, tb); } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 00:00:48 2015 From: python-checkins at python.org (matthias.klose) Date: Sun, 10 May 2015 22:00:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A__-_Do_not_ital?= =?utf-8?q?icize_punctuation_in_the_python_man_page?= Message-ID: <20150510220048.1919.57710@psf.io> https://hg.python.org/cpython/rev/b918c0ab8049 changeset: 95941:b918c0ab8049 branch: 2.7 parent: 95939:4f2fc30d483f user: doko at ubuntu.com date: Mon May 11 00:00:38 2015 +0200 summary: - Do not italicize punctuation in the python man page files: Misc/python.man | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -289,9 +289,9 @@ from that file; when called with .B \-c -.I command, +.IR command , it executes the Python statement(s) given as -.I command. +.IR command . Here .I command may contain multiple statements separated by newlines. @@ -301,7 +301,7 @@ .PP If available, the script name and additional arguments thereafter are passed to the script in the Python variable -.I sys.argv , +.IR sys.argv , which is a list of strings (you must first .I import sys to be able to access it). @@ -315,14 +315,14 @@ .I '-c'. Note that options interpreted by the Python interpreter itself are not placed in -.I sys.argv. +.IR sys.argv . .PP In interactive mode, the primary prompt is `>>>'; the second prompt (which appears when a command is not complete) is `...'. The prompts can be changed by assignment to .I sys.ps1 or -.I sys.ps2. +.IR sys.ps2 . The interpreter quits when it reads an EOF at a prompt. When an unhandled exception occurs, a stack trace is printed and control returns to the primary prompt; in non-interactive mode, the @@ -381,7 +381,7 @@ inserted in the path in front of $PYTHONPATH. The search path can be manipulated from within a Python program as the variable -.I sys.path . +.IR sys.path . .IP PYTHONSTARTUP If this is the name of a readable file, the Python commands in that file are executed before the first prompt is displayed in interactive -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 01:24:48 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 10 May 2015 23:24:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2321800=3A_Add_RFC_6855_s?= =?utf-8?q?upport_to_imaplib=2E?= Message-ID: <20150510232448.14346.45438@psf.io> https://hg.python.org/cpython/rev/195343b5e64f changeset: 95942:195343b5e64f parent: 95940:787cc3d1d3af user: R David Murray date: Sun May 10 19:17:23 2015 -0400 summary: #21800: Add RFC 6855 support to imaplib. Original patch by Milan Oberkirch, updated by myself and Maciej Szulik. files: Doc/library/imaplib.rst | 30 ++++++++++- Doc/whatsnew/3.5.rst | 11 +++ Lib/imaplib.py | 77 ++++++++++++++++++++------ Lib/test/test_imaplib.py | 78 ++++++++++++++++++++++++++++ Misc/NEWS | 4 + 5 files changed, 179 insertions(+), 21 deletions(-) diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -77,7 +77,8 @@ There's also a subclass for secure connections: -.. class:: IMAP4_SSL(host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_context=None) +.. class:: IMAP4_SSL(host='', port=IMAP4_SSL_PORT, keyfile=None, \ + certfile=None, ssl_context=None) This is a subclass derived from :class:`IMAP4` that connects over an SSL encrypted socket (to use this class you need a socket module that was compiled @@ -211,6 +212,10 @@ that will be base64 encoded and sent to the server. It should return ``None`` if the client abort response ``*`` should be sent instead. + .. versionchanged:: 3.5 + string usernames and passwords are now encoded to ``utf-8`` instead of + being limited to ASCII. + .. method:: IMAP4.check() @@ -243,6 +248,16 @@ Delete the ACLs (remove any rights) set for who on mailbox. +.. method:: IMAP4.enable(capability) + + Enable *capability* (see :rfc:`5161`). Most capabilities do not need to be + enabled. Currently only the ``UTF8=ACCEPT`` capability is supported + (see :RFC:`6855`). + + .. versionadded:: 3.5 + The :meth:`enable` method itself, and :RFC:`6855` support. + + .. method:: IMAP4.expunge() Permanently remove deleted items from selected mailbox. Generates an ``EXPUNGE`` @@ -380,7 +395,9 @@ Search mailbox for matching messages. *charset* may be ``None``, in which case no ``CHARSET`` will be specified in the request to the server. The IMAP protocol requires that at least one criterion be specified; an exception will be - raised when the server returns an error. + raised when the server returns an error. *charset* must be ``None`` if + the ``UTF8=ACCEPT`` capability was enabled using the :meth:`enable` + command. Example:: @@ -542,6 +559,15 @@ the module variable ``Debug``. Values greater than three trace each command. +.. attribute:: IMAP4.utf8_enabled + + Boolean value that is normally ``False``, but is set to ``True`` if an + :meth:`enable` command is successfully issued for the ``UTF8=ACCEPT`` + capability. + + .. versionadded:: 3.5 + + .. _imap4-example: IMAP4 Example diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -337,6 +337,17 @@ automatically at the end of the block. (Contributed by Tarek Ziad? and Serhiy Storchaka in :issue:`4972`.) +* :mod:`imaplib` now supports :rfc:`5161`: the :meth:`~imaplib.IMAP4.enable` + extension), and :rfc:`6855`: utf-8 support (internationalized email, via the + ``UTF8=ACCEPT`` argument to :meth:`~imaplib.IMAP4.enable`). A new attribute, + :attr:`~imaplib.IMAP4.utf8_enabled`, tracks whether or not :rfc:`6855` + support is enabled. Milan Oberkirch, R. David Murray, and Maciej Szulik in + :issue:`21800`.) + +* :mod:`imaplib` now automatically encodes non-ASCII string usernames and + passwords using ``UTF8``, as recommended by the RFCs. (Contributed by Milan + Oberkirch in :issue:`21800`.) + imghdr ------ diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -66,6 +66,7 @@ 'CREATE': ('AUTH', 'SELECTED'), 'DELETE': ('AUTH', 'SELECTED'), 'DELETEACL': ('AUTH', 'SELECTED'), + 'ENABLE': ('AUTH', ), 'EXAMINE': ('AUTH', 'SELECTED'), 'EXPUNGE': ('SELECTED',), 'FETCH': ('SELECTED',), @@ -107,12 +108,17 @@ br' (?P[0-9][0-9]):(?P[0-9][0-9]):(?P[0-9][0-9])' br' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9])' br'"') +# Literal is no longer used; kept for backward compatibility. Literal = re.compile(br'.*{(?P\d+)}$', re.ASCII) MapCRLF = re.compile(br'\r\n|\r|\n') Response_code = re.compile(br'\[(?P[A-Z-]+)( (?P[^\]]*))?\]') Untagged_response = re.compile(br'\* (?P[A-Z-]+)( (?P.*))?') +# Untagged_status is no longer used; kept for backward compatibility Untagged_status = re.compile( br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?', re.ASCII) +# We compile these in _mode_xxx. +_Literal = br'.*{(?P\d+)}$' +_Untagged_status = br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?' @@ -166,7 +172,7 @@ class abort(error): pass # Service errors - close and retry class readonly(abort): pass # Mailbox status changed to READ-ONLY - def __init__(self, host = '', port = IMAP4_PORT): + def __init__(self, host='', port=IMAP4_PORT): self.debug = Debug self.state = 'LOGOUT' self.literal = None # A literal argument to a command @@ -176,6 +182,7 @@ self.is_readonly = False # READ-ONLY desired state self.tagnum = 0 self._tls_established = False + self._mode_ascii() # Open socket to server. @@ -190,6 +197,19 @@ pass raise + def _mode_ascii(self): + self.utf8_enabled = False + self._encoding = 'ascii' + self.Literal = re.compile(_Literal, re.ASCII) + self.Untagged_status = re.compile(_Untagged_status, re.ASCII) + + + def _mode_utf8(self): + self.utf8_enabled = True + self._encoding = 'utf-8' + self.Literal = re.compile(_Literal) + self.Untagged_status = re.compile(_Untagged_status) + def _connect(self): # Create unique tag for this session, @@ -360,7 +380,10 @@ date_time = Time2Internaldate(date_time) else: date_time = None - self.literal = MapCRLF.sub(CRLF, message) + literal = MapCRLF.sub(CRLF, message) + if self.utf8_enabled: + literal = b'UTF8 (' + literal + b')' + self.literal = literal return self._simple_command(name, mailbox, flags, date_time) @@ -455,6 +478,18 @@ """ return self._simple_command('DELETEACL', mailbox, who) + def enable(self, capability): + """Send an RFC5161 enable string to the server. + + (typ, [data]) = .enable(capability) + """ + if 'ENABLE' not in self.capabilities: + raise IMAP4.error("Server does not support ENABLE") + typ, data = self._simple_command('ENABLE', capability) + if typ == 'OK' and 'UTF8=ACCEPT' in capability.upper(): + self._mode_utf8() + return typ, data + def expunge(self): """Permanently remove deleted items from selected mailbox. @@ -561,7 +596,7 @@ def _CRAM_MD5_AUTH(self, challenge): """ Authobject to use with CRAM-MD5 authentication. """ import hmac - pwd = (self.password.encode('ASCII') if isinstance(self.password, str) + pwd = (self.password.encode('utf-8') if isinstance(self.password, str) else self.password) return self.user + " " + hmac.HMAC(pwd, challenge, 'md5').hexdigest() @@ -661,9 +696,12 @@ (typ, [data]) = .search(charset, criterion, ...) 'data' is space separated list of matching message numbers. + If UTF8 is enabled, charset MUST be None. """ name = 'SEARCH' if charset: + if self.utf8_enabled: + raise IMAP4.error("Non-None charset not valid in UTF8 mode") typ, dat = self._simple_command(name, 'CHARSET', charset, *criteria) else: typ, dat = self._simple_command(name, *criteria) @@ -877,7 +915,7 @@ def _check_bye(self): bye = self.untagged_responses.get('BYE') if bye: - raise self.abort(bye[-1].decode('ascii', 'replace')) + raise self.abort(bye[-1].decode(self._encoding, 'replace')) def _command(self, name, *args): @@ -898,12 +936,12 @@ raise self.readonly('mailbox status changed to READ-ONLY') tag = self._new_tag() - name = bytes(name, 'ASCII') + name = bytes(name, self._encoding) data = tag + b' ' + name for arg in args: if arg is None: continue if isinstance(arg, str): - arg = bytes(arg, "ASCII") + arg = bytes(arg, self._encoding) data = data + b' ' + arg literal = self.literal @@ -913,7 +951,7 @@ literator = literal else: literator = None - data = data + bytes(' {%s}' % len(literal), 'ASCII') + data = data + bytes(' {%s}' % len(literal), self._encoding) if __debug__: if self.debug >= 4: @@ -978,7 +1016,7 @@ typ, dat = self.capability() if dat == [None]: raise self.error('no CAPABILITY response from server') - dat = str(dat[-1], "ASCII") + dat = str(dat[-1], self._encoding) dat = dat.upper() self.capabilities = tuple(dat.split()) @@ -997,10 +1035,10 @@ if self._match(self.tagre, resp): tag = self.mo.group('tag') if not tag in self.tagged_commands: - raise self.abort('unexpected tagged response: %s' % resp) + raise self.abort('unexpected tagged response: %r' % resp) typ = self.mo.group('type') - typ = str(typ, 'ASCII') + typ = str(typ, self._encoding) dat = self.mo.group('data') self.tagged_commands[tag] = (typ, [dat]) else: @@ -1009,7 +1047,7 @@ # '*' (untagged) responses? if not self._match(Untagged_response, resp): - if self._match(Untagged_status, resp): + if self._match(self.Untagged_status, resp): dat2 = self.mo.group('data2') if self.mo is None: @@ -1019,17 +1057,17 @@ self.continuation_response = self.mo.group('data') return None # NB: indicates continuation - raise self.abort("unexpected response: '%s'" % resp) + raise self.abort("unexpected response: %r" % resp) typ = self.mo.group('type') - typ = str(typ, 'ascii') + typ = str(typ, self._encoding) dat = self.mo.group('data') if dat is None: dat = b'' # Null untagged response if dat2: dat = dat + b' ' + dat2 # Is there a literal to come? - while self._match(Literal, dat): + while self._match(self.Literal, dat): # Read literal direct from connection. @@ -1053,7 +1091,7 @@ if typ in ('OK', 'NO', 'BAD') and self._match(Response_code, dat): typ = self.mo.group('type') - typ = str(typ, "ASCII") + typ = str(typ, self._encoding) self._append_untagged(typ, self.mo.group('data')) if __debug__: @@ -1123,7 +1161,7 @@ def _new_tag(self): - tag = self.tagpre + bytes(str(self.tagnum), 'ASCII') + tag = self.tagpre + bytes(str(self.tagnum), self._encoding) self.tagnum = self.tagnum + 1 self.tagged_commands[tag] = None return tag @@ -1213,7 +1251,8 @@ """ - def __init__(self, host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_context=None): + def __init__(self, host='', port=IMAP4_SSL_PORT, keyfile=None, + certfile=None, ssl_context=None): if ssl_context is not None and keyfile is not None: raise ValueError("ssl_context and keyfile arguments are mutually " "exclusive") @@ -1251,7 +1290,7 @@ Instantiate with: IMAP4_stream(command) - where "command" is a string that can be passed to subprocess.Popen() + "command" - a string that can be passed to subprocess.Popen() for more documentation see the docstring of the parent class IMAP4. """ @@ -1328,7 +1367,7 @@ # oup = b'' if isinstance(inp, str): - inp = inp.encode('ASCII') + inp = inp.encode('utf-8') while inp: if len(inp) > 48: t = inp[:48] diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -265,6 +265,84 @@ self.assertRaises(imaplib.IMAP4.abort, self.imap_class, *server.server_address) + class UTF8Server(SimpleIMAPHandler): + capabilities = 'AUTH ENABLE UTF8=ACCEPT' + + def cmd_ENABLE(self, tag, args): + self._send_tagged(tag, 'OK', 'ENABLE successful') + + def cmd_AUTHENTICATE(self, tag, args): + self._send_textline('+') + self.server.response = yield + self._send_tagged(tag, 'OK', 'FAKEAUTH successful') + + @reap_threads + def test_enable_raises_error_if_not_AUTH(self): + with self.reaped_pair(self.UTF8Server) as (server, client): + self.assertFalse(client.utf8_enabled) + self.assertRaises(imaplib.IMAP4.error, client.enable, 'foo') + self.assertFalse(client.utf8_enabled) + + # XXX Also need a test that enable after SELECT raises an error. + + @reap_threads + def test_enable_raises_error_if_no_capability(self): + class NoEnableServer(self.UTF8Server): + capabilities = 'AUTH' + with self.reaped_pair(NoEnableServer) as (server, client): + self.assertRaises(imaplib.IMAP4.error, client.enable, 'foo') + + @reap_threads + def test_enable_UTF8_raises_error_if_not_supported(self): + class NonUTF8Server(SimpleIMAPHandler): + pass + with self.assertRaises(imaplib.IMAP4.error): + with self.reaped_pair(NonUTF8Server) as (server, client): + typ, data = client.login('user', 'pass') + self.assertEqual(typ, 'OK') + client.enable('UTF8=ACCEPT') + pass + + @reap_threads + def test_enable_UTF8_True_append(self): + + class UTF8AppendServer(self.UTF8Server): + def cmd_APPEND(self, tag, args): + self._send_textline('+') + self.server.response = yield + self._send_tagged(tag, 'OK', 'okay') + + with self.reaped_pair(UTF8AppendServer) as (server, client): + self.assertEqual(client._encoding, 'ascii') + code, _ = client.authenticate('MYAUTH', lambda x: b'fake') + self.assertEqual(code, 'OK') + self.assertEqual(server.response, + b'ZmFrZQ==\r\n') # b64 encoded 'fake' + code, _ = client.enable('UTF8=ACCEPT') + self.assertEqual(code, 'OK') + self.assertEqual(client._encoding, 'utf-8') + msg_string = 'Subject: ???????' + typ, data = client.append( + None, None, None, msg_string.encode('utf-8')) + self.assertEqual(typ, 'OK') + self.assertEqual( + server.response, + ('UTF8 (%s)\r\n' % msg_string).encode('utf-8') + ) + + # XXX also need a test that makes sure that the Literal and Untagged_status + # regexes uses unicode in UTF8 mode instead of the default ASCII. + + @reap_threads + def test_search_disallows_charset_in_utf8_mode(self): + with self.reaped_pair(self.UTF8Server) as (server, client): + typ, _ = client.authenticate('MYAUTH', lambda x: b'fake') + self.assertEqual(typ, 'OK') + typ, _ = client.enable('UTF8=ACCEPT') + self.assertEqual(typ, 'OK') + self.assertTrue(client.utf8_enabled) + self.assertRaises(imaplib.IMAP4.error, client.search, 'foo', 'bar') + @reap_threads def test_bad_auth_name(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,10 @@ Library ------- +- Issue #21800: imaplib now supports RFC 5161 (enable), RFC 6855 + (utf8/internationalized email) and automatically encodes non-ASCII + usernames and passwords to UTF8. + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 03:20:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 May 2015 01:20:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150511012006.11922.59171@psf.io> https://hg.python.org/cpython/rev/2ca5a37f996f changeset: 95945:2ca5a37f996f parent: 95935:f7cc54086cd2 parent: 95943:8eddc3c169df user: Benjamin Peterson date: Sun May 10 21:19:56 2015 -0400 summary: merge 3.4 files: Misc/python.man | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -431,7 +431,7 @@ The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. .SH AUTHOR -The Python Software Foundation: https://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES Main website: https://www.python.org/ .br -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 03:20:05 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 May 2015 01:20:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_add_trailing_s?= =?utf-8?q?lash?= Message-ID: <20150511012005.1919.7404@psf.io> https://hg.python.org/cpython/rev/8eddc3c169df changeset: 95943:8eddc3c169df branch: 3.4 parent: 95929:9dfda4e7169a user: Benjamin Peterson date: Sun May 10 21:19:18 2015 -0400 summary: add trailing slash files: Misc/python.man | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -434,7 +434,7 @@ The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. .SH AUTHOR -The Python Software Foundation: https://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES Main website: https://www.python.org/ .br -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 03:20:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 May 2015 01:20:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_add_trailing_s?= =?utf-8?q?lash?= Message-ID: <20150511012006.8940.7001@psf.io> https://hg.python.org/cpython/rev/240fc7d2526b changeset: 95944:240fc7d2526b branch: 2.7 parent: 95941:b918c0ab8049 user: Benjamin Peterson date: Sun May 10 21:19:18 2015 -0400 summary: add trailing slash files: Misc/python.man | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -452,7 +452,7 @@ the value 0 will lead to the same hash values as when hash randomization is disabled. .SH AUTHOR -The Python Software Foundation: https://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES Main website: https://www.python.org/ .br -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 03:20:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 May 2015 01:20:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <20150511012006.8147.33886@psf.io> https://hg.python.org/cpython/rev/a290885ec0da changeset: 95946:a290885ec0da parent: 95945:2ca5a37f996f parent: 95942:195343b5e64f user: Benjamin Peterson date: Sun May 10 21:20:01 2015 -0400 summary: merge heads files: Doc/library/imaplib.rst | 30 ++++++++++- Doc/whatsnew/3.5.rst | 11 +++ Lib/imaplib.py | 77 ++++++++++++++++++++------ Lib/test/test_imaplib.py | 78 ++++++++++++++++++++++++++++ Misc/NEWS | 4 + Objects/genobject.c | 2 +- 6 files changed, 180 insertions(+), 22 deletions(-) diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -77,7 +77,8 @@ There's also a subclass for secure connections: -.. class:: IMAP4_SSL(host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_context=None) +.. class:: IMAP4_SSL(host='', port=IMAP4_SSL_PORT, keyfile=None, \ + certfile=None, ssl_context=None) This is a subclass derived from :class:`IMAP4` that connects over an SSL encrypted socket (to use this class you need a socket module that was compiled @@ -211,6 +212,10 @@ that will be base64 encoded and sent to the server. It should return ``None`` if the client abort response ``*`` should be sent instead. + .. versionchanged:: 3.5 + string usernames and passwords are now encoded to ``utf-8`` instead of + being limited to ASCII. + .. method:: IMAP4.check() @@ -243,6 +248,16 @@ Delete the ACLs (remove any rights) set for who on mailbox. +.. method:: IMAP4.enable(capability) + + Enable *capability* (see :rfc:`5161`). Most capabilities do not need to be + enabled. Currently only the ``UTF8=ACCEPT`` capability is supported + (see :RFC:`6855`). + + .. versionadded:: 3.5 + The :meth:`enable` method itself, and :RFC:`6855` support. + + .. method:: IMAP4.expunge() Permanently remove deleted items from selected mailbox. Generates an ``EXPUNGE`` @@ -380,7 +395,9 @@ Search mailbox for matching messages. *charset* may be ``None``, in which case no ``CHARSET`` will be specified in the request to the server. The IMAP protocol requires that at least one criterion be specified; an exception will be - raised when the server returns an error. + raised when the server returns an error. *charset* must be ``None`` if + the ``UTF8=ACCEPT`` capability was enabled using the :meth:`enable` + command. Example:: @@ -542,6 +559,15 @@ the module variable ``Debug``. Values greater than three trace each command. +.. attribute:: IMAP4.utf8_enabled + + Boolean value that is normally ``False``, but is set to ``True`` if an + :meth:`enable` command is successfully issued for the ``UTF8=ACCEPT`` + capability. + + .. versionadded:: 3.5 + + .. _imap4-example: IMAP4 Example diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -337,6 +337,17 @@ automatically at the end of the block. (Contributed by Tarek Ziad? and Serhiy Storchaka in :issue:`4972`.) +* :mod:`imaplib` now supports :rfc:`5161`: the :meth:`~imaplib.IMAP4.enable` + extension), and :rfc:`6855`: utf-8 support (internationalized email, via the + ``UTF8=ACCEPT`` argument to :meth:`~imaplib.IMAP4.enable`). A new attribute, + :attr:`~imaplib.IMAP4.utf8_enabled`, tracks whether or not :rfc:`6855` + support is enabled. Milan Oberkirch, R. David Murray, and Maciej Szulik in + :issue:`21800`.) + +* :mod:`imaplib` now automatically encodes non-ASCII string usernames and + passwords using ``UTF8``, as recommended by the RFCs. (Contributed by Milan + Oberkirch in :issue:`21800`.) + imghdr ------ diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -66,6 +66,7 @@ 'CREATE': ('AUTH', 'SELECTED'), 'DELETE': ('AUTH', 'SELECTED'), 'DELETEACL': ('AUTH', 'SELECTED'), + 'ENABLE': ('AUTH', ), 'EXAMINE': ('AUTH', 'SELECTED'), 'EXPUNGE': ('SELECTED',), 'FETCH': ('SELECTED',), @@ -107,12 +108,17 @@ br' (?P[0-9][0-9]):(?P[0-9][0-9]):(?P[0-9][0-9])' br' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9])' br'"') +# Literal is no longer used; kept for backward compatibility. Literal = re.compile(br'.*{(?P\d+)}$', re.ASCII) MapCRLF = re.compile(br'\r\n|\r|\n') Response_code = re.compile(br'\[(?P[A-Z-]+)( (?P[^\]]*))?\]') Untagged_response = re.compile(br'\* (?P[A-Z-]+)( (?P.*))?') +# Untagged_status is no longer used; kept for backward compatibility Untagged_status = re.compile( br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?', re.ASCII) +# We compile these in _mode_xxx. +_Literal = br'.*{(?P\d+)}$' +_Untagged_status = br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?' @@ -166,7 +172,7 @@ class abort(error): pass # Service errors - close and retry class readonly(abort): pass # Mailbox status changed to READ-ONLY - def __init__(self, host = '', port = IMAP4_PORT): + def __init__(self, host='', port=IMAP4_PORT): self.debug = Debug self.state = 'LOGOUT' self.literal = None # A literal argument to a command @@ -176,6 +182,7 @@ self.is_readonly = False # READ-ONLY desired state self.tagnum = 0 self._tls_established = False + self._mode_ascii() # Open socket to server. @@ -190,6 +197,19 @@ pass raise + def _mode_ascii(self): + self.utf8_enabled = False + self._encoding = 'ascii' + self.Literal = re.compile(_Literal, re.ASCII) + self.Untagged_status = re.compile(_Untagged_status, re.ASCII) + + + def _mode_utf8(self): + self.utf8_enabled = True + self._encoding = 'utf-8' + self.Literal = re.compile(_Literal) + self.Untagged_status = re.compile(_Untagged_status) + def _connect(self): # Create unique tag for this session, @@ -360,7 +380,10 @@ date_time = Time2Internaldate(date_time) else: date_time = None - self.literal = MapCRLF.sub(CRLF, message) + literal = MapCRLF.sub(CRLF, message) + if self.utf8_enabled: + literal = b'UTF8 (' + literal + b')' + self.literal = literal return self._simple_command(name, mailbox, flags, date_time) @@ -455,6 +478,18 @@ """ return self._simple_command('DELETEACL', mailbox, who) + def enable(self, capability): + """Send an RFC5161 enable string to the server. + + (typ, [data]) = .enable(capability) + """ + if 'ENABLE' not in self.capabilities: + raise IMAP4.error("Server does not support ENABLE") + typ, data = self._simple_command('ENABLE', capability) + if typ == 'OK' and 'UTF8=ACCEPT' in capability.upper(): + self._mode_utf8() + return typ, data + def expunge(self): """Permanently remove deleted items from selected mailbox. @@ -561,7 +596,7 @@ def _CRAM_MD5_AUTH(self, challenge): """ Authobject to use with CRAM-MD5 authentication. """ import hmac - pwd = (self.password.encode('ASCII') if isinstance(self.password, str) + pwd = (self.password.encode('utf-8') if isinstance(self.password, str) else self.password) return self.user + " " + hmac.HMAC(pwd, challenge, 'md5').hexdigest() @@ -661,9 +696,12 @@ (typ, [data]) = .search(charset, criterion, ...) 'data' is space separated list of matching message numbers. + If UTF8 is enabled, charset MUST be None. """ name = 'SEARCH' if charset: + if self.utf8_enabled: + raise IMAP4.error("Non-None charset not valid in UTF8 mode") typ, dat = self._simple_command(name, 'CHARSET', charset, *criteria) else: typ, dat = self._simple_command(name, *criteria) @@ -877,7 +915,7 @@ def _check_bye(self): bye = self.untagged_responses.get('BYE') if bye: - raise self.abort(bye[-1].decode('ascii', 'replace')) + raise self.abort(bye[-1].decode(self._encoding, 'replace')) def _command(self, name, *args): @@ -898,12 +936,12 @@ raise self.readonly('mailbox status changed to READ-ONLY') tag = self._new_tag() - name = bytes(name, 'ASCII') + name = bytes(name, self._encoding) data = tag + b' ' + name for arg in args: if arg is None: continue if isinstance(arg, str): - arg = bytes(arg, "ASCII") + arg = bytes(arg, self._encoding) data = data + b' ' + arg literal = self.literal @@ -913,7 +951,7 @@ literator = literal else: literator = None - data = data + bytes(' {%s}' % len(literal), 'ASCII') + data = data + bytes(' {%s}' % len(literal), self._encoding) if __debug__: if self.debug >= 4: @@ -978,7 +1016,7 @@ typ, dat = self.capability() if dat == [None]: raise self.error('no CAPABILITY response from server') - dat = str(dat[-1], "ASCII") + dat = str(dat[-1], self._encoding) dat = dat.upper() self.capabilities = tuple(dat.split()) @@ -997,10 +1035,10 @@ if self._match(self.tagre, resp): tag = self.mo.group('tag') if not tag in self.tagged_commands: - raise self.abort('unexpected tagged response: %s' % resp) + raise self.abort('unexpected tagged response: %r' % resp) typ = self.mo.group('type') - typ = str(typ, 'ASCII') + typ = str(typ, self._encoding) dat = self.mo.group('data') self.tagged_commands[tag] = (typ, [dat]) else: @@ -1009,7 +1047,7 @@ # '*' (untagged) responses? if not self._match(Untagged_response, resp): - if self._match(Untagged_status, resp): + if self._match(self.Untagged_status, resp): dat2 = self.mo.group('data2') if self.mo is None: @@ -1019,17 +1057,17 @@ self.continuation_response = self.mo.group('data') return None # NB: indicates continuation - raise self.abort("unexpected response: '%s'" % resp) + raise self.abort("unexpected response: %r" % resp) typ = self.mo.group('type') - typ = str(typ, 'ascii') + typ = str(typ, self._encoding) dat = self.mo.group('data') if dat is None: dat = b'' # Null untagged response if dat2: dat = dat + b' ' + dat2 # Is there a literal to come? - while self._match(Literal, dat): + while self._match(self.Literal, dat): # Read literal direct from connection. @@ -1053,7 +1091,7 @@ if typ in ('OK', 'NO', 'BAD') and self._match(Response_code, dat): typ = self.mo.group('type') - typ = str(typ, "ASCII") + typ = str(typ, self._encoding) self._append_untagged(typ, self.mo.group('data')) if __debug__: @@ -1123,7 +1161,7 @@ def _new_tag(self): - tag = self.tagpre + bytes(str(self.tagnum), 'ASCII') + tag = self.tagpre + bytes(str(self.tagnum), self._encoding) self.tagnum = self.tagnum + 1 self.tagged_commands[tag] = None return tag @@ -1213,7 +1251,8 @@ """ - def __init__(self, host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_context=None): + def __init__(self, host='', port=IMAP4_SSL_PORT, keyfile=None, + certfile=None, ssl_context=None): if ssl_context is not None and keyfile is not None: raise ValueError("ssl_context and keyfile arguments are mutually " "exclusive") @@ -1251,7 +1290,7 @@ Instantiate with: IMAP4_stream(command) - where "command" is a string that can be passed to subprocess.Popen() + "command" - a string that can be passed to subprocess.Popen() for more documentation see the docstring of the parent class IMAP4. """ @@ -1328,7 +1367,7 @@ # oup = b'' if isinstance(inp, str): - inp = inp.encode('ASCII') + inp = inp.encode('utf-8') while inp: if len(inp) > 48: t = inp[:48] diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -265,6 +265,84 @@ self.assertRaises(imaplib.IMAP4.abort, self.imap_class, *server.server_address) + class UTF8Server(SimpleIMAPHandler): + capabilities = 'AUTH ENABLE UTF8=ACCEPT' + + def cmd_ENABLE(self, tag, args): + self._send_tagged(tag, 'OK', 'ENABLE successful') + + def cmd_AUTHENTICATE(self, tag, args): + self._send_textline('+') + self.server.response = yield + self._send_tagged(tag, 'OK', 'FAKEAUTH successful') + + @reap_threads + def test_enable_raises_error_if_not_AUTH(self): + with self.reaped_pair(self.UTF8Server) as (server, client): + self.assertFalse(client.utf8_enabled) + self.assertRaises(imaplib.IMAP4.error, client.enable, 'foo') + self.assertFalse(client.utf8_enabled) + + # XXX Also need a test that enable after SELECT raises an error. + + @reap_threads + def test_enable_raises_error_if_no_capability(self): + class NoEnableServer(self.UTF8Server): + capabilities = 'AUTH' + with self.reaped_pair(NoEnableServer) as (server, client): + self.assertRaises(imaplib.IMAP4.error, client.enable, 'foo') + + @reap_threads + def test_enable_UTF8_raises_error_if_not_supported(self): + class NonUTF8Server(SimpleIMAPHandler): + pass + with self.assertRaises(imaplib.IMAP4.error): + with self.reaped_pair(NonUTF8Server) as (server, client): + typ, data = client.login('user', 'pass') + self.assertEqual(typ, 'OK') + client.enable('UTF8=ACCEPT') + pass + + @reap_threads + def test_enable_UTF8_True_append(self): + + class UTF8AppendServer(self.UTF8Server): + def cmd_APPEND(self, tag, args): + self._send_textline('+') + self.server.response = yield + self._send_tagged(tag, 'OK', 'okay') + + with self.reaped_pair(UTF8AppendServer) as (server, client): + self.assertEqual(client._encoding, 'ascii') + code, _ = client.authenticate('MYAUTH', lambda x: b'fake') + self.assertEqual(code, 'OK') + self.assertEqual(server.response, + b'ZmFrZQ==\r\n') # b64 encoded 'fake' + code, _ = client.enable('UTF8=ACCEPT') + self.assertEqual(code, 'OK') + self.assertEqual(client._encoding, 'utf-8') + msg_string = 'Subject: ???????' + typ, data = client.append( + None, None, None, msg_string.encode('utf-8')) + self.assertEqual(typ, 'OK') + self.assertEqual( + server.response, + ('UTF8 (%s)\r\n' % msg_string).encode('utf-8') + ) + + # XXX also need a test that makes sure that the Literal and Untagged_status + # regexes uses unicode in UTF8 mode instead of the default ASCII. + + @reap_threads + def test_search_disallows_charset_in_utf8_mode(self): + with self.reaped_pair(self.UTF8Server) as (server, client): + typ, _ = client.authenticate('MYAUTH', lambda x: b'fake') + self.assertEqual(typ, 'OK') + typ, _ = client.enable('UTF8=ACCEPT') + self.assertEqual(typ, 'OK') + self.assertTrue(client.utf8_enabled) + self.assertRaises(imaplib.IMAP4.error, client.search, 'foo', 'bar') + @reap_threads def test_bad_auth_name(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,10 @@ Library ------- +- Issue #21800: imaplib now supports RFC 5161 (enable), RFC 6855 + (utf8/internationalized email) and automatically encodes non-ASCII + usernames and passwords to UTF8. + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -149,9 +149,9 @@ "generator raised StopIteration"); PyErr_Fetch(&exc, &val2, &tb); PyErr_NormalizeException(&exc, &val2, &tb); + Py_INCREF(val); PyException_SetCause(val2, val); PyException_SetContext(val2, val); - Py_INCREF(val); PyErr_Restore(exc, val2, tb); } } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 04:14:42 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 11 May 2015 02:14:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Adds_UUIDs_for?= =?utf-8?q?_2=2E7=2E10?= Message-ID: <20150511021442.76616.22675@psf.io> https://hg.python.org/cpython/rev/5c29bbcad278 changeset: 95947:5c29bbcad278 branch: 2.7 parent: 95944:240fc7d2526b user: Steve Dower date: Sun May 10 19:06:07 2015 -0700 summary: Adds UUIDs for 2.7.10 files: Tools/msi/uuids.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Tools/msi/uuids.py b/Tools/msi/uuids.py --- a/Tools/msi/uuids.py +++ b/Tools/msi/uuids.py @@ -68,4 +68,6 @@ '2.7.8150':'{61121B12-88BD-4261-A6EE-AB32610A56DD}', # 2.7.8 '2.7.9121':'{AAB1E8FF-6D00-4409-8F13-BE365AB92FFE}', # 2.7.9rc1 '2.7.9150':'{79F081BF-7454-43DB-BD8F-9EE596813232}', # 2.7.9 + '2.7.10121':'{872BE558-2E5F-4E9C-A42D-8561FA43811C}', # 2.7.10rc1 + '2.7.10150':'{E2B51919-207A-43EB-AE78-733F9C6797C2}', # 2.7.10 } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon May 11 10:40:09 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 11 May 2015 08:40:09 +0000 Subject: [Python-checkins] Daily reference leaks (a290885ec0da): sum=3 Message-ID: <20150511084009.8149.1818@psf.io> results for a290885ec0da on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghvaAxY', '--timeout', '7200'] From python-checkins at python.org Mon May 11 17:15:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 11 May 2015 15:15:28 +0000 Subject: [Python-checkins] =?utf-8?q?release=3A_welcome_to_a_world_with_tw?= =?utf-8?q?o_digit_patchlevel_versions?= Message-ID: <20150511151528.25441.78877@psf.io> https://hg.python.org/release/rev/1bff57e982e6 changeset: 94:1bff57e982e6 user: Benjamin Peterson date: Mon May 11 11:15:26 2015 -0400 summary: welcome to a world with two digit patchlevel versions files: add-to-pydotorg.py | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-) diff --git a/add-to-pydotorg.py b/add-to-pydotorg.py --- a/add-to-pydotorg.py +++ b/add-to-pydotorg.py @@ -44,6 +44,8 @@ ftp_root = '/srv/www.python.org/ftp/python/' download_root = 'https://www.python.org/ftp/python/' +tag_cre = re.compile(r'(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:([ab]|rc)(\d+))?$') + headers = {'Authorization': 'ApiKey %s' % auth_info, 'Content-Type': 'application/json'} rx = re.compile @@ -70,20 +72,24 @@ def slug_for(release): return release[0] + '-' + release[2] + '-' + release[4] + \ - ('-' + release[5:] if release[5:] else '') + ('-' + release[len(base_version(release)):] if release[len(base_version(release)):] else '') def sigfile_for(release, rfile): return download_root + '%s/%s.asc' % (release, rfile) def md5sum_for(release, rfile): - return hashlib.md5(open(ftp_root + release[:5] + '/' + rfile, 'rb').read()).hexdigest() + return hashlib.md5(open(ftp_root + base_version(release) + '/' + rfile, 'rb').read()).hexdigest() def filesize_for(release, rfile): - return path.getsize(ftp_root + release[:5] + '/' + rfile) + return path.getsize(ftp_root + base_version(release) + '/' + rfile) def make_slug(text): return re.sub('[^a-zA-Z0-9_-]', '', text.replace(' ', '-')) +def base_version(release): + m = tag_cre.match(release) + return ".".join(m.groups()[:3]) + def build_release_dict(release, reldate, is_latest, page_pk): """Return a dictionary with all needed fields for a Release object.""" return dict( @@ -107,7 +113,7 @@ release = '/api/v1/downloads/release/%s/' % rel_pk, description = add_desc, is_source = os_pk == 3, - url = download_root + '%s/%s' % (release[:5], rfile), + url = download_root + '%s/%s' % (base_version(release), rfile), md5_sum = md5sum_for(release, rfile), filesize = filesize_for(release, rfile), download_button = 'tar.xz' in rfile or @@ -115,13 +121,13 @@ 'macosx10.6.pkg' in rfile or ('.msi' in rfile and not 'amd64' in rfile), ) - if os.path.exists(ftp_root + "%s/%s.asc" % (release[:5], rfile)): - d["gpg_signature_file"] = sigfile_for(release[:5], rfile) + if os.path.exists(ftp_root + "%s/%s.asc" % (base_version(release), rfile)): + d["gpg_signature_file"] = sigfile_for(base_version(release), rfile) return d def list_files(release): """List all of the release's download files.""" - reldir = release[:5] + reldir = base_version(release) for rfile in os.listdir(path.join(ftp_root, reldir)): if not path.isfile(path.join(ftp_root, reldir, rfile)): continue -- Repository URL: https://hg.python.org/release From python-checkins at python.org Mon May 11 18:12:05 2015 From: python-checkins at python.org (r.david.murray) Date: Mon, 11 May 2015 16:12:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2321795=3A_advertise_8BIT?= =?utf-8?q?MIME_if_decode=5Fdata_is_False=2E?= Message-ID: <20150511161204.11932.78967@psf.io> https://hg.python.org/cpython/rev/e34ed02738bf changeset: 95948:e34ed02738bf parent: 95946:a290885ec0da user: R David Murray date: Mon May 11 12:11:40 2015 -0400 summary: #21795: advertise 8BITMIME if decode_data is False. Patch by Milan Oberkirch, with a few updates. This changeset also tweaks the smtpd and whatsnew docs for smtpd into what should be the final form for the 3.5 release. files: Doc/library/smtpd.rst | 58 +++++++----- Doc/whatsnew/3.5.rst | 22 +++- Lib/smtpd.py | 104 ++++++++++++---------- Lib/test/test_smtpd.py | 129 ++++++++++++++++++++++++---- Misc/NEWS | 3 + 5 files changed, 219 insertions(+), 97 deletions(-) diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst --- a/Doc/library/smtpd.rst +++ b/Doc/library/smtpd.rst @@ -40,20 +40,27 @@ accepted in a ``DATA`` command. A value of ``None`` or ``0`` means no limit. + *map* is the socket map to use for connections (an initially empty + dictionary is a suitable value). If not specified the :mod:`asyncore` + global socket map is used. + *enable_SMTPUTF8* determins whether the ``SMTPUTF8`` extension (as defined - in :RFC:`6531`) should be enabled. The default is ``False``. If - *enable_SMTPUTF* is set to ``True``, the :meth:`process_smtputf8_message` - method must be defined. A :exc:`ValueError` is raised if both - *enable_SMTPUTF8* and *decode_data* are set to ``True`` at the same time. - - A dictionary can be specified in *map* to avoid using a global socket map. + in :RFC:`6531`) should be enabled. The default is ``False``. If set to + ``True``, *decode_data* must be ``False`` (otherwise an error is raised). + When ``True``, ``SMTPUTF8`` is accepted as a parameter to the ``MAIL`` + command and when present is passed to :meth:`process_message` in the + ``kwargs['mail_options']`` list. *decode_data* specifies whether the data portion of the SMTP transaction should be decoded using UTF-8. The default is ``True`` for backward - compatibility reasons, but will change to ``False`` in Python 3.6. Specify - the keyword value explicitly to avoid the :exc:`DeprecationWarning`. + compatibility reasons, but will change to ``False`` in Python 3.6; specify + the keyword value explicitly to avoid the :exc:`DeprecationWarning`. When + *decode_data* is set to ``False`` the server advertises the ``8BITMIME`` + extension (:rfc:`6152`), accepts the ``BODY=8BITMIME`` parameter to + the ``MAIL`` command, and when present passes it to :meth:`process_message` + in the ``kwargs['mail_options']`` list. - .. method:: process_message(peer, mailfrom, rcpttos, data) + .. method:: process_message(peer, mailfrom, rcpttos, data, **kwargs) Raise a :exc:`NotImplementedError` exception. Override this in subclasses to do something useful with this message. Whatever was passed in the @@ -67,34 +74,39 @@ argument will be a unicode string. If it is set to ``False``, it will be a bytes object. + *kwargs* is a dictionary containing additional information. It is empty + unless at least one of ``decode_data=False`` or ``enable_SMTPUTF8=True`` + was given as an init parameter, in which case it contains the following + keys: + + *mail_options*: + a list of all received parameters to the ``MAIL`` + command (the elements are uppercase strings; example: + ``['BODY=8BITMIME', 'SMTPUTF8']``). + + *rcpt_options*: + same as *mail_options* but for the ``RCPT`` command. + Currently no ``RCPT TO`` options are supported, so for now + this will always be an empty list. + Return ``None`` to request a normal ``250 Ok`` response; otherwise return the desired response string in :RFC:`5321` format. - .. method:: process_smtputf8_message(peer, mailfrom, rcpttos, data) - - Raise a :exc:`NotImplementedError` exception. Override this in - subclasses to do something useful with messages when *enable_SMTPUTF8* - has been set to ``True`` and the SMTP client requested ``SMTPUTF8``, - since this method is called rather than :meth:`process_message` when the - client actively requests ``SMTPUTF8``. The *data* argument will always - be a bytes object, and any non-``None`` return value should conform to - :rfc:`6531`; otherwise, the API is the same as for - :meth:`process_message`. - .. attribute:: channel_class Override this in subclasses to use a custom :class:`SMTPChannel` for managing SMTP clients. - .. versionchanged:: 3.4 - The *map* argument was added. + .. versionadded:: 3.4 + The *map* constructor argument. .. versionchanged:: 3.5 *localaddr* and *remoteaddr* may now contain IPv6 addresses. .. versionadded:: 3.5 the *decode_data* and *enable_SMTPUTF8* constructor arguments, and the - :meth:`process_smtputf8_message` method. + *kwargs* argument to :meth:`process_message` when one or more of these is + specified. DebuggingServer Objects diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -468,16 +468,28 @@ transaction is decoded using the ``utf-8`` codec or is instead provided to :meth:`~smtpd.SMTPServer.process_message` as a byte string. The default is ``True`` for backward compatibility reasons, but will change to ``False`` - in Python 3.6. (Contributed by Maciej Szulik in :issue:`19662`.) + in Python 3.6. If *decode_data* is set to ``False``, the + :meth:`~smtpd.SMTPServer.process_message` method must be prepared to accept + keyword arguments. (Contributed by Maciej Szulik in :issue:`19662`.) + +* :class:`~smtpd.SMTPServer` now advertises the ``8BITMIME`` extension + (:rfc:`6152`) if if *decode_data* has been set ``True``. If the client + specifies ``BODY=8BITMIME`` on the ``MAIL`` command, it is passed to + :meth:`~smtpd.SMTPServer.process_message` via the ``mail_options`` keyword. + (Contributed by Milan Oberkirch and R. David Murray in :issue:`21795`.) + +* :class:`~smtpd.SMTPServer` now supports the ``SMTPUTF8`` extension + (:rfc:`6531`: Internationalized Email). If the client specified ``SMTPUTF8 + BODY=8BITMIME`` on the ``MAIL`` command, they are passed to + :meth:`~smtpd.SMTPServer.process_message` via the ``mail_options`` keyword. + It is the responsibility of the :meth:`~smtpd.SMTPServer.process_message` + method to correctly handle the ``SMTPUTF8`` data. (Contributed by Milan + Oberkirch in :issue:`21725`.) * It is now possible to provide, directly or via name resolution, IPv6 addresses in the :class:`~smtpd.SMTPServer` constructor, and have it successfully connect. (Contributed by Milan Oberkirch in :issue:`14758`.) -* :mod:`~smtpd.SMTPServer` now supports :rfc:`6531` via the *enable_SMTPUTF8* - constructor argument and a user-provided - :meth:`~smtpd.SMTPServer.process_smtputf8_message` method. - smtplib ------- diff --git a/Lib/smtpd.py b/Lib/smtpd.py --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -381,10 +381,13 @@ data.append(text) self.received_data = self._newline.join(data) args = (self.peer, self.mailfrom, self.rcpttos, self.received_data) - if self.require_SMTPUTF8: - status = self.smtp_server.process_smtputf8_message(*args) - else: - status = self.smtp_server.process_message(*args) + kwargs = {} + if not self._decode_data: + kwargs = { + 'mail_options': self.mail_options, + 'rcpt_options': self.rcpt_options, + } + status = self.smtp_server.process_message(*args, **kwargs) self._set_post_data_state() if not status: self.push('250 OK') @@ -419,8 +422,9 @@ if self.data_size_limit: self.push('250-SIZE %s' % self.data_size_limit) self.command_size_limits['MAIL'] += 26 + if not self._decode_data: + self.push('250-8BITMIME') if self.enable_SMTPUTF8: - self.push('250-8BITMIME') self.push('250-SMTPUTF8') self.command_size_limits['MAIL'] += 10 self.push('250 HELP') @@ -454,11 +458,15 @@ return address.addr_spec, rest def _getparams(self, params): - # Return any parameters that appear to be syntactically valid according - # to RFC 1869, ignore all others. (Postel rule: accept what we can.) - params = [param.split('=', 1) if '=' in param else (param, True) - for param in params.split()] - return {k: v for k, v in params if k.isalnum()} + # Return params as dictionary. Return None if not all parameters + # appear to be syntactically valid according to RFC 1869. + result = {} + for param in params: + param, eq, value = param.partition('=') + if not param.isalnum() or eq and not value: + return None + result[param] = value if eq else True + return result def smtp_HELP(self, arg): if arg: @@ -508,7 +516,7 @@ def smtp_MAIL(self, arg): if not self.seen_greeting: - self.push('503 Error: send HELO first'); + self.push('503 Error: send HELO first') return print('===> MAIL', arg, file=DEBUGSTREAM) syntaxerr = '501 Syntax: MAIL FROM:
' @@ -528,18 +536,23 @@ if self.mailfrom: self.push('503 Error: nested MAIL command') return - params = self._getparams(params.upper()) + self.mail_options = params.upper().split() + params = self._getparams(self.mail_options) if params is None: self.push(syntaxerr) return - body = params.pop('BODY', '7BIT') - if self.enable_SMTPUTF8 and params.pop('SMTPUTF8', False): - if body != '8BITMIME': - self.push('501 Syntax: MAIL FROM:
' - ' [BODY=8BITMIME SMTPUTF8]') + if not self._decode_data: + body = params.pop('BODY', '7BIT') + if body not in ['7BIT', '8BITMIME']: + self.push('501 Error: BODY can only be one of 7BIT, 8BITMIME') return - else: + if self.enable_SMTPUTF8: + smtputf8 = params.pop('SMTPUTF8', False) + if smtputf8 is True: self.require_SMTPUTF8 = True + elif smtputf8 is not False: + self.push('501 Error: SMTPUTF8 takes no arguments') + return size = params.pop('SIZE', None) if size: if not size.isdigit(): @@ -574,16 +587,16 @@ if not address: self.push(syntaxerr) return - if params: - if self.extended_smtp: - params = self._getparams(params.upper()) - if params is None: - self.push(syntaxerr) - return - else: - self.push(syntaxerr) - return - if params and len(params.keys()) > 0: + if not self.extended_smtp and params: + self.push(syntaxerr) + return + self.rcpt_options = params.upper().split() + params = self._getparams(self.rcpt_options) + if params is None: + self.push(syntaxerr) + return + # XXX currently there are no options we recognize. + if len(params.keys()) > 0: self.push('555 RCPT TO parameters not recognized or not implemented') return self.rcpttos.append(address) @@ -667,7 +680,7 @@ self._decode_data) # API for "doing something useful with the message" - def process_message(self, peer, mailfrom, rcpttos, data): + def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): """Override this abstract method to handle messages from the client. peer is a tuple containing (ipaddr, port) of the client that made the @@ -685,6 +698,14 @@ containing a `.' followed by other text has had the leading dot removed. + kwargs is a dictionary containing additional information. It is empty + unless decode_data=False or enable_SMTPUTF8=True was given as init + parameter, in which case ut will contain the following keys: + 'mail_options': list of parameters to the mail command. All + elements are uppercase strings. Example: + ['BODY=8BITMIME', 'SMTPUTF8']. + 'rcpt_options': same, for the rcpt command. + This function should return None for a normal `250 Ok' response; otherwise, it should return the desired response string in RFC 821 format. @@ -692,19 +713,6 @@ """ raise NotImplementedError - # API for processing messeges needing Unicode support (RFC 6531, RFC 6532). - def process_smtputf8_message(self, peer, mailfrom, rcpttos, data): - """Same as ``process_message`` but for messages for which the client - has sent the SMTPUTF8 parameter with the MAIL command (see the - enable_SMTPUTF8 parameter of the constructor). - - This function should return None for a normal `250 Ok' response; - otherwise, it should return the desired response string in RFC 6531 - format. - - """ - raise NotImplementedError - class DebuggingServer(SMTPServer): @@ -725,13 +733,13 @@ line = repr(line) print(line) - def process_message(self, peer, mailfrom, rcpttos, data): + def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): print('---------- MESSAGE FOLLOWS ----------') - self._print_message_content(peer, data) - print('------------ END MESSAGE ------------') - - def process_smtputf8_message(self, peer, mailfrom, rcpttos, data): - print('----- SMTPUTF8 MESSAGE FOLLOWS ------') + if kwargs: + if kwargs.get('mail_options'): + print('mail options: %s' % kwargs['mail_options']) + if kwargs.get('rcpt_options'): + print('rcpt options: %s\n' % kwargs['rcpt_options']) self._print_message_content(peer, data) print('------------ END MESSAGE ------------') diff --git a/Lib/test/test_smtpd.py b/Lib/test/test_smtpd.py --- a/Lib/test/test_smtpd.py +++ b/Lib/test/test_smtpd.py @@ -16,13 +16,12 @@ else: self.return_status = b'return status' - def process_message(self, peer, mailfrom, rcpttos, data): + def process_message(self, peer, mailfrom, rcpttos, data, **kw): self.messages.append((peer, mailfrom, rcpttos, data)) if data == self.return_status: return '250 Okish' - - def process_smtputf8_message(self, *args, **kwargs): - return '250 SMTPUTF8 message okish' + if 'mail_options' in kw and 'SMTPUTF8' in kw['mail_options']: + return '250 SMTPUTF8 message okish' class DummyDispatcherBroken(Exception): @@ -54,22 +53,6 @@ write_line(b'DATA') self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n') - def test_process_smtputf8_message_unimplemented(self): - server = smtpd.SMTPServer((support.HOST, 0), ('b', 0), - enable_SMTPUTF8=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) - - def write_line(line): - channel.socket.queue_recv(line) - channel.handle_read() - - write_line(b'EHLO example') - write_line(b'MAIL From: BODY=8BITMIME SMTPUTF8') - write_line(b'RCPT To: ') - write_line(b'DATA') - self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n') - def test_decode_data_default_warns(self): with self.assertWarns(DeprecationWarning): smtpd.SMTPServer((support.HOST, 0), ('b', 0)) @@ -168,7 +151,8 @@ enable_SMTPUTF8=True) stdout = s.getvalue() self.assertEqual(stdout, textwrap.dedent("""\ - ----- SMTPUTF8 MESSAGE FOLLOWS ------ + ---------- MESSAGE FOLLOWS ---------- + mail options: ['BODY=8BITMIME', 'SMTPUTF8'] b'From: test' b'X-Peer: peer-address' b'' @@ -201,6 +185,109 @@ self.assertEqual(server.socket.family, socket.AF_INET) +class TestRcptOptionParsing(unittest.TestCase): + error_response = (b'555 RCPT TO parameters not recognized or not ' + b'implemented\r\n') + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, channel, line): + channel.socket.queue_recv(line) + channel.handle_read() + + def test_params_rejected(self): + server = DummyServer((support.HOST, 0), ('b', 0), decode_data=False) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=False) + self.write_line(channel, b'EHLO example') + self.write_line(channel, b'MAIL from: size=20') + self.write_line(channel, b'RCPT to: foo=bar') + self.assertEqual(channel.socket.last, self.error_response) + + def test_nothing_accepted(self): + server = DummyServer((support.HOST, 0), ('b', 0), decode_data=False) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=False) + self.write_line(channel, b'EHLO example') + self.write_line(channel, b'MAIL from: size=20') + self.write_line(channel, b'RCPT to: ') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + +class TestMailOptionParsing(unittest.TestCase): + error_response = (b'555 MAIL FROM parameters not recognized or not ' + b'implemented\r\n') + + def setUp(self): + smtpd.socket = asyncore.socket = mock_socket + self.old_debugstream = smtpd.DEBUGSTREAM + self.debug = smtpd.DEBUGSTREAM = io.StringIO() + + def tearDown(self): + asyncore.close_all() + asyncore.socket = smtpd.socket = socket + smtpd.DEBUGSTREAM = self.old_debugstream + + def write_line(self, channel, line): + channel.socket.queue_recv(line) + channel.handle_read() + + def test_with_decode_data_true(self): + server = DummyServer((support.HOST, 0), ('b', 0), decode_data=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) + self.write_line(channel, b'EHLO example') + for line in [ + b'MAIL from: size=20 SMTPUTF8', + b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', + b'MAIL from: size=20 BODY=UNKNOWN', + b'MAIL from: size=20 body=8bitmime', + ]: + self.write_line(channel, line) + self.assertEqual(channel.socket.last, self.error_response) + self.write_line(channel, b'MAIL from: size=20') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + def test_with_decode_data_false(self): + server = DummyServer((support.HOST, 0), ('b', 0), decode_data=False) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, decode_data=False) + self.write_line(channel, b'EHLO example') + for line in [ + b'MAIL from: size=20 SMTPUTF8', + b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', + ]: + self.write_line(channel, line) + self.assertEqual(channel.socket.last, self.error_response) + self.write_line( + channel, + b'MAIL from: size=20 SMTPUTF8 BODY=UNKNOWN') + self.assertEqual( + channel.socket.last, + b'501 Error: BODY can only be one of 7BIT, 8BITMIME\r\n') + self.write_line( + channel, b'MAIL from: size=20 body=8bitmime') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + def test_with_enable_smtputf8_true(self): + server = DummyServer((support.HOST, 0), ('b', 0), enable_SMTPUTF8=True) + conn, addr = server.accept() + channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) + self.write_line(channel, b'EHLO example') + self.write_line( + channel, + b'MAIL from: size=20 body=8bitmime smtputf8') + self.assertEqual(channel.socket.last, b'250 OK\r\n') + + class SMTPDChannelTest(unittest.TestCase): def setUp(self): smtpd.socket = asyncore.socket = mock_socket diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,9 @@ Library ------- +- Issue #21795: smtpd now supports the 8BITMIME extension whenever + the new *decode_data* constructor argument is set to False. + - Issue #21800: imaplib now supports RFC 5161 (enable), RFC 6855 (utf8/internationalized email) and automatically encodes non-ASCII usernames and passwords to UTF8. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 19:19:13 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 May 2015 17:19:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324155=3A_Optimize?= =?utf-8?q?_heapify_for_better_cache_utililzation=2E?= Message-ID: <20150511171912.76616.52020@psf.io> https://hg.python.org/cpython/rev/db87591fce01 changeset: 95949:db87591fce01 user: Raymond Hettinger date: Mon May 11 10:19:03 2015 -0700 summary: Issue #24155: Optimize heapify for better cache utililzation. files: Misc/NEWS | 3 + Modules/_heapqmodule.c | 72 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ - Issue #21795: smtpd now supports the 8BITMIME extension whenever the new *decode_data* constructor argument is set to False. +- Issue #24155: optimize heapq.heapify() for better cache performance + when heapifying large lists. + - Issue #21800: imaplib now supports RFC 5161 (enable), RFC 6855 (utf8/internationalized email) and automatically encodes non-ASCII usernames and passwords to UTF8. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -250,6 +250,71 @@ from the heap. The combined action runs more efficiently than\n\ heappush() followed by a separate call to heappop()."); +static Py_ssize_t +keep_top_bit(Py_ssize_t n) +{ + int i = 0; + + while (n > 1) { + i += 1; + n >>= 1; + } + return n << i; +} + +/* Cache friendly version of heapify() + ----------------------------------- + + Build-up a heap in O(n) time by performing siftup() operations + on nodes whose children are already heaps. + + The simplest way is to sift the nodes in reverse order from + n//2-1 to 0 inclusive. The downside is that children may be + out of cache by the time their parent is reached. + + A better way is to not wait for the children to go out of cache. + Once a sibling pair of child nodes have been sifted, immediately + sift their parent node (while the children are still in cache). + + Both ways build child heaps before their parents, so both ways + do the exact same number of comparisons and produce exactly + the same heap. The only difference is that the traversal + order is optimized for cache efficiency. +*/ + +static PyObject * +cache_friendly_heapify(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) +{ + Py_ssize_t i, j, m, mhalf, leftmost; + + m = PyList_GET_SIZE(heap) >> 1; /* index of first childless node */ + leftmost = keep_top_bit(m + 1) - 1; /* leftmost node in row of m */ + mhalf = m >> 1; /* parent of first childless node */ + + for (i = leftmost - 1 ; i >= mhalf ; i--) { + j = i; + while (1) { + if (siftup_func((PyListObject *)heap, j)) + return NULL; + if (!(j & 1)) + break; + j >>= 1; + } + } + + for (i = m - 1 ; i >= leftmost ; i--) { + j = i; + while (1) { + if (siftup_func((PyListObject *)heap, j)) + return NULL; + if (!(j & 1)) + break; + j >>= 1; + } + } + Py_RETURN_NONE; +} + static PyObject * heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) { @@ -260,7 +325,14 @@ return NULL; } + /* For heaps likely to be bigger than L1 cache, we use the cache + friendly heapify function. For smaller heaps that fit entirely + in cache, we prefer the simpler algorithm with less branching. + */ n = PyList_GET_SIZE(heap); + if (n > 10000) + return cache_friendly_heapify(heap, siftup_func); + /* Transform bottom-up. The largest index there's any point to looking at is the largest with a child index in-range, so must have 2*i + 1 < n, or i < (n-1)/2. If n is even = 2*j, this is -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 19:22:32 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 May 2015 17:22:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTYx?= =?utf-8?q?=3A__Document_that_PyIter=5FCheck=28=29_returns_false_positives?= =?utf-8?q?_for?= Message-ID: <20150511172231.25449.55369@psf.io> https://hg.python.org/cpython/rev/0f7795edca65 changeset: 95950:0f7795edca65 branch: 2.7 parent: 95947:5c29bbcad278 user: Raymond Hettinger date: Mon May 11 10:22:20 2015 -0700 summary: Issue #24161: Document that PyIter_Check() returns false positives for old-style instances. files: Doc/c-api/iter.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -14,6 +14,10 @@ Return true if the object *o* supports the iterator protocol. + This function can return a false positive in the case of old-style + classes because those classes always define a :c:member:`tp_iternext` + slot with logic that either invokes a :meth:`next` method or raises + a :exc:`TypeError`. .. c:function:: PyObject* PyIter_Next(PyObject *o) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 19:33:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 11 May 2015 17:33:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_stylistic_clean-up?= =?utf-8?q?=2E?= Message-ID: <20150511173303.76604.14702@psf.io> https://hg.python.org/cpython/rev/4bbc8f70a162 changeset: 95951:4bbc8f70a162 parent: 95949:db87591fce01 user: Raymond Hettinger date: Mon May 11 10:32:57 2015 -0700 summary: Minor stylistic clean-up. files: Modules/_heapqmodule.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -107,10 +107,10 @@ return NULL; } - if (PyList_Append(heap, item) == -1) + if (PyList_Append(heap, item)) return NULL; - if (siftdown((PyListObject *)heap, 0, PyList_GET_SIZE(heap)-1) == -1) + if (siftdown((PyListObject *)heap, 0, PyList_GET_SIZE(heap)-1)) return NULL; Py_RETURN_NONE; } @@ -148,7 +148,7 @@ return lastelt; returnitem = PyList_GET_ITEM(heap, 0); PyList_SET_ITEM(heap, 0, lastelt); - if (siftup_func((PyListObject *)heap, 0) == -1) { + if (siftup_func((PyListObject *)heap, 0)) { Py_DECREF(returnitem); return NULL; } @@ -185,7 +185,7 @@ returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); - if (siftup_func((PyListObject *)heap, 0) == -1) { + if (siftup_func((PyListObject *)heap, 0)) { Py_DECREF(returnitem); return NULL; } @@ -238,7 +238,7 @@ returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); - if (siftup((PyListObject *)heap, 0) == -1) { + if (siftup((PyListObject *)heap, 0)) { Py_DECREF(returnitem); return NULL; } @@ -341,7 +341,7 @@ and that's again n//2-1. */ for (i=n/2-1 ; i>=0 ; i--) - if(siftup_func((PyListObject *)heap, i) == -1) + if(siftup_func((PyListObject *)heap, i)) return NULL; Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 19:52:55 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 17:52:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Sync_with_githu?= =?utf-8?q?b_repo?= Message-ID: <20150511175255.11944.49421@psf.io> https://hg.python.org/cpython/rev/28ee9c45e665 changeset: 95952:28ee9c45e665 user: Yury Selivanov date: Mon May 11 13:48:16 2015 -0400 summary: asyncio: Sync with github repo files: Lib/asyncio/base_events.py | 44 +++++++-- Lib/asyncio/events.py | 10 ++- Lib/asyncio/queues.py | 7 +- Lib/selectors.py | 49 +++++----- Lib/test/test_asyncio/test_base_events.py | 36 ++++++++ 5 files changed, 110 insertions(+), 36 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -197,6 +197,7 @@ # exceed this duration in seconds, the slow callback/task is logged. self.slow_callback_duration = 0.1 self._current_handle = None + self._task_factory = None def __repr__(self): return ('<%s running=%s closed=%s debug=%s>' @@ -209,11 +210,32 @@ Return a task object. """ self._check_closed() - task = tasks.Task(coro, loop=self) - if task._source_traceback: - del task._source_traceback[-1] + if self._task_factory is None: + task = tasks.Task(coro, loop=self) + if task._source_traceback: + del task._source_traceback[-1] + else: + task = self._task_factory(self, coro) return task + def set_task_factory(self, factory): + """Set a task factory that will be used by loop.create_task(). + + If factory is None the default task factory will be set. + + If factory is a callable, it should have a signature matching + '(loop, coro)', where 'loop' will be a reference to the active + event loop, 'coro' will be a coroutine object. The callable + must return a Future. + """ + if factory is not None and not callable(factory): + raise TypeError('task factory must be a callable or None') + self._task_factory = factory + + def get_task_factory(self): + """Return a task factory, or None if the default one is in use.""" + return self._task_factory + def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): """Create socket transport.""" @@ -465,25 +487,25 @@ self._write_to_self() return handle - def run_in_executor(self, executor, callback, *args): - if (coroutines.iscoroutine(callback) - or coroutines.iscoroutinefunction(callback)): + def run_in_executor(self, executor, func, *args): + if (coroutines.iscoroutine(func) + or coroutines.iscoroutinefunction(func)): raise TypeError("coroutines cannot be used with run_in_executor()") self._check_closed() - if isinstance(callback, events.Handle): + if isinstance(func, events.Handle): assert not args - assert not isinstance(callback, events.TimerHandle) - if callback._cancelled: + assert not isinstance(func, events.TimerHandle) + if func._cancelled: f = futures.Future(loop=self) f.set_result(None) return f - callback, args = callback._callback, callback._args + func, args = func._callback, func._args if executor is None: executor = self._default_executor if executor is None: executor = concurrent.futures.ThreadPoolExecutor(_MAX_WORKERS) self._default_executor = executor - return futures.wrap_future(executor.submit(callback, *args), loop=self) + return futures.wrap_future(executor.submit(func, *args), loop=self) def set_default_executor(self, executor): self._default_executor = executor diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -277,7 +277,7 @@ def call_soon_threadsafe(self, callback, *args): raise NotImplementedError - def run_in_executor(self, executor, callback, *args): + def run_in_executor(self, executor, func, *args): raise NotImplementedError def set_default_executor(self, executor): @@ -438,6 +438,14 @@ def remove_signal_handler(self, sig): raise NotImplementedError + # Task factory. + + def set_task_factory(self, factory): + raise NotImplementedError + + def get_task_factory(self): + raise NotImplementedError + # Error handlers. def set_exception_handler(self, handler): diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -1,6 +1,7 @@ """Queues""" -__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty'] +__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty', + 'JoinableQueue'] import collections import heapq @@ -286,3 +287,7 @@ def _get(self): return self._queue.pop() + + +JoinableQueue = Queue +"""Deprecated alias for Queue.""" diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -310,7 +310,10 @@ def select(self, timeout=None): timeout = None if timeout is None else max(timeout, 0) ready = [] - r, w, _ = self._select(self._readers, self._writers, [], timeout) + try: + r, w, _ = self._select(self._readers, self._writers, [], timeout) + except InterruptedError: + return ready r = set(r) w = set(w) for fd in r | w: @@ -359,10 +362,11 @@ # poll() has a resolution of 1 millisecond, round away from # zero to wait *at least* timeout seconds. timeout = math.ceil(timeout * 1e3) - - fd_event_list = self._poll.poll(timeout) - ready = [] + try: + fd_event_list = self._poll.poll(timeout) + except InterruptedError: + return ready for fd, event in fd_event_list: events = 0 if event & ~select.POLLIN: @@ -423,9 +427,11 @@ # FD is registered. max_ev = max(len(self._fd_to_key), 1) - fd_event_list = self._epoll.poll(timeout, max_ev) - ready = [] + try: + fd_event_list = self._epoll.poll(timeout, max_ev) + except InterruptedError: + return ready for fd, event in fd_event_list: events = 0 if event & ~select.EPOLLIN: @@ -439,10 +445,8 @@ return ready def close(self): - try: - self._epoll.close() - finally: - super().close() + self._epoll.close() + super().close() if hasattr(select, 'devpoll'): @@ -481,10 +485,11 @@ # devpoll() has a resolution of 1 millisecond, round away from # zero to wait *at least* timeout seconds. timeout = math.ceil(timeout * 1e3) - - fd_event_list = self._devpoll.poll(timeout) - ready = [] + try: + fd_event_list = self._devpoll.poll(timeout) + except InterruptedError: + return ready for fd, event in fd_event_list: events = 0 if event & ~select.POLLIN: @@ -498,10 +503,8 @@ return ready def close(self): - try: - self._devpoll.close() - finally: - super().close() + self._devpoll.close() + super().close() if hasattr(select, 'kqueue'): @@ -552,9 +555,11 @@ def select(self, timeout=None): timeout = None if timeout is None else max(timeout, 0) max_ev = len(self._fd_to_key) - kev_list = self._kqueue.control(None, max_ev, timeout) - ready = [] + try: + kev_list = self._kqueue.control(None, max_ev, timeout) + except InterruptedError: + return ready for kev in kev_list: fd = kev.ident flag = kev.filter @@ -570,10 +575,8 @@ return ready def close(self): - try: - self._kqueue.close() - finally: - super().close() + self._kqueue.close() + super().close() # Choose the best implementation, roughly: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -623,6 +623,42 @@ self.assertIs(type(_context['context']['exception']), ZeroDivisionError) + def test_set_task_factory_invalid(self): + with self.assertRaisesRegex( + TypeError, 'task factory must be a callable or None'): + + self.loop.set_task_factory(1) + + self.assertIsNone(self.loop.get_task_factory()) + + def test_set_task_factory(self): + self.loop._process_events = mock.Mock() + + class MyTask(asyncio.Task): + pass + + @asyncio.coroutine + def coro(): + pass + + factory = lambda loop, coro: MyTask(coro, loop=loop) + + self.assertIsNone(self.loop.get_task_factory()) + self.loop.set_task_factory(factory) + self.assertIs(self.loop.get_task_factory(), factory) + + task = self.loop.create_task(coro()) + self.assertTrue(isinstance(task, MyTask)) + self.loop.run_until_complete(task) + + self.loop.set_task_factory(None) + self.assertIsNone(self.loop.get_task_factory()) + + task = self.loop.create_task(coro()) + self.assertTrue(isinstance(task, asyncio.Task)) + self.assertFalse(isinstance(task, MyTask)) + self.loop.run_until_complete(task) + def test_env_var_debug(self): code = '\n'.join(( 'import asyncio', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:42:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:42:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=28asyncio=29?= Message-ID: <20150511184250.98669.96003@psf.io> https://hg.python.org/cpython/rev/11d7aa8c2790 changeset: 95954:11d7aa8c2790 parent: 95952:28ee9c45e665 parent: 95953:a983d63e3321 user: Yury Selivanov date: Mon May 11 14:40:56 2015 -0400 summary: Merge 3.4 (asyncio) files: Lib/test/test_asyncio/test_base_events.py | 9 +++++++-- Lib/test/test_asyncio/test_tasks.py | 9 +++++++-- Misc/NEWS | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -16,10 +16,15 @@ from asyncio import test_utils try: from test import support +except ImportError: + from asyncio import test_support as support +try: from test.support.script_helper import assert_python_ok except ImportError: - from asyncio import test_support as support - from asyncio.test_support import assert_python_ok + try: + from test.script_helper import assert_python_ok + except ImportError: + from asyncio.test_support import assert_python_ok MOCK_ANY = mock.ANY diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -15,10 +15,15 @@ from asyncio import test_utils try: from test import support +except ImportError: + from asyncio import test_support as support +try: from test.support.script_helper import assert_python_ok except ImportError: - from asyncio import test_support as support - from asyncio.test_support import assert_python_ok + try: + from test.script_helper import assert_python_ok + except ImportError: + from asyncio.test_support import assert_python_ok PY34 = (sys.version_info >= (3, 4)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -154,6 +154,8 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. +- asyncio: New event loop APIs: set_task_factory() and get_task_factory() + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:42:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:42:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Drop_JoinableQu?= =?utf-8?q?eue_from_3=2E5?= Message-ID: <20150511184251.84482.61049@psf.io> https://hg.python.org/cpython/rev/17bd326e2e2f changeset: 95955:17bd326e2e2f user: Yury Selivanov date: Mon May 11 14:42:43 2015 -0400 summary: asyncio: Drop JoinableQueue from 3.5 files: Lib/asyncio/queues.py | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -1,7 +1,6 @@ """Queues""" -__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty', - 'JoinableQueue'] +__all__ = ['Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty'] import collections import heapq @@ -287,7 +286,3 @@ def _get(self): return self._queue.pop() - - -JoinableQueue = Queue -"""Deprecated alias for Queue.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:42:50 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:42:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Sync_asyncio_c?= =?utf-8?q?hanges_from_the_main_repo=2E?= Message-ID: <20150511184250.14370.29346@psf.io> https://hg.python.org/cpython/rev/a983d63e3321 changeset: 95953:a983d63e3321 branch: 3.4 parent: 95943:8eddc3c169df user: Yury Selivanov date: Mon May 11 14:23:38 2015 -0400 summary: Sync asyncio changes from the main repo. files: Lib/asyncio/base_events.py | 44 ++++++++-- Lib/asyncio/events.py | 10 ++- Lib/test/test_asyncio/test_base_events.py | 45 ++++++++++- Lib/test/test_asyncio/test_tasks.py | 9 +- Misc/NEWS | 2 + 5 files changed, 94 insertions(+), 16 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -197,6 +197,7 @@ # exceed this duration in seconds, the slow callback/task is logged. self.slow_callback_duration = 0.1 self._current_handle = None + self._task_factory = None def __repr__(self): return ('<%s running=%s closed=%s debug=%s>' @@ -209,11 +210,32 @@ Return a task object. """ self._check_closed() - task = tasks.Task(coro, loop=self) - if task._source_traceback: - del task._source_traceback[-1] + if self._task_factory is None: + task = tasks.Task(coro, loop=self) + if task._source_traceback: + del task._source_traceback[-1] + else: + task = self._task_factory(self, coro) return task + def set_task_factory(self, factory): + """Set a task factory that will be used by loop.create_task(). + + If factory is None the default task factory will be set. + + If factory is a callable, it should have a signature matching + '(loop, coro)', where 'loop' will be a reference to the active + event loop, 'coro' will be a coroutine object. The callable + must return a Future. + """ + if factory is not None and not callable(factory): + raise TypeError('task factory must be a callable or None') + self._task_factory = factory + + def get_task_factory(self): + """Return a task factory, or None if the default one is in use.""" + return self._task_factory + def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): """Create socket transport.""" @@ -465,25 +487,25 @@ self._write_to_self() return handle - def run_in_executor(self, executor, callback, *args): - if (coroutines.iscoroutine(callback) - or coroutines.iscoroutinefunction(callback)): + def run_in_executor(self, executor, func, *args): + if (coroutines.iscoroutine(func) + or coroutines.iscoroutinefunction(func)): raise TypeError("coroutines cannot be used with run_in_executor()") self._check_closed() - if isinstance(callback, events.Handle): + if isinstance(func, events.Handle): assert not args - assert not isinstance(callback, events.TimerHandle) - if callback._cancelled: + assert not isinstance(func, events.TimerHandle) + if func._cancelled: f = futures.Future(loop=self) f.set_result(None) return f - callback, args = callback._callback, callback._args + func, args = func._callback, func._args if executor is None: executor = self._default_executor if executor is None: executor = concurrent.futures.ThreadPoolExecutor(_MAX_WORKERS) self._default_executor = executor - return futures.wrap_future(executor.submit(callback, *args), loop=self) + return futures.wrap_future(executor.submit(func, *args), loop=self) def set_default_executor(self, executor): self._default_executor = executor diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -277,7 +277,7 @@ def call_soon_threadsafe(self, callback, *args): raise NotImplementedError - def run_in_executor(self, executor, callback, *args): + def run_in_executor(self, executor, func, *args): raise NotImplementedError def set_default_executor(self, executor): @@ -438,6 +438,14 @@ def remove_signal_handler(self, sig): raise NotImplementedError + # Task factory. + + def set_task_factory(self, factory): + raise NotImplementedError + + def get_task_factory(self): + raise NotImplementedError + # Error handlers. def set_exception_handler(self, handler): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -16,10 +16,15 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support - from asyncio.test_support import assert_python_ok +try: + from test.support.script_helper import assert_python_ok +except ImportError: + try: + from test.script_helper import assert_python_ok + except ImportError: + from asyncio.test_support import assert_python_ok MOCK_ANY = mock.ANY @@ -623,6 +628,42 @@ self.assertIs(type(_context['context']['exception']), ZeroDivisionError) + def test_set_task_factory_invalid(self): + with self.assertRaisesRegex( + TypeError, 'task factory must be a callable or None'): + + self.loop.set_task_factory(1) + + self.assertIsNone(self.loop.get_task_factory()) + + def test_set_task_factory(self): + self.loop._process_events = mock.Mock() + + class MyTask(asyncio.Task): + pass + + @asyncio.coroutine + def coro(): + pass + + factory = lambda loop, coro: MyTask(coro, loop=loop) + + self.assertIsNone(self.loop.get_task_factory()) + self.loop.set_task_factory(factory) + self.assertIs(self.loop.get_task_factory(), factory) + + task = self.loop.create_task(coro()) + self.assertTrue(isinstance(task, MyTask)) + self.loop.run_until_complete(task) + + self.loop.set_task_factory(None) + self.assertIsNone(self.loop.get_task_factory()) + + task = self.loop.create_task(coro()) + self.assertTrue(isinstance(task, asyncio.Task)) + self.assertFalse(isinstance(task, MyTask)) + self.loop.run_until_complete(task) + def test_env_var_debug(self): code = '\n'.join(( 'import asyncio', diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -15,10 +15,15 @@ from asyncio import test_utils try: from test import support - from test.script_helper import assert_python_ok except ImportError: from asyncio import test_support as support - from asyncio.test_support import assert_python_ok +try: + from test.support.script_helper import assert_python_ok +except ImportError: + try: + from test.script_helper import assert_python_ok + except ImportError: + from asyncio.test_support import assert_python_ok PY34 = (sys.version_info >= (3, 4)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,8 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. +- asyncio: New event loop APIs: set_task_factory() and get_task_factory() + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:50:48 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:50:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=28asyncio_changes=29?= Message-ID: <20150511185047.14366.22933@psf.io> https://hg.python.org/cpython/rev/9491fd7e6f51 changeset: 95957:9491fd7e6f51 parent: 95955:17bd326e2e2f parent: 95956:b78127eafad7 user: Yury Selivanov date: Mon May 11 14:50:41 2015 -0400 summary: Merge 3.4 (asyncio changes) files: Lib/asyncio/base_events.py | 2 +- Lib/asyncio/tasks.py | 27 ++++- Lib/asyncio/windows_events.py | 2 +- Lib/test/test_asyncio/test_base_events.py | 6 +- Lib/test/test_asyncio/test_tasks.py | 48 +++++---- Lib/test/test_asyncio/test_windows_events.py | 2 +- Misc/NEWS | 6 +- 7 files changed, 58 insertions(+), 35 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -315,7 +315,7 @@ self._check_closed() new_task = not isinstance(future, futures.Future) - future = tasks.async(future, loop=self) + future = tasks.ensure_future(future, loop=self) if new_task: # An exception is raised if the future didn't complete, so there # is no need to log the "destroy pending task" message diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -3,7 +3,7 @@ __all__ = ['Task', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'wait', 'wait_for', 'as_completed', 'sleep', 'async', - 'gather', 'shield', + 'gather', 'shield', 'ensure_future', ] import concurrent.futures @@ -12,6 +12,7 @@ import linecache import sys import traceback +import warnings import weakref from . import coroutines @@ -327,7 +328,7 @@ if loop is None: loop = events.get_event_loop() - fs = {async(f, loop=loop) for f in set(fs)} + fs = {ensure_future(f, loop=loop) for f in set(fs)} return (yield from _wait(fs, timeout, return_when, loop)) @@ -361,7 +362,7 @@ timeout_handle = loop.call_later(timeout, _release_waiter, waiter) cb = functools.partial(_release_waiter, waiter) - fut = async(fut, loop=loop) + fut = ensure_future(fut, loop=loop) fut.add_done_callback(cb) try: @@ -449,7 +450,7 @@ if isinstance(fs, futures.Future) or coroutines.iscoroutine(fs): raise TypeError("expect a list of futures, not %s" % type(fs).__name__) loop = loop if loop is not None else events.get_event_loop() - todo = {async(f, loop=loop) for f in set(fs)} + todo = {ensure_future(f, loop=loop) for f in set(fs)} from .queues import Queue # Import here to avoid circular import problem. done = Queue(loop=loop) timeout_handle = None @@ -500,6 +501,20 @@ """Wrap a coroutine in a future. If the argument is a Future, it is returned directly. + + This function is deprecated in 3.5. Use asyncio.ensure_future() instead. + """ + + warnings.warn("asyncio.async() function is deprecated, use ensure_future()", + DeprecationWarning) + + return ensure_future(coro_or_future, loop=loop) + + +def ensure_future(coro_or_future, *, loop=None): + """Wrap a coroutine in a future. + + If the argument is a Future, it is returned directly. """ if isinstance(coro_or_future, futures.Future): if loop is not None and loop is not coro_or_future._loop: @@ -564,7 +579,7 @@ arg_to_fut = {} for arg in set(coros_or_futures): if not isinstance(arg, futures.Future): - fut = async(arg, loop=loop) + fut = ensure_future(arg, loop=loop) if loop is None: loop = fut._loop # The caller cannot control this future, the "destroy pending task" @@ -640,7 +655,7 @@ except CancelledError: res = None """ - inner = async(arg, loop=loop) + inner = ensure_future(arg, loop=loop) if inner.done(): # Shortcut. return inner diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -488,7 +488,7 @@ future = self._register(ov, listener, finish_accept) coro = accept_coro(future, conn) - tasks.async(coro, loop=self._loop) + tasks.ensure_future(coro, loop=self._loop) return future def connect(self, conn, address): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -504,7 +504,7 @@ # Test Future.__del__ with mock.patch('asyncio.base_events.logger') as log: - fut = asyncio.async(zero_error_coro(), loop=self.loop) + fut = asyncio.ensure_future(zero_error_coro(), loop=self.loop) fut.add_done_callback(lambda *args: self.loop.stop()) self.loop.run_forever() fut = None # Trigger Future.__del__ or futures._TracebackLogger @@ -703,7 +703,7 @@ self.set_event_loop(loop) coro = test() - task = asyncio.async(coro, loop=loop) + task = asyncio.ensure_future(coro, loop=loop) self.assertIsInstance(task, MyTask) # make warnings quiet @@ -1265,7 +1265,7 @@ "took .* seconds$") # slow task - asyncio.async(stop_loop_coro(self.loop), loop=self.loop) + asyncio.ensure_future(stop_loop_coro(self.loop), loop=self.loop) self.loop.run_forever() fmt, *args = m_logger.warning.call_args[0] self.assertRegex(fmt % tuple(args), diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -92,11 +92,11 @@ loop.run_until_complete(t) loop.close() - def test_async_coroutine(self): + def test_ensure_future_coroutine(self): @asyncio.coroutine def notmuch(): return 'ok' - t = asyncio.async(notmuch(), loop=self.loop) + t = asyncio.ensure_future(notmuch(), loop=self.loop) self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') @@ -104,16 +104,16 @@ loop = asyncio.new_event_loop() self.set_event_loop(loop) - t = asyncio.async(notmuch(), loop=loop) + t = asyncio.ensure_future(notmuch(), loop=loop) self.assertIs(t._loop, loop) loop.run_until_complete(t) loop.close() - def test_async_future(self): + def test_ensure_future_future(self): f_orig = asyncio.Future(loop=self.loop) f_orig.set_result('ko') - f = asyncio.async(f_orig) + f = asyncio.ensure_future(f_orig) self.loop.run_until_complete(f) self.assertTrue(f.done()) self.assertEqual(f.result(), 'ko') @@ -123,19 +123,19 @@ self.set_event_loop(loop) with self.assertRaises(ValueError): - f = asyncio.async(f_orig, loop=loop) + f = asyncio.ensure_future(f_orig, loop=loop) loop.close() - f = asyncio.async(f_orig, loop=self.loop) + f = asyncio.ensure_future(f_orig, loop=self.loop) self.assertIs(f, f_orig) - def test_async_task(self): + def test_ensure_future_task(self): @asyncio.coroutine def notmuch(): return 'ok' t_orig = asyncio.Task(notmuch(), loop=self.loop) - t = asyncio.async(t_orig) + t = asyncio.ensure_future(t_orig) self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') @@ -145,16 +145,22 @@ self.set_event_loop(loop) with self.assertRaises(ValueError): - t = asyncio.async(t_orig, loop=loop) + t = asyncio.ensure_future(t_orig, loop=loop) loop.close() - t = asyncio.async(t_orig, loop=self.loop) + t = asyncio.ensure_future(t_orig, loop=self.loop) self.assertIs(t, t_orig) - def test_async_neither(self): + def test_ensure_future_neither(self): with self.assertRaises(TypeError): - asyncio.async('ok') + asyncio.ensure_future('ok') + + def test_async_warning(self): + f = asyncio.Future(loop=self.loop) + with self.assertWarnsRegex(DeprecationWarning, + 'function is deprecated, use ensure_'): + self.assertIs(f, asyncio.async(f)) def test_task_repr(self): self.loop.set_debug(False) @@ -1420,7 +1426,7 @@ else: proof += 10 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() self.loop.run_until_complete(f) @@ -1445,7 +1451,7 @@ d, p = yield from asyncio.wait([inner()], loop=self.loop) proof += 100 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() self.assertRaises( @@ -1501,7 +1507,7 @@ yield from asyncio.shield(inner(), loop=self.loop) proof += 100 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() with self.assertRaises(asyncio.CancelledError): @@ -1668,7 +1674,7 @@ # schedule the task coro = kill_me(self.loop) - task = asyncio.async(coro, loop=self.loop) + task = asyncio.ensure_future(coro, loop=self.loop) self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {task}) # execute the task so it waits for future @@ -1996,8 +2002,8 @@ yield from waiter proof += 1 - child1 = asyncio.async(inner(), loop=self.one_loop) - child2 = asyncio.async(inner(), loop=self.one_loop) + child1 = asyncio.ensure_future(inner(), loop=self.one_loop) + child2 = asyncio.ensure_future(inner(), loop=self.one_loop) gatherer = None @asyncio.coroutine @@ -2007,7 +2013,7 @@ yield from gatherer proof += 100 - f = asyncio.async(outer(), loop=self.one_loop) + f = asyncio.ensure_future(outer(), loop=self.one_loop) test_utils.run_briefly(self.one_loop) self.assertTrue(f.cancel()) with self.assertRaises(asyncio.CancelledError): @@ -2034,7 +2040,7 @@ def outer(): yield from asyncio.gather(inner(a), inner(b), loop=self.one_loop) - f = asyncio.async(outer(), loop=self.one_loop) + f = asyncio.ensure_future(outer(), loop=self.one_loop) test_utils.run_briefly(self.one_loop) a.set_result(None) test_utils.run_briefly(self.one_loop) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -37,7 +37,7 @@ def test_close(self): a, b = self.loop._socketpair() trans = self.loop._make_socket_transport(a, asyncio.Protocol()) - f = asyncio.async(self.loop.sock_recv(b, 100)) + f = asyncio.ensure_future(self.loop.sock_recv(b, 100)) trans.close() self.loop.run_until_complete(f) self.assertEqual(f.result(), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -87,6 +87,10 @@ - Issue #23887: urllib.error.HTTPError now has a proper repr() representation. Patch by Berker Peksag. +- asyncio: New event loop APIs: set_task_factory() and get_task_factory(). + +- asyncio: async() function is deprecated in favour of ensure_future(). + Tests ----- @@ -154,8 +158,6 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. -- asyncio: New event loop APIs: set_task_factory() and get_task_factory() - Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:50:48 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:50:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogYXN5?= =?utf-8?q?nc=28=29_function_is_deprecated_in_favour_of_ensure=5Ffuture=28?= =?utf-8?b?KS4=?= Message-ID: <20150511185047.84480.21325@psf.io> https://hg.python.org/cpython/rev/b78127eafad7 changeset: 95956:b78127eafad7 branch: 3.4 parent: 95953:a983d63e3321 user: Yury Selivanov date: Mon May 11 14:48:38 2015 -0400 summary: asyncio: async() function is deprecated in favour of ensure_future(). files: Lib/asyncio/base_events.py | 2 +- Lib/asyncio/tasks.py | 27 ++++- Lib/asyncio/windows_events.py | 2 +- Lib/test/test_asyncio/test_base_events.py | 6 +- Lib/test/test_asyncio/test_tasks.py | 48 +++++---- Lib/test/test_asyncio/test_windows_events.py | 2 +- Misc/NEWS | 4 +- 7 files changed, 57 insertions(+), 34 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -315,7 +315,7 @@ self._check_closed() new_task = not isinstance(future, futures.Future) - future = tasks.async(future, loop=self) + future = tasks.ensure_future(future, loop=self) if new_task: # An exception is raised if the future didn't complete, so there # is no need to log the "destroy pending task" message diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -3,7 +3,7 @@ __all__ = ['Task', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'wait', 'wait_for', 'as_completed', 'sleep', 'async', - 'gather', 'shield', + 'gather', 'shield', 'ensure_future', ] import concurrent.futures @@ -12,6 +12,7 @@ import linecache import sys import traceback +import warnings import weakref from . import coroutines @@ -327,7 +328,7 @@ if loop is None: loop = events.get_event_loop() - fs = {async(f, loop=loop) for f in set(fs)} + fs = {ensure_future(f, loop=loop) for f in set(fs)} return (yield from _wait(fs, timeout, return_when, loop)) @@ -361,7 +362,7 @@ timeout_handle = loop.call_later(timeout, _release_waiter, waiter) cb = functools.partial(_release_waiter, waiter) - fut = async(fut, loop=loop) + fut = ensure_future(fut, loop=loop) fut.add_done_callback(cb) try: @@ -449,7 +450,7 @@ if isinstance(fs, futures.Future) or coroutines.iscoroutine(fs): raise TypeError("expect a list of futures, not %s" % type(fs).__name__) loop = loop if loop is not None else events.get_event_loop() - todo = {async(f, loop=loop) for f in set(fs)} + todo = {ensure_future(f, loop=loop) for f in set(fs)} from .queues import Queue # Import here to avoid circular import problem. done = Queue(loop=loop) timeout_handle = None @@ -500,6 +501,20 @@ """Wrap a coroutine in a future. If the argument is a Future, it is returned directly. + + This function is deprecated in 3.5. Use asyncio.ensure_future() instead. + """ + + warnings.warn("asyncio.async() function is deprecated, use ensure_future()", + DeprecationWarning) + + return ensure_future(coro_or_future, loop=loop) + + +def ensure_future(coro_or_future, *, loop=None): + """Wrap a coroutine in a future. + + If the argument is a Future, it is returned directly. """ if isinstance(coro_or_future, futures.Future): if loop is not None and loop is not coro_or_future._loop: @@ -564,7 +579,7 @@ arg_to_fut = {} for arg in set(coros_or_futures): if not isinstance(arg, futures.Future): - fut = async(arg, loop=loop) + fut = ensure_future(arg, loop=loop) if loop is None: loop = fut._loop # The caller cannot control this future, the "destroy pending task" @@ -640,7 +655,7 @@ except CancelledError: res = None """ - inner = async(arg, loop=loop) + inner = ensure_future(arg, loop=loop) if inner.done(): # Shortcut. return inner diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -488,7 +488,7 @@ future = self._register(ov, listener, finish_accept) coro = accept_coro(future, conn) - tasks.async(coro, loop=self._loop) + tasks.ensure_future(coro, loop=self._loop) return future def connect(self, conn, address): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -504,7 +504,7 @@ # Test Future.__del__ with mock.patch('asyncio.base_events.logger') as log: - fut = asyncio.async(zero_error_coro(), loop=self.loop) + fut = asyncio.ensure_future(zero_error_coro(), loop=self.loop) fut.add_done_callback(lambda *args: self.loop.stop()) self.loop.run_forever() fut = None # Trigger Future.__del__ or futures._TracebackLogger @@ -703,7 +703,7 @@ self.set_event_loop(loop) coro = test() - task = asyncio.async(coro, loop=loop) + task = asyncio.ensure_future(coro, loop=loop) self.assertIsInstance(task, MyTask) # make warnings quiet @@ -1265,7 +1265,7 @@ "took .* seconds$") # slow task - asyncio.async(stop_loop_coro(self.loop), loop=self.loop) + asyncio.ensure_future(stop_loop_coro(self.loop), loop=self.loop) self.loop.run_forever() fmt, *args = m_logger.warning.call_args[0] self.assertRegex(fmt % tuple(args), diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -92,11 +92,11 @@ loop.run_until_complete(t) loop.close() - def test_async_coroutine(self): + def test_ensure_future_coroutine(self): @asyncio.coroutine def notmuch(): return 'ok' - t = asyncio.async(notmuch(), loop=self.loop) + t = asyncio.ensure_future(notmuch(), loop=self.loop) self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') @@ -104,16 +104,16 @@ loop = asyncio.new_event_loop() self.set_event_loop(loop) - t = asyncio.async(notmuch(), loop=loop) + t = asyncio.ensure_future(notmuch(), loop=loop) self.assertIs(t._loop, loop) loop.run_until_complete(t) loop.close() - def test_async_future(self): + def test_ensure_future_future(self): f_orig = asyncio.Future(loop=self.loop) f_orig.set_result('ko') - f = asyncio.async(f_orig) + f = asyncio.ensure_future(f_orig) self.loop.run_until_complete(f) self.assertTrue(f.done()) self.assertEqual(f.result(), 'ko') @@ -123,19 +123,19 @@ self.set_event_loop(loop) with self.assertRaises(ValueError): - f = asyncio.async(f_orig, loop=loop) + f = asyncio.ensure_future(f_orig, loop=loop) loop.close() - f = asyncio.async(f_orig, loop=self.loop) + f = asyncio.ensure_future(f_orig, loop=self.loop) self.assertIs(f, f_orig) - def test_async_task(self): + def test_ensure_future_task(self): @asyncio.coroutine def notmuch(): return 'ok' t_orig = asyncio.Task(notmuch(), loop=self.loop) - t = asyncio.async(t_orig) + t = asyncio.ensure_future(t_orig) self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') @@ -145,16 +145,22 @@ self.set_event_loop(loop) with self.assertRaises(ValueError): - t = asyncio.async(t_orig, loop=loop) + t = asyncio.ensure_future(t_orig, loop=loop) loop.close() - t = asyncio.async(t_orig, loop=self.loop) + t = asyncio.ensure_future(t_orig, loop=self.loop) self.assertIs(t, t_orig) - def test_async_neither(self): + def test_ensure_future_neither(self): with self.assertRaises(TypeError): - asyncio.async('ok') + asyncio.ensure_future('ok') + + def test_async_warning(self): + f = asyncio.Future(loop=self.loop) + with self.assertWarnsRegex(DeprecationWarning, + 'function is deprecated, use ensure_'): + self.assertIs(f, asyncio.async(f)) def test_task_repr(self): self.loop.set_debug(False) @@ -1420,7 +1426,7 @@ else: proof += 10 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() self.loop.run_until_complete(f) @@ -1445,7 +1451,7 @@ d, p = yield from asyncio.wait([inner()], loop=self.loop) proof += 100 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() self.assertRaises( @@ -1501,7 +1507,7 @@ yield from asyncio.shield(inner(), loop=self.loop) proof += 100 - f = asyncio.async(outer(), loop=self.loop) + f = asyncio.ensure_future(outer(), loop=self.loop) test_utils.run_briefly(self.loop) f.cancel() with self.assertRaises(asyncio.CancelledError): @@ -1668,7 +1674,7 @@ # schedule the task coro = kill_me(self.loop) - task = asyncio.async(coro, loop=self.loop) + task = asyncio.ensure_future(coro, loop=self.loop) self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {task}) # execute the task so it waits for future @@ -1996,8 +2002,8 @@ yield from waiter proof += 1 - child1 = asyncio.async(inner(), loop=self.one_loop) - child2 = asyncio.async(inner(), loop=self.one_loop) + child1 = asyncio.ensure_future(inner(), loop=self.one_loop) + child2 = asyncio.ensure_future(inner(), loop=self.one_loop) gatherer = None @asyncio.coroutine @@ -2007,7 +2013,7 @@ yield from gatherer proof += 100 - f = asyncio.async(outer(), loop=self.one_loop) + f = asyncio.ensure_future(outer(), loop=self.one_loop) test_utils.run_briefly(self.one_loop) self.assertTrue(f.cancel()) with self.assertRaises(asyncio.CancelledError): @@ -2034,7 +2040,7 @@ def outer(): yield from asyncio.gather(inner(a), inner(b), loop=self.one_loop) - f = asyncio.async(outer(), loop=self.one_loop) + f = asyncio.ensure_future(outer(), loop=self.one_loop) test_utils.run_briefly(self.one_loop) a.set_result(None) test_utils.run_briefly(self.one_loop) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -37,7 +37,7 @@ def test_close(self): a, b = self.loop._socketpair() trans = self.loop._make_socket_transport(a, asyncio.Protocol()) - f = asyncio.async(self.loop.sock_recv(b, 100)) + f = asyncio.ensure_future(self.loop.sock_recv(b, 100)) trans.close() self.loop.run_until_complete(f) self.assertEqual(f.result(), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,7 +42,9 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. -- asyncio: New event loop APIs: set_task_factory() and get_task_factory() +- asyncio: New event loop APIs: set_task_factory() and get_task_factory(). + +- asyncio: async() function is deprecated in favour of ensure_future(). Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:56:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:56:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_NEWS_file?= =?utf-8?q?=2E?= Message-ID: <20150511185601.11930.99073@psf.io> https://hg.python.org/cpython/rev/d80e8721e55b changeset: 95958:d80e8721e55b branch: 3.4 parent: 95956:b78127eafad7 user: Yury Selivanov date: Mon May 11 14:52:37 2015 -0400 summary: Fix NEWS file. files: Misc/NEWS | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,10 +42,6 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. -- asyncio: New event loop APIs: set_task_factory() and get_task_factory(). - -- asyncio: async() function is deprecated in favour of ensure_future(). - Library ------- @@ -234,6 +230,10 @@ - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. +- asyncio: New event loop APIs: set_task_factory() and get_task_factory(). + +- asyncio: async() function is deprecated in favour of ensure_future(). + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 20:56:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 18:56:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge=2E?= Message-ID: <20150511185601.76592.72018@psf.io> https://hg.python.org/cpython/rev/976223ff4566 changeset: 95959:976223ff4566 parent: 95957:9491fd7e6f51 parent: 95958:d80e8721e55b user: Yury Selivanov date: Mon May 11 14:55:54 2015 -0400 summary: Null merge. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 22:34:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 20:34:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_docs/asyncio?= =?utf-8?q?=3A_Document_set=5Ftask=5Ffactory/get=5Ftask=5Ffactory?= Message-ID: <20150511203429.84486.18675@psf.io> https://hg.python.org/cpython/rev/c57f37352e3e changeset: 95960:c57f37352e3e branch: 3.4 parent: 95958:d80e8721e55b user: Yury Selivanov date: Mon May 11 16:28:27 2015 -0400 summary: docs/asyncio: Document set_task_factory/get_task_factory files: Doc/library/asyncio-eventloop.rst | 20 +++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -181,6 +181,26 @@ .. versionadded:: 3.4.2 +.. method:: BaseEventLoop.set_task_factory(factory) + + Set a task factory that will be used by + :meth:`BaseEventLoop.create_task`. + + If *factory* is ``None`` the default task factory will be set. + + If *factory* is a *callable*, it should have a signature matching + ``(loop, coro)``, where *loop* will be a reference to the active + event loop, *coro* will be a coroutine object. The callable + must return an :class:`asyncio.Future` compatible object. + + .. versionadded:: 3.4.4 + +.. method:: BaseEventLoop.get_task_factory() + + Return a task factory, or ``None`` if the default one is in use. + + .. versionadded:: 3.4.4 + Creating connections -------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 22:34:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 20:34:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_docs/asyncio?= =?utf-8?q?=3A_Document_new_ensure=5Ffuture=28=29_and_deprecated_async=28?= =?utf-8?q?=29?= Message-ID: <20150511203429.1928.61097@psf.io> https://hg.python.org/cpython/rev/9d9e445d25dc changeset: 95961:9d9e445d25dc branch: 3.4 user: Yury Selivanov date: Mon May 11 16:33:41 2015 -0400 summary: docs/asyncio: Document new ensure_future() and deprecated async() files: Doc/library/asyncio-dev.rst | 26 +++++++++++----------- Doc/library/asyncio-stream.rst | 2 +- Doc/library/asyncio-task.rst | 20 +++++++++++----- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -210,7 +210,7 @@ raise Exception("not consumed") loop = asyncio.get_event_loop() - asyncio.async(bug()) + asyncio.ensure_future(bug()) loop.run_forever() loop.close() @@ -234,7 +234,7 @@ future: exception=Exception('not consumed',) created at test.py:8> source_traceback: Object created at (most recent call last): File "test.py", line 8, in - asyncio.async(bug()) + asyncio.ensure_future(bug()) Traceback (most recent call last): File "asyncio/tasks.py", line 237, in _step result = next(coro) @@ -257,14 +257,14 @@ print("exception consumed") loop = asyncio.get_event_loop() - asyncio.async(handle_exception()) + asyncio.ensure_future(handle_exception()) loop.run_forever() loop.close() Another option is to use the :meth:`BaseEventLoop.run_until_complete` function:: - task = asyncio.async(bug()) + task = asyncio.ensure_future(bug()) try: loop.run_until_complete(task) except Exception: @@ -303,14 +303,14 @@ @asyncio.coroutine def test(): - asyncio.async(create()) - asyncio.async(write()) - asyncio.async(close()) + asyncio.ensure_future(create()) + asyncio.ensure_future(write()) + asyncio.ensure_future(close()) yield from asyncio.sleep(2.0) loop.stop() loop = asyncio.get_event_loop() - asyncio.async(test()) + asyncio.ensure_future(test()) loop.run_forever() print("Pending tasks at exit: %s" % asyncio.Task.all_tasks(loop)) loop.close() @@ -338,13 +338,13 @@ @asyncio.coroutine def test(): - yield from asyncio.async(create()) - yield from asyncio.async(write()) - yield from asyncio.async(close()) + yield from asyncio.ensure_future(create()) + yield from asyncio.ensure_future(write()) + yield from asyncio.ensure_future(close()) yield from asyncio.sleep(2.0) loop.stop() -Or without ``asyncio.async()``:: +Or without ``asyncio.ensure_future()``:: @asyncio.coroutine def test(): @@ -374,7 +374,7 @@ Task was destroyed but it is pending! source_traceback: Object created at (most recent call last): File "test.py", line 15, in - task = asyncio.async(coro, loop=loop) + task = asyncio.ensure_future(coro, loop=loop) task: wait_for= created at test.py:15> diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -364,7 +364,7 @@ url = sys.argv[1] loop = asyncio.get_event_loop() - task = asyncio.async(print_http_headers(url)) + task = asyncio.ensure_future(print_http_headers(url)) loop.run_until_complete(task) loop.close() diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -296,7 +296,7 @@ loop = asyncio.get_event_loop() future = asyncio.Future() - asyncio.async(slow_operation(future)) + asyncio.ensure_future(slow_operation(future)) loop.run_until_complete(future) print(future.result()) loop.close() @@ -332,7 +332,7 @@ loop = asyncio.get_event_loop() future = asyncio.Future() - asyncio.async(slow_operation(future)) + asyncio.ensure_future(slow_operation(future)) future.add_done_callback(got_result) try: loop.run_forever() @@ -461,9 +461,9 @@ loop = asyncio.get_event_loop() tasks = [ - asyncio.async(factorial("A", 2)), - asyncio.async(factorial("B", 3)), - asyncio.async(factorial("C", 4))] + asyncio.ensure_future(factorial("A", 2)), + asyncio.ensure_future(factorial("B", 3)), + asyncio.ensure_future(factorial("C", 4))] loop.run_until_complete(asyncio.wait(tasks)) loop.close() @@ -510,17 +510,25 @@ The futures ``f`` are not necessarily members of fs. -.. function:: async(coro_or_future, \*, loop=None) +.. function:: ensure_future(coro_or_future, \*, loop=None) Schedule the execution of a :ref:`coroutine object `: wrap it in a future. Return a :class:`Task` object. If the argument is a :class:`Future`, it is returned directly. + .. versionadded:: 3.4.4 + .. seealso:: The :meth:`BaseEventLoop.create_task` method. +.. function:: async(coro_or_future, \*, loop=None) + + A deprecated alias to :func:`ensure_future`. + + .. deprecated:: 3.4.4 + .. function:: gather(\*coros_or_futures, loop=None, return_exceptions=False) Return a future aggregating results from the given coroutine objects or -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 11 22:34:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 20:34:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40IChhc3luY2lvIGRvY3Mp?= Message-ID: <20150511203430.84486.38219@psf.io> https://hg.python.org/cpython/rev/90ff2b9e9244 changeset: 95962:90ff2b9e9244 parent: 95959:976223ff4566 parent: 95961:9d9e445d25dc user: Yury Selivanov date: Mon May 11 16:34:13 2015 -0400 summary: Merge 3.4 (asyncio docs) files: Doc/library/asyncio-dev.rst | 26 +++++++++--------- Doc/library/asyncio-eventloop.rst | 20 ++++++++++++++ Doc/library/asyncio-stream.rst | 2 +- Doc/library/asyncio-task.rst | 20 ++++++++++---- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -210,7 +210,7 @@ raise Exception("not consumed") loop = asyncio.get_event_loop() - asyncio.async(bug()) + asyncio.ensure_future(bug()) loop.run_forever() loop.close() @@ -234,7 +234,7 @@ future: exception=Exception('not consumed',) created at test.py:8> source_traceback: Object created at (most recent call last): File "test.py", line 8, in - asyncio.async(bug()) + asyncio.ensure_future(bug()) Traceback (most recent call last): File "asyncio/tasks.py", line 237, in _step result = next(coro) @@ -257,14 +257,14 @@ print("exception consumed") loop = asyncio.get_event_loop() - asyncio.async(handle_exception()) + asyncio.ensure_future(handle_exception()) loop.run_forever() loop.close() Another option is to use the :meth:`BaseEventLoop.run_until_complete` function:: - task = asyncio.async(bug()) + task = asyncio.ensure_future(bug()) try: loop.run_until_complete(task) except Exception: @@ -303,14 +303,14 @@ @asyncio.coroutine def test(): - asyncio.async(create()) - asyncio.async(write()) - asyncio.async(close()) + asyncio.ensure_future(create()) + asyncio.ensure_future(write()) + asyncio.ensure_future(close()) yield from asyncio.sleep(2.0) loop.stop() loop = asyncio.get_event_loop() - asyncio.async(test()) + asyncio.ensure_future(test()) loop.run_forever() print("Pending tasks at exit: %s" % asyncio.Task.all_tasks(loop)) loop.close() @@ -338,13 +338,13 @@ @asyncio.coroutine def test(): - yield from asyncio.async(create()) - yield from asyncio.async(write()) - yield from asyncio.async(close()) + yield from asyncio.ensure_future(create()) + yield from asyncio.ensure_future(write()) + yield from asyncio.ensure_future(close()) yield from asyncio.sleep(2.0) loop.stop() -Or without ``asyncio.async()``:: +Or without ``asyncio.ensure_future()``:: @asyncio.coroutine def test(): @@ -374,7 +374,7 @@ Task was destroyed but it is pending! source_traceback: Object created at (most recent call last): File "test.py", line 15, in - task = asyncio.async(coro, loop=loop) + task = asyncio.ensure_future(coro, loop=loop) task: wait_for= created at test.py:15> diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -181,6 +181,26 @@ .. versionadded:: 3.4.2 +.. method:: BaseEventLoop.set_task_factory(factory) + + Set a task factory that will be used by + :meth:`BaseEventLoop.create_task`. + + If *factory* is ``None`` the default task factory will be set. + + If *factory* is a *callable*, it should have a signature matching + ``(loop, coro)``, where *loop* will be a reference to the active + event loop, *coro* will be a coroutine object. The callable + must return an :class:`asyncio.Future` compatible object. + + .. versionadded:: 3.4.4 + +.. method:: BaseEventLoop.get_task_factory() + + Return a task factory, or ``None`` if the default one is in use. + + .. versionadded:: 3.4.4 + Creating connections -------------------- diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -364,7 +364,7 @@ url = sys.argv[1] loop = asyncio.get_event_loop() - task = asyncio.async(print_http_headers(url)) + task = asyncio.ensure_future(print_http_headers(url)) loop.run_until_complete(task) loop.close() diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -296,7 +296,7 @@ loop = asyncio.get_event_loop() future = asyncio.Future() - asyncio.async(slow_operation(future)) + asyncio.ensure_future(slow_operation(future)) loop.run_until_complete(future) print(future.result()) loop.close() @@ -332,7 +332,7 @@ loop = asyncio.get_event_loop() future = asyncio.Future() - asyncio.async(slow_operation(future)) + asyncio.ensure_future(slow_operation(future)) future.add_done_callback(got_result) try: loop.run_forever() @@ -461,9 +461,9 @@ loop = asyncio.get_event_loop() tasks = [ - asyncio.async(factorial("A", 2)), - asyncio.async(factorial("B", 3)), - asyncio.async(factorial("C", 4))] + asyncio.ensure_future(factorial("A", 2)), + asyncio.ensure_future(factorial("B", 3)), + asyncio.ensure_future(factorial("C", 4))] loop.run_until_complete(asyncio.wait(tasks)) loop.close() @@ -510,17 +510,25 @@ The futures ``f`` are not necessarily members of fs. -.. function:: async(coro_or_future, \*, loop=None) +.. function:: ensure_future(coro_or_future, \*, loop=None) Schedule the execution of a :ref:`coroutine object `: wrap it in a future. Return a :class:`Task` object. If the argument is a :class:`Future`, it is returned directly. + .. versionadded:: 3.4.4 + .. seealso:: The :meth:`BaseEventLoop.create_task` method. +.. function:: async(coro_or_future, \*, loop=None) + + A deprecated alias to :func:`ensure_future`. + + .. deprecated:: 3.4.4 + .. function:: gather(\*coros_or_futures, loop=None, return_exceptions=False) Return a future aggregating results from the given coroutine objects or -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 01:35:17 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 11 May 2015 23:35:17 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0475=3A_Mark_as_Final=2E?= Message-ID: <20150511233517.76604.2856@psf.io> https://hg.python.org/peps/rev/9b1276eab721 changeset: 5839:9b1276eab721 user: Yury Selivanov date: Mon May 11 19:35:14 2015 -0400 summary: pep-0475: Mark as Final. files: pep-0475.txt | 10 +++++++++- pep-0478.txt | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pep-0475.txt b/pep-0475.txt --- a/pep-0475.txt +++ b/pep-0475.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Charles-Fran?ois Natali , Victor Stinner BDFL-Delegate: Antoine Pitrou -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 29-July-2014 @@ -462,6 +462,14 @@ `_ +Implementation +============== + +The implementation is tracked in `issue 23285 +`_. It was committed on +February 07, 2015. + + Copyright ========= diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -64,10 +64,10 @@ * PEP 441, improved Python zip application support * PEP 448, additional unpacking generalizations * PEP 486, make the Python Launcher aware of virtual environments +* PEP 475, retrying system calls that fail with EINTR Accepted PEPs: -* PEP 475, retrying system calls that fail with EINTR * PEP 485, math.isclose(), a function for testing approximate equality * PEP 492, coroutines with async and await syntax -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 04:25:46 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 12 May 2015 02:25:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_code_cleanups=2E?= Message-ID: <20150512022546.25439.49526@psf.io> https://hg.python.org/cpython/rev/5c3813e74f88 changeset: 95963:5c3813e74f88 user: Raymond Hettinger date: Mon May 11 19:25:32 2015 -0700 summary: Minor code cleanups. files: Modules/_heapqmodule.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -138,7 +138,7 @@ lastelt = PyList_GET_ITEM(heap, n-1) ; Py_INCREF(lastelt); - if (PyList_SetSlice(heap, n-1, n, NULL) < 0) { + if (PyList_SetSlice(heap, n-1, n, NULL)) { Py_DECREF(lastelt); return NULL; } @@ -177,7 +177,7 @@ return NULL; } - if (PyList_GET_SIZE(heap) < 1) { + if (PyList_GET_SIZE(heap) == 0) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; } @@ -222,7 +222,7 @@ return NULL; } - if (PyList_GET_SIZE(heap) < 1) { + if (PyList_GET_SIZE(heap) == 0) { Py_INCREF(item); return item; } @@ -340,8 +340,8 @@ n is odd = 2*j+1, this is (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. */ - for (i=n/2-1 ; i>=0 ; i--) - if(siftup_func((PyListObject *)heap, i)) + for (i = n/2 - 1 ; i >= 0 ; i--) + if (siftup_func((PyListObject *)heap, i)) return NULL; Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 04:31:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 02:31:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogU3Vw?= =?utf-8?q?port_PEP_492=2E_Issue_=2324017=2E?= Message-ID: <20150512023129.121088.19542@psf.io> https://hg.python.org/cpython/rev/957478e95b26 changeset: 95964:957478e95b26 branch: 3.4 parent: 95961:9d9e445d25dc user: Yury Selivanov date: Mon May 11 22:27:25 2015 -0400 summary: asyncio: Support PEP 492. Issue #24017. files: Lib/asyncio/base_events.py | 47 +++++- Lib/asyncio/coroutines.py | 77 +++++++++- Lib/asyncio/futures.py | 4 + Lib/asyncio/tasks.py | 8 +- Lib/test/test_asyncio/test_base_events.py | 3 +- Lib/test/test_asyncio/test_tasks.py | 4 +- 6 files changed, 116 insertions(+), 27 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -191,8 +191,8 @@ self._thread_id = None self._clock_resolution = time.get_clock_info('monotonic').resolution self._exception_handler = None - self._debug = (not sys.flags.ignore_environment - and bool(os.environ.get('PYTHONASYNCIODEBUG'))) + self.set_debug((not sys.flags.ignore_environment + and bool(os.environ.get('PYTHONASYNCIODEBUG')))) # In debug mode, if the execution of a callback or a step of a task # exceed this duration in seconds, the slow callback/task is logged. self.slow_callback_duration = 0.1 @@ -360,13 +360,18 @@ return if self._debug: logger.debug("Close %r", self) - self._closed = True - self._ready.clear() - self._scheduled.clear() - executor = self._default_executor - if executor is not None: - self._default_executor = None - executor.shutdown(wait=False) + try: + self._closed = True + self._ready.clear() + self._scheduled.clear() + executor = self._default_executor + if executor is not None: + self._default_executor = None + executor.shutdown(wait=False) + finally: + # It is important to unregister "sys.coroutine_wrapper" + # if it was registered. + self.set_debug(False) def is_closed(self): """Returns True if the event loop was closed.""" @@ -1199,3 +1204,27 @@ def set_debug(self, enabled): self._debug = enabled + wrapper = coroutines.debug_wrapper + + try: + set_wrapper = sys.set_coroutine_wrapper + except AttributeError: + pass + else: + current_wrapper = sys.get_coroutine_wrapper() + if enabled: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(True): cannot set debug coroutine " + "wrapper; another wrapper is already set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(wrapper) + else: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(False): cannot unset debug coroutine " + "wrapper; another wrapper was set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(None) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -14,6 +14,9 @@ from .log import logger +_PY35 = sys.version_info >= (3, 5) + + # Opcode of "yield from" instruction _YIELD_FROM = opcode.opmap['YIELD_FROM'] @@ -30,6 +33,27 @@ and bool(os.environ.get('PYTHONASYNCIODEBUG'))) +try: + types.coroutine +except AttributeError: + native_coroutine_support = False +else: + native_coroutine_support = True + +try: + _iscoroutinefunction = inspect.iscoroutinefunction +except AttributeError: + _iscoroutinefunction = lambda func: False + +try: + inspect.CO_COROUTINE +except AttributeError: + _is_native_coro_code = lambda code: False +else: + _is_native_coro_code = lambda code: (code.co_flags & + inspect.CO_COROUTINE) + + # Check for CPython issue #21209 def has_yield_from_bug(): class MyGen: @@ -54,16 +78,27 @@ del has_yield_from_bug +def debug_wrapper(gen): + # This function is called from 'sys.set_coroutine_wrapper'. + # We only wrap here coroutines defined via 'async def' syntax. + # Generator-based coroutines are wrapped in @coroutine + # decorator. + if _is_native_coro_code(gen.gi_code): + return CoroWrapper(gen, None) + else: + return gen + + class CoroWrapper: # Wrapper for coroutine object in _DEBUG mode. - def __init__(self, gen, func): - assert inspect.isgenerator(gen), gen + def __init__(self, gen, func=None): + assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen self.gen = gen - self.func = func + self.func = func # Used to unwrap @coroutine decorator self._source_traceback = traceback.extract_stack(sys._getframe(1)) - # __name__, __qualname__, __doc__ attributes are set by the coroutine() - # decorator + self.__name__ = getattr(gen, '__name__', None) + self.__qualname__ = getattr(gen, '__qualname__', None) def __repr__(self): coro_repr = _format_coroutine(self) @@ -75,6 +110,9 @@ def __iter__(self): return self + if _PY35: + __await__ = __iter__ # make compatible with 'await' expression + def __next__(self): return next(self.gen) @@ -133,6 +171,14 @@ If the coroutine is not yielded from before it is destroyed, an error message is logged. """ + is_coroutine = _iscoroutinefunction(func) + if is_coroutine and _is_native_coro_code(func.__code__): + # In Python 3.5 that's all we need to do for coroutines + # defiend with "async def". + # Wrapping in CoroWrapper will happen via + # 'sys.set_coroutine_wrapper' function. + return func + if inspect.isgeneratorfunction(func): coro = func else: @@ -144,18 +190,22 @@ return res if not _DEBUG: - wrapper = coro + if native_coroutine_support: + wrapper = types.coroutine(coro) + else: + wrapper = coro else: @functools.wraps(func) def wrapper(*args, **kwds): - w = CoroWrapper(coro(*args, **kwds), func) + w = CoroWrapper(coro(*args, **kwds), func=func) if w._source_traceback: del w._source_traceback[-1] - if hasattr(func, '__name__'): - w.__name__ = func.__name__ - if hasattr(func, '__qualname__'): - w.__qualname__ = func.__qualname__ - w.__doc__ = func.__doc__ + # Python < 3.5 does not implement __qualname__ + # on generator objects, so we set it manually. + # We use getattr as some callables (such as + # functools.partial may lack __qualname__). + w.__name__ = getattr(func, '__name__', None) + w.__qualname__ = getattr(func, '__qualname__', None) return w wrapper._is_coroutine = True # For iscoroutinefunction(). @@ -164,7 +214,8 @@ def iscoroutinefunction(func): """Return True if func is a decorated coroutine function.""" - return getattr(func, '_is_coroutine', False) + return (getattr(func, '_is_coroutine', False) or + _iscoroutinefunction(func)) _COROUTINE_TYPES = (types.GeneratorType, CoroWrapper) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -19,6 +19,7 @@ _FINISHED = 'FINISHED' _PY34 = sys.version_info >= (3, 4) +_PY35 = sys.version_info >= (3, 5) Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError @@ -387,6 +388,9 @@ assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. + if _PY35: + __await__ = __iter__ # make compatible with 'await' expression + def wrap_future(fut, *, loop=None): """Wrap concurrent.futures.Future object.""" diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -11,6 +11,7 @@ import inspect import linecache import sys +import types import traceback import warnings import weakref @@ -73,7 +74,10 @@ super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - self._coro = iter(coro) # Use the iterator just in case. + if coro.__class__ is types.GeneratorType: + self._coro = coro + else: + self._coro = iter(coro) # Use the iterator just in case. self._fut_waiter = None self._must_cancel = False self._loop.call_soon(self._step) @@ -236,7 +240,7 @@ elif value is not None: result = coro.send(value) else: - result = next(coro) + result = coro.send(None) except StopIteration as exc: self.set_result(exc.value) except futures.CancelledError as exc: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -61,7 +61,8 @@ NotImplementedError, self.loop._make_write_pipe_transport, m, m) gen = self.loop._make_subprocess_transport(m, m, m, m, m, m, m) - self.assertRaises(NotImplementedError, next, iter(gen)) + with self.assertRaises(NotImplementedError): + gen.send(None) def test_close(self): self.assertFalse(self.loop.is_closed()) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1638,7 +1638,7 @@ return a def call(arg): - cw = asyncio.coroutines.CoroWrapper(foo(), foo) + cw = asyncio.coroutines.CoroWrapper(foo()) cw.send(None) try: cw.send(arg) @@ -1653,7 +1653,7 @@ def test_corowrapper_weakref(self): wd = weakref.WeakValueDictionary() def foo(): yield from [] - cw = asyncio.coroutines.CoroWrapper(foo(), foo) + cw = asyncio.coroutines.CoroWrapper(foo()) wd['cw'] = cw # Would fail without __weakref__ slot. cw.gen = None # Suppress warning from __del__. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 04:31:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 02:31:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_asyncio=3A_Merge_3=2E4_--_Support_PEP_492=2E_Issue_=2324?= =?utf-8?q?017=2E?= Message-ID: <20150512023129.19174.39030@psf.io> https://hg.python.org/cpython/rev/44c1db190525 changeset: 95965:44c1db190525 parent: 95963:5c3813e74f88 parent: 95964:957478e95b26 user: Yury Selivanov date: Mon May 11 22:31:19 2015 -0400 summary: asyncio: Merge 3.4 -- Support PEP 492. Issue #24017. files: Lib/asyncio/base_events.py | 47 +++++- Lib/asyncio/coroutines.py | 77 +++++++++- Lib/asyncio/futures.py | 4 + Lib/asyncio/tasks.py | 8 +- Lib/test/test_asyncio/test_base_events.py | 3 +- Lib/test/test_asyncio/test_tasks.py | 4 +- 6 files changed, 116 insertions(+), 27 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -191,8 +191,8 @@ self._thread_id = None self._clock_resolution = time.get_clock_info('monotonic').resolution self._exception_handler = None - self._debug = (not sys.flags.ignore_environment - and bool(os.environ.get('PYTHONASYNCIODEBUG'))) + self.set_debug((not sys.flags.ignore_environment + and bool(os.environ.get('PYTHONASYNCIODEBUG')))) # In debug mode, if the execution of a callback or a step of a task # exceed this duration in seconds, the slow callback/task is logged. self.slow_callback_duration = 0.1 @@ -360,13 +360,18 @@ return if self._debug: logger.debug("Close %r", self) - self._closed = True - self._ready.clear() - self._scheduled.clear() - executor = self._default_executor - if executor is not None: - self._default_executor = None - executor.shutdown(wait=False) + try: + self._closed = True + self._ready.clear() + self._scheduled.clear() + executor = self._default_executor + if executor is not None: + self._default_executor = None + executor.shutdown(wait=False) + finally: + # It is important to unregister "sys.coroutine_wrapper" + # if it was registered. + self.set_debug(False) def is_closed(self): """Returns True if the event loop was closed.""" @@ -1199,3 +1204,27 @@ def set_debug(self, enabled): self._debug = enabled + wrapper = coroutines.debug_wrapper + + try: + set_wrapper = sys.set_coroutine_wrapper + except AttributeError: + pass + else: + current_wrapper = sys.get_coroutine_wrapper() + if enabled: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(True): cannot set debug coroutine " + "wrapper; another wrapper is already set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(wrapper) + else: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(False): cannot unset debug coroutine " + "wrapper; another wrapper was set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(None) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -14,6 +14,9 @@ from .log import logger +_PY35 = sys.version_info >= (3, 5) + + # Opcode of "yield from" instruction _YIELD_FROM = opcode.opmap['YIELD_FROM'] @@ -30,6 +33,27 @@ and bool(os.environ.get('PYTHONASYNCIODEBUG'))) +try: + types.coroutine +except AttributeError: + native_coroutine_support = False +else: + native_coroutine_support = True + +try: + _iscoroutinefunction = inspect.iscoroutinefunction +except AttributeError: + _iscoroutinefunction = lambda func: False + +try: + inspect.CO_COROUTINE +except AttributeError: + _is_native_coro_code = lambda code: False +else: + _is_native_coro_code = lambda code: (code.co_flags & + inspect.CO_COROUTINE) + + # Check for CPython issue #21209 def has_yield_from_bug(): class MyGen: @@ -54,16 +78,27 @@ del has_yield_from_bug +def debug_wrapper(gen): + # This function is called from 'sys.set_coroutine_wrapper'. + # We only wrap here coroutines defined via 'async def' syntax. + # Generator-based coroutines are wrapped in @coroutine + # decorator. + if _is_native_coro_code(gen.gi_code): + return CoroWrapper(gen, None) + else: + return gen + + class CoroWrapper: # Wrapper for coroutine object in _DEBUG mode. - def __init__(self, gen, func): - assert inspect.isgenerator(gen), gen + def __init__(self, gen, func=None): + assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen self.gen = gen - self.func = func + self.func = func # Used to unwrap @coroutine decorator self._source_traceback = traceback.extract_stack(sys._getframe(1)) - # __name__, __qualname__, __doc__ attributes are set by the coroutine() - # decorator + self.__name__ = getattr(gen, '__name__', None) + self.__qualname__ = getattr(gen, '__qualname__', None) def __repr__(self): coro_repr = _format_coroutine(self) @@ -75,6 +110,9 @@ def __iter__(self): return self + if _PY35: + __await__ = __iter__ # make compatible with 'await' expression + def __next__(self): return next(self.gen) @@ -133,6 +171,14 @@ If the coroutine is not yielded from before it is destroyed, an error message is logged. """ + is_coroutine = _iscoroutinefunction(func) + if is_coroutine and _is_native_coro_code(func.__code__): + # In Python 3.5 that's all we need to do for coroutines + # defiend with "async def". + # Wrapping in CoroWrapper will happen via + # 'sys.set_coroutine_wrapper' function. + return func + if inspect.isgeneratorfunction(func): coro = func else: @@ -144,18 +190,22 @@ return res if not _DEBUG: - wrapper = coro + if native_coroutine_support: + wrapper = types.coroutine(coro) + else: + wrapper = coro else: @functools.wraps(func) def wrapper(*args, **kwds): - w = CoroWrapper(coro(*args, **kwds), func) + w = CoroWrapper(coro(*args, **kwds), func=func) if w._source_traceback: del w._source_traceback[-1] - if hasattr(func, '__name__'): - w.__name__ = func.__name__ - if hasattr(func, '__qualname__'): - w.__qualname__ = func.__qualname__ - w.__doc__ = func.__doc__ + # Python < 3.5 does not implement __qualname__ + # on generator objects, so we set it manually. + # We use getattr as some callables (such as + # functools.partial may lack __qualname__). + w.__name__ = getattr(func, '__name__', None) + w.__qualname__ = getattr(func, '__qualname__', None) return w wrapper._is_coroutine = True # For iscoroutinefunction(). @@ -164,7 +214,8 @@ def iscoroutinefunction(func): """Return True if func is a decorated coroutine function.""" - return getattr(func, '_is_coroutine', False) + return (getattr(func, '_is_coroutine', False) or + _iscoroutinefunction(func)) _COROUTINE_TYPES = (types.GeneratorType, CoroWrapper) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -19,6 +19,7 @@ _FINISHED = 'FINISHED' _PY34 = sys.version_info >= (3, 4) +_PY35 = sys.version_info >= (3, 5) Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError @@ -387,6 +388,9 @@ assert self.done(), "yield from wasn't used with future" return self.result() # May raise too. + if _PY35: + __await__ = __iter__ # make compatible with 'await' expression + def wrap_future(fut, *, loop=None): """Wrap concurrent.futures.Future object.""" diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -11,6 +11,7 @@ import inspect import linecache import sys +import types import traceback import warnings import weakref @@ -73,7 +74,10 @@ super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - self._coro = iter(coro) # Use the iterator just in case. + if coro.__class__ is types.GeneratorType: + self._coro = coro + else: + self._coro = iter(coro) # Use the iterator just in case. self._fut_waiter = None self._must_cancel = False self._loop.call_soon(self._step) @@ -236,7 +240,7 @@ elif value is not None: result = coro.send(value) else: - result = next(coro) + result = coro.send(None) except StopIteration as exc: self.set_result(exc.value) except futures.CancelledError as exc: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -61,7 +61,8 @@ NotImplementedError, self.loop._make_write_pipe_transport, m, m) gen = self.loop._make_subprocess_transport(m, m, m, m, m, m, m) - self.assertRaises(NotImplementedError, next, iter(gen)) + with self.assertRaises(NotImplementedError): + gen.send(None) def test_close(self): self.assertFalse(self.loop.is_closed()) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1638,7 +1638,7 @@ return a def call(arg): - cw = asyncio.coroutines.CoroWrapper(foo(), foo) + cw = asyncio.coroutines.CoroWrapper(foo()) cw.send(None) try: cw.send(arg) @@ -1653,7 +1653,7 @@ def test_corowrapper_weakref(self): wd = weakref.WeakValueDictionary() def foo(): yield from [] - cw = asyncio.coroutines.CoroWrapper(foo(), foo) + cw = asyncio.coroutines.CoroWrapper(foo()) wd['cw'] = cw # Would fail without __weakref__ slot. cw.gen = None # Suppress warning from __del__. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 04:59:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 12 May 2015 02:59:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Defend_against?= =?utf-8?q?_a_mutation_during_comparison?= Message-ID: <20150512025929.1915.64652@psf.io> https://hg.python.org/cpython/rev/6df4045c7f85 changeset: 95966:6df4045c7f85 branch: 3.4 parent: 95964:957478e95b26 user: Raymond Hettinger date: Mon May 11 19:58:56 2015 -0700 summary: Defend against a mutation during comparison files: Modules/_heapqmodule.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -224,6 +224,11 @@ return item; } + if (PyList_GET_SIZE(heap) == 0) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; + } + returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 04:59:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 12 May 2015 02:59:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150512025930.25441.44670@psf.io> https://hg.python.org/cpython/rev/50698bb955b0 changeset: 95967:50698bb955b0 parent: 95965:44c1db190525 parent: 95966:6df4045c7f85 user: Raymond Hettinger date: Mon May 11 19:59:21 2015 -0700 summary: merge files: Modules/_heapqmodule.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -235,6 +235,11 @@ return item; } + if (PyList_GET_SIZE(heap) == 0) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; + } + returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 05:00:49 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 12 May 2015 03:00:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Defend_against?= =?utf-8?q?_a_mutation_during_comparison?= Message-ID: <20150512030049.7796.35758@psf.io> https://hg.python.org/cpython/rev/0e8a17f437b5 changeset: 95968:0e8a17f437b5 branch: 2.7 parent: 95950:0f7795edca65 user: Raymond Hettinger date: Mon May 11 20:00:25 2015 -0700 summary: Defend against a mutation during comparison files: Modules/_heapqmodule.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -244,6 +244,11 @@ return item; } + if (PyList_GET_SIZE(heap) == 0) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; + } + returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 05:03:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:03:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_PEP_0492_--_Coroutines_wit?= =?utf-8?q?h_async_and_await_syntax=2E_Issue_=2324017=2E?= Message-ID: <20150512030320.63264.35493@psf.io> https://hg.python.org/cpython/rev/eeeb666a5365 changeset: 95969:eeeb666a5365 parent: 95967:50698bb955b0 user: Yury Selivanov date: Mon May 11 22:57:16 2015 -0400 summary: PEP 0492 -- Coroutines with async and await syntax. Issue #24017. files: Doc/includes/typestruct.h | 2 +- Doc/library/dis.rst | 42 +- Grammar/Grammar | 11 +- Include/Python-ast.h | 59 +- Include/ceval.h | 2 + Include/code.h | 5 + Include/genobject.h | 7 + Include/graminit.h | 155 +- Include/object.h | 11 +- Include/opcode.h | 130 +- Include/pyerrors.h | 1 + Include/pystate.h | 2 + Include/token.h | 6 +- Include/typeslots.h | 3 + Lib/_collections_abc.py | 76 +- Lib/dis.py | 2 + Lib/inspect.py | 26 +- Lib/lib2to3/Grammar.txt | 8 +- Lib/lib2to3/pgen2/token.py | 6 +- Lib/lib2to3/pgen2/tokenize.py | 63 +- Lib/lib2to3/tests/test_parser.py | 32 +- Lib/opcode.py | 10 +- Lib/test/badsyntax_async1.py | 3 + Lib/test/badsyntax_async2.py | 3 + Lib/test/badsyntax_async3.py | 2 + Lib/test/badsyntax_async4.py | 2 + Lib/test/badsyntax_async5.py | 2 + Lib/test/badsyntax_async6.py | 2 + Lib/test/badsyntax_async7.py | 2 + Lib/test/badsyntax_async8.py | 2 + Lib/test/badsyntax_async9.py | 2 + Lib/test/exception_hierarchy.txt | 1 + Lib/test/test_ast.py | 9 + Lib/test/test_collections.py | 80 + Lib/test/test_coroutines.py | 862 +++ Lib/test/test_dis.py | 46 +- Lib/test/test_grammar.py | 87 + Lib/test/test_inspect.py | 72 +- Lib/test/test_minidom.py | 15 + Lib/test/test_parser.py | 16 + Lib/test/test_pickle.py | 4 +- Lib/test/test_sys.py | 4 +- Lib/test/test_tokenize.py | 186 + Lib/test/test_types.py | 35 +- Lib/token.py | 6 +- Lib/tokenize.py | 56 +- Lib/types.py | 24 + Lib/xml/dom/xmlbuilder.py | 26 +- Modules/_testcapimodule.c | 97 + Modules/parsermodule.c | 117 +- Objects/exceptions.c | 9 + Objects/frameobject.c | 8 +- Objects/genobject.c | 102 +- Objects/typeobject.c | 91 +- Objects/typeslots.inc | 3 + Objects/typeslots.py | 2 + Parser/Python.asdl | 8 +- Parser/tokenizer.c | 68 + Parser/tokenizer.h | 7 + Python/Python-ast.c | 473 + Python/ast.c | 174 +- Python/ceval.c | 231 +- Python/compile.c | 290 +- Python/graminit.c | 3110 +++++----- Python/importlib.h | 3484 ++++++------ Python/importlib_external.h | 4765 +++++++++-------- Python/opcode_targets.h | 14 +- Python/peephole.c | 3 + Python/pystate.c | 4 + Python/symtable.c | 49 +- Python/sysmodule.c | 47 + Tools/parser/unparse.py | 32 +- 72 files changed, 9459 insertions(+), 5937 deletions(-) diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -9,7 +9,7 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - void *tp_reserved; + PyAsyncMethods *tp_as_async; reprfunc tp_repr; /* Method suites for standard classes */ diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -508,6 +508,38 @@ Implements ``del TOS1[TOS]``. +**Coroutines opcodes** + +.. opcode:: GET_AWAITABLE + + Implements ``TOS = get_awaitable(TOS)``; where ``get_awaitable(o)`` + returns ``o`` if ``o`` is a coroutine object; or resolved ``o.__await__``. + + +.. opcode:: GET_AITER + + Implements ``TOS = get_awaitable(TOS.__aiter__())``. See ``GET_AWAITABLE`` + for details about ``get_awaitable`` + + +.. opcode:: GET_ANEXT + + Implements ``PUSH(get_awaitable(TOS.__anext__()))``. See ``GET_AWAITABLE`` + for details about ``get_awaitable`` + + +.. 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. + + +.. opcode:: SETUP_ASYNC_WITH + + Creates a new frame object. + + + **Miscellaneous opcodes** .. opcode:: PRINT_EXPR @@ -612,7 +644,7 @@ :opcode:`UNPACK_SEQUENCE`). -.. opcode:: WITH_CLEANUP +.. 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 @@ -624,7 +656,13 @@ * (SECOND, THIRD, FOURTH) = exc_info() In the last case, ``TOS(SECOND, THIRD, FOURTH)`` is called, otherwise - ``TOS(None, None, None)``. In addition, TOS is removed from the stack. + ``TOS(None, None, None)``. Pushes SECOND and result of the call + to the stack. + + +.. opcode:: WITH_CLEANUP_FINISH + + Pops exception type and result of 'exit' function call from the stack. If the stack represents an exception, *and* the function call returns a 'true' value, this information is "zapped" and replaced with a single diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -21,8 +21,11 @@ decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ -decorated: decorators (classdef | funcdef) +decorated: decorators (classdef | funcdef | async_funcdef) + +async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite + parameters: '(' [typedargslist] ')' typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] @@ -65,7 +68,8 @@ nonlocal_stmt: 'nonlocal' NAME (',' NAME)* assert_stmt: 'assert' test [',' test] -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt +async_stmt: ASYNC (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] @@ -99,7 +103,8 @@ arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power -power: atom trailer* ['**' factor] +power: atom_expr ['**' factor] +atom_expr: [AWAIT] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | diff --git a/Include/Python-ast.h b/Include/Python-ast.h --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -63,12 +63,13 @@ } v; }; -enum _stmt_kind {FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3, - Delete_kind=4, Assign_kind=5, AugAssign_kind=6, For_kind=7, - While_kind=8, If_kind=9, With_kind=10, Raise_kind=11, - Try_kind=12, Assert_kind=13, Import_kind=14, - ImportFrom_kind=15, Global_kind=16, Nonlocal_kind=17, - Expr_kind=18, Pass_kind=19, Break_kind=20, Continue_kind=21}; +enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3, + Return_kind=4, Delete_kind=5, Assign_kind=6, + AugAssign_kind=7, For_kind=8, AsyncFor_kind=9, While_kind=10, + If_kind=11, With_kind=12, AsyncWith_kind=13, Raise_kind=14, + Try_kind=15, Assert_kind=16, Import_kind=17, + ImportFrom_kind=18, Global_kind=19, Nonlocal_kind=20, + Expr_kind=21, Pass_kind=22, Break_kind=23, Continue_kind=24}; struct _stmt { enum _stmt_kind kind; union { @@ -82,6 +83,14 @@ struct { identifier name; + arguments_ty args; + asdl_seq *body; + asdl_seq *decorator_list; + expr_ty returns; + } AsyncFunctionDef; + + struct { + identifier name; asdl_seq *bases; asdl_seq *keywords; asdl_seq *body; @@ -115,6 +124,13 @@ } For; struct { + expr_ty target; + expr_ty iter; + asdl_seq *body; + asdl_seq *orelse; + } AsyncFor; + + struct { expr_ty test; asdl_seq *body; asdl_seq *orelse; @@ -132,6 +148,11 @@ } With; struct { + asdl_seq *items; + asdl_seq *body; + } AsyncWith; + + struct { expr_ty exc; expr_ty cause; } Raise; @@ -178,11 +199,11 @@ enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4, IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8, SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11, - Yield_kind=12, YieldFrom_kind=13, Compare_kind=14, - Call_kind=15, Num_kind=16, Str_kind=17, Bytes_kind=18, - NameConstant_kind=19, Ellipsis_kind=20, Attribute_kind=21, - Subscript_kind=22, Starred_kind=23, Name_kind=24, - List_kind=25, Tuple_kind=26}; + Await_kind=12, Yield_kind=13, YieldFrom_kind=14, + Compare_kind=15, Call_kind=16, Num_kind=17, Str_kind=18, + Bytes_kind=19, NameConstant_kind=20, Ellipsis_kind=21, + Attribute_kind=22, Subscript_kind=23, Starred_kind=24, + Name_kind=25, List_kind=26, Tuple_kind=27}; struct _expr { enum _expr_kind kind; union { @@ -245,6 +266,10 @@ struct { expr_ty value; + } Await; + + struct { + expr_ty value; } Yield; struct { @@ -402,6 +427,10 @@ stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorator_list, expr_ty returns, int lineno, int col_offset, PyArena *arena); +#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) +stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * + body, asdl_seq * decorator_list, expr_ty returns, + int lineno, int col_offset, PyArena *arena); #define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * body, asdl_seq * decorator_list, int lineno, @@ -420,6 +449,9 @@ #define For(a0, a1, a2, a3, a4, a5, a6) _Py_For(a0, a1, a2, a3, a4, a5, a6) stmt_ty _Py_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena); +#define AsyncFor(a0, a1, a2, a3, a4, a5, a6) _Py_AsyncFor(a0, a1, a2, a3, a4, a5, a6) +stmt_ty _Py_AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * + orelse, int lineno, int col_offset, PyArena *arena); #define While(a0, a1, a2, a3, a4, a5) _Py_While(a0, a1, a2, a3, a4, a5) stmt_ty _Py_While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena); @@ -429,6 +461,9 @@ #define With(a0, a1, a2, a3, a4) _Py_With(a0, a1, a2, a3, a4) stmt_ty _Py_With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, PyArena *arena); +#define AsyncWith(a0, a1, a2, a3, a4) _Py_AsyncWith(a0, a1, a2, a3, a4) +stmt_ty _Py_AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int + col_offset, PyArena *arena); #define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4) stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena); @@ -491,6 +526,8 @@ #define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4) expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena *arena); +#define Await(a0, a1, a2, a3) _Py_Await(a0, a1, a2, a3) +expr_ty _Py_Await(expr_ty value, int lineno, int col_offset, PyArena *arena); #define Yield(a0, a1, a2, a3) _Py_Yield(a0, a1, a2, a3) expr_ty _Py_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena); #define YieldFrom(a0, a1, a2, a3) _Py_YieldFrom(a0, a1, a2, a3) diff --git a/Include/ceval.h b/Include/ceval.h --- a/Include/ceval.h +++ b/Include/ceval.h @@ -23,6 +23,8 @@ #ifndef Py_LIMITED_API PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); +PyAPI_FUNC(void) PyEval_SetCoroutineWrapper(PyObject *wrapper); +PyAPI_FUNC(PyObject *) PyEval_GetCoroutineWrapper(); #endif struct _frame; /* Avoid including frameobject.h */ diff --git a/Include/code.h b/Include/code.h --- a/Include/code.h +++ b/Include/code.h @@ -51,6 +51,11 @@ */ #define CO_NOFREE 0x0040 +/* The CO_COROUTINE flag is set for coroutine functions (defined with + ``async def`` keywords) */ +#define CO_COROUTINE 0x0080 +#define CO_ITERABLE_COROUTINE 0x0100 + /* These are no longer used. */ #if 0 #define CO_GENERATOR_ALLOWED 0x1000 diff --git a/Include/genobject.h b/Include/genobject.h --- a/Include/genobject.h +++ b/Include/genobject.h @@ -38,6 +38,12 @@ #define PyGen_Check(op) PyObject_TypeCheck(op, &PyGen_Type) #define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type) +#define PyGen_CheckCoroutineExact(op) (PyGen_CheckExact(op) && \ + (((PyCodeObject*) \ + ((PyGenObject*)op)->gi_code) \ + ->co_flags & (CO_ITERABLE_COROUTINE | \ + CO_COROUTINE))) + PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *); PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *, PyObject *name, PyObject *qualname); @@ -46,6 +52,7 @@ PyObject *_PyGen_Send(PyGenObject *, PyObject *); PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); +PyObject *_PyGen_GetAwaitableIter(PyObject *o); #ifdef __cplusplus } diff --git a/Include/graminit.h b/Include/graminit.h --- a/Include/graminit.h +++ b/Include/graminit.h @@ -6,79 +6,82 @@ #define decorator 259 #define decorators 260 #define decorated 261 -#define funcdef 262 -#define parameters 263 -#define typedargslist 264 -#define tfpdef 265 -#define varargslist 266 -#define vfpdef 267 -#define stmt 268 -#define simple_stmt 269 -#define small_stmt 270 -#define expr_stmt 271 -#define testlist_star_expr 272 -#define augassign 273 -#define del_stmt 274 -#define pass_stmt 275 -#define flow_stmt 276 -#define break_stmt 277 -#define continue_stmt 278 -#define return_stmt 279 -#define yield_stmt 280 -#define raise_stmt 281 -#define import_stmt 282 -#define import_name 283 -#define import_from 284 -#define import_as_name 285 -#define dotted_as_name 286 -#define import_as_names 287 -#define dotted_as_names 288 -#define dotted_name 289 -#define global_stmt 290 -#define nonlocal_stmt 291 -#define assert_stmt 292 -#define compound_stmt 293 -#define if_stmt 294 -#define while_stmt 295 -#define for_stmt 296 -#define try_stmt 297 -#define with_stmt 298 -#define with_item 299 -#define except_clause 300 -#define suite 301 -#define test 302 -#define test_nocond 303 -#define lambdef 304 -#define lambdef_nocond 305 -#define or_test 306 -#define and_test 307 -#define not_test 308 -#define comparison 309 -#define comp_op 310 -#define star_expr 311 -#define expr 312 -#define xor_expr 313 -#define and_expr 314 -#define shift_expr 315 -#define arith_expr 316 -#define term 317 -#define factor 318 -#define power 319 -#define atom 320 -#define testlist_comp 321 -#define trailer 322 -#define subscriptlist 323 -#define subscript 324 -#define sliceop 325 -#define exprlist 326 -#define testlist 327 -#define dictorsetmaker 328 -#define classdef 329 -#define arglist 330 -#define argument 331 -#define comp_iter 332 -#define comp_for 333 -#define comp_if 334 -#define encoding_decl 335 -#define yield_expr 336 -#define yield_arg 337 +#define async_funcdef 262 +#define funcdef 263 +#define parameters 264 +#define typedargslist 265 +#define tfpdef 266 +#define varargslist 267 +#define vfpdef 268 +#define stmt 269 +#define simple_stmt 270 +#define small_stmt 271 +#define expr_stmt 272 +#define testlist_star_expr 273 +#define augassign 274 +#define del_stmt 275 +#define pass_stmt 276 +#define flow_stmt 277 +#define break_stmt 278 +#define continue_stmt 279 +#define return_stmt 280 +#define yield_stmt 281 +#define raise_stmt 282 +#define import_stmt 283 +#define import_name 284 +#define import_from 285 +#define import_as_name 286 +#define dotted_as_name 287 +#define import_as_names 288 +#define dotted_as_names 289 +#define dotted_name 290 +#define global_stmt 291 +#define nonlocal_stmt 292 +#define assert_stmt 293 +#define compound_stmt 294 +#define async_stmt 295 +#define if_stmt 296 +#define while_stmt 297 +#define for_stmt 298 +#define try_stmt 299 +#define with_stmt 300 +#define with_item 301 +#define except_clause 302 +#define suite 303 +#define test 304 +#define test_nocond 305 +#define lambdef 306 +#define lambdef_nocond 307 +#define or_test 308 +#define and_test 309 +#define not_test 310 +#define comparison 311 +#define comp_op 312 +#define star_expr 313 +#define expr 314 +#define xor_expr 315 +#define and_expr 316 +#define shift_expr 317 +#define arith_expr 318 +#define term 319 +#define factor 320 +#define power 321 +#define atom_expr 322 +#define atom 323 +#define testlist_comp 324 +#define trailer 325 +#define subscriptlist 326 +#define subscript 327 +#define sliceop 328 +#define exprlist 329 +#define testlist 330 +#define dictorsetmaker 331 +#define classdef 332 +#define arglist 333 +#define argument 334 +#define comp_iter 335 +#define comp_for 336 +#define comp_if 337 +#define encoding_decl 338 +#define yield_expr 339 +#define yield_arg 340 diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -173,6 +173,9 @@ typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*getawaitablefunc) (PyObject *); +typedef PyObject *(*getaiterfunc) (PyObject *); +typedef PyObject *(*aiternextfunc) (PyObject *); #ifndef Py_LIMITED_API /* buffer interface */ @@ -301,6 +304,11 @@ objobjargproc mp_ass_subscript; } PyMappingMethods; +typedef struct { + getawaitablefunc am_await; + getaiterfunc am_aiter; + aiternextfunc am_anext; +} PyAsyncMethods; typedef struct { getbufferproc bf_getbuffer; @@ -346,7 +354,7 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - void *tp_reserved; /* formerly known as tp_compare */ + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ reprfunc tp_repr; /* Method suites for standard classes */ @@ -453,6 +461,7 @@ /* Note: there's a dependency on the order of these members in slotptr() in typeobject.c . */ PyTypeObject ht_type; + PyAsyncMethods as_async; PyNumberMethods as_number; PyMappingMethods as_mapping; PySequenceMethods as_sequence; /* as_sequence comes after as_mapping, diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -7,68 +7,73 @@ /* Instruction opcodes for compiled code */ -#define POP_TOP 1 -#define ROT_TWO 2 -#define ROT_THREE 3 -#define DUP_TOP 4 -#define DUP_TOP_TWO 5 -#define NOP 9 -#define UNARY_POSITIVE 10 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define BINARY_MATRIX_MULTIPLY 16 -#define INPLACE_MATRIX_MULTIPLY 17 -#define BINARY_POWER 19 -#define BINARY_MULTIPLY 20 -#define BINARY_MODULO 22 -#define BINARY_ADD 23 -#define BINARY_SUBTRACT 24 -#define BINARY_SUBSCR 25 -#define BINARY_FLOOR_DIVIDE 26 -#define BINARY_TRUE_DIVIDE 27 -#define INPLACE_FLOOR_DIVIDE 28 -#define INPLACE_TRUE_DIVIDE 29 -#define STORE_MAP 54 -#define INPLACE_ADD 55 -#define INPLACE_SUBTRACT 56 -#define INPLACE_MULTIPLY 57 -#define INPLACE_MODULO 59 -#define STORE_SUBSCR 60 -#define DELETE_SUBSCR 61 -#define BINARY_LSHIFT 62 -#define BINARY_RSHIFT 63 -#define BINARY_AND 64 -#define BINARY_XOR 65 -#define BINARY_OR 66 -#define INPLACE_POWER 67 -#define GET_ITER 68 -#define PRINT_EXPR 70 -#define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 -#define INPLACE_LSHIFT 75 -#define INPLACE_RSHIFT 76 -#define INPLACE_AND 77 -#define INPLACE_XOR 78 -#define INPLACE_OR 79 -#define BREAK_LOOP 80 -#define WITH_CLEANUP 81 -#define RETURN_VALUE 83 -#define IMPORT_STAR 84 -#define YIELD_VALUE 86 -#define POP_BLOCK 87 -#define END_FINALLY 88 -#define POP_EXCEPT 89 -#define HAVE_ARGUMENT 90 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 +#define POP_TOP 1 +#define ROT_TWO 2 +#define ROT_THREE 3 +#define DUP_TOP 4 +#define DUP_TOP_TWO 5 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_MATRIX_MULTIPLY 16 +#define INPLACE_MATRIX_MULTIPLY 17 +#define BINARY_POWER 19 +#define BINARY_MULTIPLY 20 +#define BINARY_MODULO 22 +#define BINARY_ADD 23 +#define BINARY_SUBTRACT 24 +#define BINARY_SUBSCR 25 +#define BINARY_FLOOR_DIVIDE 26 +#define BINARY_TRUE_DIVIDE 27 +#define INPLACE_FLOOR_DIVIDE 28 +#define INPLACE_TRUE_DIVIDE 29 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define STORE_MAP 54 +#define INPLACE_ADD 55 +#define INPLACE_SUBTRACT 56 +#define INPLACE_MULTIPLY 57 +#define INPLACE_MODULO 59 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define BINARY_LSHIFT 62 +#define BINARY_RSHIFT 63 +#define BINARY_AND 64 +#define BINARY_XOR 65 +#define BINARY_OR 66 +#define INPLACE_POWER 67 +#define GET_ITER 68 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define YIELD_FROM 72 +#define GET_AWAITABLE 73 +#define INPLACE_LSHIFT 75 +#define INPLACE_RSHIFT 76 +#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 +#define IMPORT_STAR 84 +#define YIELD_VALUE 86 +#define POP_BLOCK 87 +#define END_FINALLY 88 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 #define LOAD_CONST 100 #define LOAD_NAME 101 #define BUILD_TUPLE 102 @@ -116,6 +121,7 @@ #define BUILD_MAP_UNPACK_WITH_CALL 151 #define BUILD_TUPLE_UNPACK 152 #define BUILD_SET_UNPACK 153 +#define SETUP_ASYNC_WITH 154 /* 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/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -147,6 +147,7 @@ PyAPI_DATA(PyObject *) PyExc_BaseException; PyAPI_DATA(PyObject *) PyExc_Exception; +PyAPI_DATA(PyObject *) PyExc_StopAsyncIteration; PyAPI_DATA(PyObject *) PyExc_StopIteration; PyAPI_DATA(PyObject *) PyExc_GeneratorExit; PyAPI_DATA(PyObject *) PyExc_ArithmeticError; diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -134,6 +134,8 @@ void (*on_delete)(void *); void *on_delete_data; + PyObject *coroutine_wrapper; + /* XXX signal handlers should also be here */ } PyThreadState; diff --git a/Include/token.h b/Include/token.h --- a/Include/token.h +++ b/Include/token.h @@ -64,8 +64,10 @@ #define ELLIPSIS 52 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ #define OP 53 -#define ERRORTOKEN 54 -#define N_TOKENS 55 +#define AWAIT 54 +#define ASYNC 55 +#define ERRORTOKEN 56 +#define N_TOKENS 57 /* Special definitions for cooperation with parser */ diff --git a/Include/typeslots.h b/Include/typeslots.h --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -76,3 +76,6 @@ #define Py_tp_free 74 #define Py_nb_matrix_multiply 75 #define Py_nb_inplace_matrix_multiply 76 +#define Py_am_await 77 +#define Py_am_aiter 78 +#define Py_am_anext 79 diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -9,7 +9,8 @@ from abc import ABCMeta, abstractmethod import sys -__all__ = ["Hashable", "Iterable", "Iterator", "Generator", +__all__ = ["Awaitable", "Coroutine", + "Hashable", "Iterable", "Iterator", "Generator", "Sized", "Container", "Callable", "Set", "MutableSet", "Mapping", "MutableMapping", @@ -74,6 +75,79 @@ return NotImplemented +class _CoroutineMeta(ABCMeta): + + def __instancecheck__(cls, instance): + # 0x80 = CO_COROUTINE + # 0x100 = CO_ITERABLE_COROUTINE + # We don't want to import 'inspect' module, as + # a dependency for 'collections.abc'. + CO_COROUTINES = 0x80 | 0x100 + + if (isinstance(instance, generator) and + instance.gi_code.co_flags & CO_COROUTINES): + + return True + + return super().__instancecheck__(instance) + + +class Coroutine(metaclass=_CoroutineMeta): + + __slots__ = () + + @abstractmethod + def send(self, value): + """Send a value into the coroutine. + Return next yielded value or raise StopIteration. + """ + raise StopIteration + + @abstractmethod + def throw(self, typ, val=None, tb=None): + """Raise an exception in the coroutine. + Return next yielded value or raise StopIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + def close(self): + """Raise GeneratorExit inside coroutine. + """ + try: + self.throw(GeneratorExit) + except (GeneratorExit, StopIteration): + pass + else: + raise RuntimeError("coroutine ignored GeneratorExit") + + +class Awaitable(metaclass=_CoroutineMeta): + + __slots__ = () + + @abstractmethod + def __await__(self): + yield + + @classmethod + def __subclasshook__(cls, C): + if cls is Awaitable: + for B in C.__mro__: + if "__await__" in B.__dict__: + if B.__dict__["__await__"]: + return True + break + return NotImplemented + +Awaitable.register(Coroutine) + + class Iterable(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/dis.py b/Lib/dis.py --- a/Lib/dis.py +++ b/Lib/dis.py @@ -84,6 +84,8 @@ 16: "NESTED", 32: "GENERATOR", 64: "NOFREE", + 128: "COROUTINE", + 256: "ITERABLE_COROUTINE", } def pretty_flags(flags): diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -33,6 +33,7 @@ import ast import dis +import collections.abc import enum import importlib.machinery import itertools @@ -174,7 +175,22 @@ See help(isfunction) for attributes listing.""" return bool((isfunction(object) or ismethod(object)) and - object.__code__.co_flags & CO_GENERATOR) + object.__code__.co_flags & CO_GENERATOR and + not object.__code__.co_flags & CO_COROUTINE) + +def iscoroutinefunction(object): + """Return true if the object is a coroutine function. + + Coroutine functions are defined with "async def" syntax, + or generators decorated with "types.coroutine". + """ + return bool((isfunction(object) or ismethod(object)) and + object.__code__.co_flags & (CO_ITERABLE_COROUTINE | + CO_COROUTINE)) + +def isawaitable(object): + """Return true if the object can be used in "await" expression.""" + return isinstance(object, collections.abc.Awaitable) def isgenerator(object): """Return true if the object is a generator. @@ -191,7 +207,13 @@ send resumes the generator and "sends" a value that becomes the result of the current yield-expression throw used to raise an exception inside the generator""" - return isinstance(object, types.GeneratorType) + return (isinstance(object, types.GeneratorType) and + not object.gi_code.co_flags & CO_COROUTINE) + +def iscoroutine(object): + """Return true if the object is a coroutine.""" + return (isinstance(object, types.GeneratorType) and + object.gi_code.co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) def istraceback(object): """Return true if the object is a traceback. diff --git a/Lib/lib2to3/Grammar.txt b/Lib/lib2to3/Grammar.txt --- a/Lib/lib2to3/Grammar.txt +++ b/Lib/lib2to3/Grammar.txt @@ -33,7 +33,8 @@ decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ -decorated: decorators (classdef | funcdef) +decorated: decorators (classdef | funcdef | async_funcdef) +async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: ((tfpdef ['=' test] ',')* @@ -82,7 +83,8 @@ exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt +async_stmt: ASYNC (funcdef | with_stmt | for_stmt) if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] @@ -121,7 +123,7 @@ arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power -power: atom trailer* ['**' factor] +power: [AWAIT] atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictsetmaker] '}' | diff --git a/Lib/lib2to3/pgen2/token.py b/Lib/lib2to3/pgen2/token.py --- a/Lib/lib2to3/pgen2/token.py +++ b/Lib/lib2to3/pgen2/token.py @@ -62,8 +62,10 @@ COMMENT = 53 NL = 54 RARROW = 55 -ERRORTOKEN = 56 -N_TOKENS = 57 +AWAIT = 56 +ASYNC = 57 +ERRORTOKEN = 58 +N_TOKENS = 59 NT_OFFSET = 256 #--end constants-- diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -220,7 +220,7 @@ for tok in iterable: toknum, tokval = tok[:2] - if toknum in (NAME, NUMBER): + if toknum in (NAME, NUMBER, ASYNC, AWAIT): tokval += ' ' if toknum == INDENT: @@ -366,6 +366,10 @@ contline = None indents = [0] + # 'stashed' and 'ctx' are used for async/await parsing + stashed = None + ctx = [('sync', 0)] + while 1: # loop over lines in stream try: line = readline() @@ -406,6 +410,10 @@ pos = pos + 1 if pos == max: break + if stashed: + yield stashed + stashed = None + if line[pos] in '#\r\n': # skip comments or blank lines if line[pos] == '#': comment_token = line[pos:].rstrip('\r\n') @@ -449,9 +457,15 @@ newline = NEWLINE if parenlev > 0: newline = NL + if stashed: + yield stashed + stashed = None yield (newline, token, spos, epos, line) elif initial == '#': assert not token.endswith("\n") + if stashed: + yield stashed + stashed = None yield (COMMENT, token, spos, epos, line) elif token in triple_quoted: endprog = endprogs[token] @@ -459,6 +473,9 @@ if endmatch: # all on one line pos = endmatch.end(0) token = line[start:pos] + if stashed: + yield stashed + stashed = None yield (STRING, token, spos, (lnum, pos), line) else: strstart = (lnum, start) # multiple lines @@ -476,22 +493,64 @@ contline = line break else: # ordinary string + if stashed: + yield stashed + stashed = None yield (STRING, token, spos, epos, line) elif initial in namechars: # ordinary name - yield (NAME, token, spos, epos, line) + if token in ('async', 'await'): + if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + yield (ASYNC if token == 'async' else AWAIT, + token, spos, epos, line) + continue + + tok = (NAME, token, spos, epos, line) + if token == 'async' and not stashed: + stashed = tok + continue + + if token == 'def': + if (stashed + and stashed[0] == NAME + and stashed[1] == 'async'): + + ctx.append(('async', indents[-1])) + + yield (ASYNC, stashed[1], + stashed[2], stashed[3], + stashed[4]) + stashed = None + else: + ctx.append(('sync', indents[-1])) + + if stashed: + yield stashed + stashed = None + + yield tok elif initial == '\\': # continued stmt # This yield is new; needed for better idempotency: + if stashed: + yield stashed + stashed = None yield (NL, token, spos, (lnum, pos), line) continued = 1 else: if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 + if stashed: + yield stashed + stashed = None yield (OP, token, spos, epos, line) else: yield (ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos = pos + 1 + if stashed: + yield stashed + stashed = None + for indent in indents[1:]: # pop remaining indent levels yield (DEDENT, '', (lnum, 0), (lnum, 0), '') yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '') diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -55,12 +55,42 @@ class TestYieldFrom(GrammarTest): - def test_matrix_multiplication_operator(self): + def test_yield_from(self): self.validate("yield from x") self.validate("(yield from x) + y") self.invalid_syntax("yield from") +class TestAsyncAwait(GrammarTest): + def test_await_expr(self): + self.validate("""async def foo(): + await x + """) + + self.invalid_syntax("await x") + self.invalid_syntax("""def foo(): + await x""") + + def test_async_var(self): + self.validate("""async = 1""") + self.validate("""await = 1""") + self.validate("""def async(): pass""") + + def test_async_with(self): + self.validate("""async def foo(): + async for a in b: pass""") + + self.invalid_syntax("""def foo(): + async for a in b: pass""") + + def test_async_for(self): + self.validate("""async def foo(): + async with a: pass""") + + self.invalid_syntax("""def foo(): + async with a: pass""") + + class TestRaiseChanges(GrammarTest): def test_2x_style_1(self): self.validate("raise") diff --git a/Lib/opcode.py b/Lib/opcode.py --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -85,6 +85,10 @@ def_op('INPLACE_FLOOR_DIVIDE', 28) def_op('INPLACE_TRUE_DIVIDE', 29) +def_op('GET_AITER', 50) +def_op('GET_ANEXT', 51) +def_op('BEFORE_ASYNC_WITH', 52) + def_op('STORE_MAP', 54) def_op('INPLACE_ADD', 55) def_op('INPLACE_SUBTRACT', 56) @@ -104,6 +108,7 @@ def_op('PRINT_EXPR', 70) def_op('LOAD_BUILD_CLASS', 71) def_op('YIELD_FROM', 72) +def_op('GET_AWAITABLE', 73) def_op('INPLACE_LSHIFT', 75) def_op('INPLACE_RSHIFT', 76) @@ -111,7 +116,8 @@ def_op('INPLACE_XOR', 78) def_op('INPLACE_OR', 79) def_op('BREAK_LOOP', 80) -def_op('WITH_CLEANUP', 81) +def_op('WITH_CLEANUP_START', 81) +def_op('WITH_CLEANUP_FINISH', 82) def_op('RETURN_VALUE', 83) def_op('IMPORT_STAR', 84) @@ -197,6 +203,8 @@ def_op('LOAD_CLASSDEREF', 148) hasfree.append(148) +jrel_op('SETUP_ASYNC_WITH', 154) + def_op('EXTENDED_ARG', 144) EXTENDED_ARG = 144 diff --git a/Lib/test/badsyntax_async1.py b/Lib/test/badsyntax_async1.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async1.py @@ -0,0 +1,3 @@ +async def foo(): + def foo(a=await something()): + pass diff --git a/Lib/test/badsyntax_async2.py b/Lib/test/badsyntax_async2.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async2.py @@ -0,0 +1,3 @@ +async def foo(): + def foo(a:await something()): + pass diff --git a/Lib/test/badsyntax_async3.py b/Lib/test/badsyntax_async3.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async3.py @@ -0,0 +1,2 @@ +async def foo(): + [i async for i in els] diff --git a/Lib/test/badsyntax_async4.py b/Lib/test/badsyntax_async4.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async4.py @@ -0,0 +1,2 @@ +async def foo(): + async def foo(): await something() diff --git a/Lib/test/badsyntax_async5.py b/Lib/test/badsyntax_async5.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async5.py @@ -0,0 +1,2 @@ +def foo(): + await something() diff --git a/Lib/test/badsyntax_async6.py b/Lib/test/badsyntax_async6.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async6.py @@ -0,0 +1,2 @@ +async def foo(): + yield diff --git a/Lib/test/badsyntax_async7.py b/Lib/test/badsyntax_async7.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async7.py @@ -0,0 +1,2 @@ +async def foo(): + yield from [] diff --git a/Lib/test/badsyntax_async8.py b/Lib/test/badsyntax_async8.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async8.py @@ -0,0 +1,2 @@ +async def foo(): + await await fut diff --git a/Lib/test/badsyntax_async9.py b/Lib/test/badsyntax_async9.py new file mode 100644 --- /dev/null +++ b/Lib/test/badsyntax_async9.py @@ -0,0 +1,2 @@ +async def foo(): + await diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -4,6 +4,7 @@ +-- GeneratorExit +-- Exception +-- StopIteration + +-- StopAsyncIteration +-- ArithmeticError | +-- FloatingPointError | +-- OverflowError diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -106,6 +106,12 @@ "{r for l in x if g}", # setcomp with naked tuple "{r for l,m in x}", + # AsyncFunctionDef + "async def f():\n await something()", + # AsyncFor + "async def f():\n async for e in i: 1\n else: 2", + # AsyncWith + "async def f():\n async with a as b: 1", ] # These are compiled through "single" @@ -974,6 +980,9 @@ ('Module', [('Expr', (1, 0), ('DictComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [])]))]), ('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))])]))]), ('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [])]))]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Await', (2, 1), ('Call', (2, 7), ('Name', (2, 7), 'something', ('Load',)), [], [])))], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None)]), ] single_results = [ ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -11,9 +11,11 @@ import keyword import re import sys +import types from collections import UserDict from collections import ChainMap from collections import deque +from collections.abc import Awaitable, Coroutine from collections.abc import Hashable, Iterable, Iterator, Generator from collections.abc import Sized, Container, Callable from collections.abc import Set, MutableSet @@ -446,6 +448,84 @@ class TestOneTrickPonyABCs(ABCTestCase): + def test_Awaitable(self): + def gen(): + yield + + @types.coroutine + def coro(): + yield + + async def new_coro(): + pass + + class Bar: + def __await__(self): + yield + + class MinimalCoro(Coroutine): + def send(self, value): + return value + def throw(self, typ, val=None, tb=None): + super().throw(typ, val, tb) + + non_samples = [None, int(), gen(), object()] + for x in non_samples: + self.assertNotIsInstance(x, Awaitable) + self.assertFalse(issubclass(type(x), Awaitable), repr(type(x))) + + samples = [Bar(), MinimalCoro()] + for x in samples: + self.assertIsInstance(x, Awaitable) + self.assertTrue(issubclass(type(x), Awaitable)) + + c = coro() + self.assertIsInstance(c, Awaitable) + c.close() # awoid RuntimeWarning that coro() was not awaited + + c = new_coro() + self.assertIsInstance(c, Awaitable) + c.close() # awoid RuntimeWarning that coro() was not awaited + + def test_Coroutine(self): + def gen(): + yield + + @types.coroutine + def coro(): + yield + + async def new_coro(): + pass + + class Bar: + def __await__(self): + yield + + class MinimalCoro(Coroutine): + def send(self, value): + return value + def throw(self, typ, val=None, tb=None): + super().throw(typ, val, tb) + + non_samples = [None, int(), gen(), object(), Bar()] + for x in non_samples: + self.assertNotIsInstance(x, Coroutine) + self.assertFalse(issubclass(type(x), Coroutine), repr(type(x))) + + samples = [MinimalCoro()] + for x in samples: + self.assertIsInstance(x, Awaitable) + self.assertTrue(issubclass(type(x), Awaitable)) + + c = coro() + self.assertIsInstance(c, Coroutine) + c.close() # awoid RuntimeWarning that coro() was not awaited + + c = new_coro() + self.assertIsInstance(c, Coroutine) + c.close() # awoid RuntimeWarning that coro() was not awaited + def test_Hashable(self): # Check some non-hashables non_samples = [bytearray(), list(), set(), dict()] diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_coroutines.py @@ -0,0 +1,862 @@ +import contextlib +import gc +import sys +import types +import unittest +import warnings +from test import support + + +class AsyncYieldFrom: + def __init__(self, obj): + self.obj = obj + + def __await__(self): + yield from self.obj + + +class AsyncYield: + def __init__(self, value): + self.value = value + + def __await__(self): + yield self.value + + +def run_async(coro): + assert coro.__class__ is types.GeneratorType + + buffer = [] + result = None + while True: + try: + buffer.append(coro.send(None)) + except StopIteration as ex: + result = ex.args[0] if ex.args else None + break + return buffer, result + + + at contextlib.contextmanager +def silence_coro_gc(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + yield + support.gc_collect() + + +class AsyncBadSyntaxTest(unittest.TestCase): + + def test_badsyntax_1(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async1 + + def test_badsyntax_2(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async2 + + def test_badsyntax_3(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async3 + + def test_badsyntax_4(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async4 + + def test_badsyntax_5(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async5 + + def test_badsyntax_6(self): + with self.assertRaisesRegex( + SyntaxError, "'yield' inside async function"): + + import test.badsyntax_async6 + + def test_badsyntax_7(self): + with self.assertRaisesRegex( + SyntaxError, "'yield from' inside async function"): + + import test.badsyntax_async7 + + def test_badsyntax_8(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async8 + + def test_badsyntax_9(self): + with self.assertRaisesRegex(SyntaxError, 'invalid syntax'): + import test.badsyntax_async9 + + +class CoroutineTest(unittest.TestCase): + + def test_gen_1(self): + def gen(): yield + self.assertFalse(hasattr(gen, '__await__')) + + def test_func_1(self): + async def foo(): + return 10 + + f = foo() + self.assertIsInstance(f, types.GeneratorType) + self.assertTrue(bool(foo.__code__.co_flags & 0x80)) + self.assertTrue(bool(foo.__code__.co_flags & 0x20)) + self.assertTrue(bool(f.gi_code.co_flags & 0x80)) + self.assertTrue(bool(f.gi_code.co_flags & 0x20)) + self.assertEqual(run_async(f), ([], 10)) + + def bar(): pass + self.assertFalse(bool(bar.__code__.co_flags & 0x80)) + + def test_func_2(self): + async def foo(): + raise StopIteration + + with self.assertRaisesRegex( + RuntimeError, "generator raised StopIteration"): + + run_async(foo()) + + def test_func_3(self): + async def foo(): + raise StopIteration + + with silence_coro_gc(): + self.assertRegex(repr(foo()), '^$') + + def test_func_4(self): + async def foo(): + raise StopIteration + + check = lambda: self.assertRaisesRegex( + TypeError, "coroutine-objects do not support iteration") + + with check(): + list(foo()) + + with check(): + tuple(foo()) + + with check(): + sum(foo()) + + with check(): + iter(foo()) + + with check(): + next(foo()) + + with silence_coro_gc(), check(): + for i in foo(): + pass + + with silence_coro_gc(), check(): + [i for i in foo()] + + def test_func_5(self): + @types.coroutine + def bar(): + yield 1 + + async def foo(): + await bar() + + check = lambda: self.assertRaisesRegex( + TypeError, "coroutine-objects do not support iteration") + + with check(): + for el in foo(): pass + + # the following should pass without an error + for el in bar(): + self.assertEqual(el, 1) + self.assertEqual([el for el in bar()], [1]) + self.assertEqual(tuple(bar()), (1,)) + self.assertEqual(next(iter(bar())), 1) + + def test_func_6(self): + @types.coroutine + def bar(): + yield 1 + yield 2 + + async def foo(): + await bar() + + f = foo() + self.assertEquals(f.send(None), 1) + self.assertEquals(f.send(None), 2) + with self.assertRaises(StopIteration): + f.send(None) + + def test_func_7(self): + async def bar(): + return 10 + + def foo(): + yield from bar() + + with silence_coro_gc(), self.assertRaisesRegex( + TypeError, + "cannot 'yield from' a coroutine object from a generator"): + + list(foo()) + + def test_func_8(self): + @types.coroutine + def bar(): + return (yield from foo()) + + async def foo(): + return 'spam' + + self.assertEqual(run_async(bar()), ([], 'spam') ) + + def test_func_9(self): + async def foo(): pass + + with self.assertWarnsRegex( + RuntimeWarning, "coroutine '.*test_func_9.*foo' was never awaited"): + + foo() + support.gc_collect() + + def test_await_1(self): + + async def foo(): + await 1 + with self.assertRaisesRegex(TypeError, "object int can.t.*await"): + run_async(foo()) + + def test_await_2(self): + async def foo(): + await [] + with self.assertRaisesRegex(TypeError, "object list can.t.*await"): + run_async(foo()) + + def test_await_3(self): + async def foo(): + await AsyncYieldFrom([1, 2, 3]) + + self.assertEqual(run_async(foo()), ([1, 2, 3], None)) + + def test_await_4(self): + async def bar(): + return 42 + + async def foo(): + return await bar() + + self.assertEqual(run_async(foo()), ([], 42)) + + def test_await_5(self): + class Awaitable: + def __await__(self): + return + + async def foo(): + return (await Awaitable()) + + with self.assertRaisesRegex( + TypeError, "__await__.*returned non-iterator of type"): + + run_async(foo()) + + def test_await_6(self): + class Awaitable: + def __await__(self): + return iter([52]) + + async def foo(): + return (await Awaitable()) + + self.assertEqual(run_async(foo()), ([52], None)) + + def test_await_7(self): + class Awaitable: + def __await__(self): + yield 42 + return 100 + + async def foo(): + return (await Awaitable()) + + self.assertEqual(run_async(foo()), ([42], 100)) + + def test_await_8(self): + class Awaitable: + pass + + async def foo(): + return (await Awaitable()) + + with self.assertRaisesRegex( + TypeError, "object Awaitable can't be used in 'await' expression"): + + run_async(foo()) + + def test_await_9(self): + def wrap(): + return bar + + async def bar(): + return 42 + + async def foo(): + b = bar() + + db = {'b': lambda: wrap} + + class DB: + b = wrap + + return (await bar() + await wrap()() + await db['b']()()() + + await bar() * 1000 + await DB.b()()) + + async def foo2(): + return -await bar() + + self.assertEqual(run_async(foo()), ([], 42168)) + self.assertEqual(run_async(foo2()), ([], -42)) + + def test_await_10(self): + async def baz(): + return 42 + + async def bar(): + return baz() + + async def foo(): + return await (await bar()) + + self.assertEqual(run_async(foo()), ([], 42)) + + def test_await_11(self): + def ident(val): + return val + + async def bar(): + return 'spam' + + async def foo(): + return ident(val=await bar()) + + async def foo2(): + return await bar(), 'ham' + + self.assertEqual(run_async(foo2()), ([], ('spam', 'ham'))) + + def test_await_12(self): + async def coro(): + return 'spam' + + class Awaitable: + def __await__(self): + return coro() + + async def foo(): + return await Awaitable() + + with self.assertRaisesRegex( + TypeError, "__await__\(\) returned a coroutine"): + + run_async(foo()) + + def test_await_13(self): + class Awaitable: + def __await__(self): + return self + + async def foo(): + return await Awaitable() + + with self.assertRaisesRegex( + TypeError, "__await__.*returned non-iterator of type"): + + run_async(foo()) + + def test_with_1(self): + class Manager: + def __init__(self, name): + self.name = name + + async def __aenter__(self): + await AsyncYieldFrom(['enter-1-' + self.name, + 'enter-2-' + self.name]) + return self + + async def __aexit__(self, *args): + await AsyncYieldFrom(['exit-1-' + self.name, + 'exit-2-' + self.name]) + + if self.name == 'B': + return True + + + async def foo(): + async with Manager("A") as a, Manager("B") as b: + await AsyncYieldFrom([('managers', a.name, b.name)]) + 1/0 + + f = foo() + result, _ = run_async(f) + + self.assertEqual( + result, ['enter-1-A', 'enter-2-A', 'enter-1-B', 'enter-2-B', + ('managers', 'A', 'B'), + 'exit-1-B', 'exit-2-B', 'exit-1-A', 'exit-2-A'] + ) + + async def foo(): + async with Manager("A") as a, Manager("C") as c: + await AsyncYieldFrom([('managers', a.name, c.name)]) + 1/0 + + with self.assertRaises(ZeroDivisionError): + run_async(foo()) + + def test_with_2(self): + class CM: + def __aenter__(self): + pass + + async def foo(): + async with CM(): + pass + + with self.assertRaisesRegex(AttributeError, '__aexit__'): + run_async(foo()) + + def test_with_3(self): + class CM: + def __aexit__(self): + pass + + async def foo(): + async with CM(): + pass + + with self.assertRaisesRegex(AttributeError, '__aenter__'): + run_async(foo()) + + def test_with_4(self): + class CM: + def __enter__(self): + pass + + def __exit__(self): + pass + + async def foo(): + async with CM(): + pass + + with self.assertRaisesRegex(AttributeError, '__aexit__'): + run_async(foo()) + + def test_with_5(self): + # While this test doesn't make a lot of sense, + # it's a regression test for an early bug with opcodes + # generation + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *exc): + pass + + async def func(): + async with CM(): + assert (1, ) == 1 + + with self.assertRaises(AssertionError): + run_async(func()) + + def test_with_6(self): + class CM: + def __aenter__(self): + return 123 + + def __aexit__(self, *e): + return 456 + + async def foo(): + async with CM(): + pass + + with self.assertRaisesRegex( + TypeError, "object int can't be used in 'await' expression"): + # it's important that __aexit__ wasn't called + run_async(foo()) + + def test_with_7(self): + class CM: + async def __aenter__(self): + return self + + def __aexit__(self, *e): + return 456 + + async def foo(): + async with CM(): + pass + + with self.assertRaisesRegex( + TypeError, "object int can't be used in 'await' expression"): + + run_async(foo()) + + def test_for_1(self): + aiter_calls = 0 + + class AsyncIter: + def __init__(self): + self.i = 0 + + async def __aiter__(self): + nonlocal aiter_calls + aiter_calls += 1 + return self + + async def __anext__(self): + self.i += 1 + + if not (self.i % 10): + await AsyncYield(self.i * 10) + + if self.i > 100: + raise StopAsyncIteration + + return self.i, self.i + + + buffer = [] + async def test1(): + async for i1, i2 in AsyncIter(): + buffer.append(i1 + i2) + + yielded, _ = run_async(test1()) + # Make sure that __aiter__ was called only once + self.assertEqual(aiter_calls, 1) + self.assertEqual(yielded, [i * 100 for i in range(1, 11)]) + self.assertEqual(buffer, [i*2 for i in range(1, 101)]) + + + buffer = [] + async def test2(): + nonlocal buffer + async for i in AsyncIter(): + buffer.append(i[0]) + if i[0] == 20: + break + else: + buffer.append('what?') + buffer.append('end') + + yielded, _ = run_async(test2()) + # Make sure that __aiter__ was called only once + self.assertEqual(aiter_calls, 2) + self.assertEqual(yielded, [100, 200]) + self.assertEqual(buffer, [i for i in range(1, 21)] + ['end']) + + + buffer = [] + async def test3(): + nonlocal buffer + async for i in AsyncIter(): + if i[0] > 20: + continue + buffer.append(i[0]) + else: + buffer.append('what?') + buffer.append('end') + + yielded, _ = run_async(test3()) + # Make sure that __aiter__ was called only once + self.assertEqual(aiter_calls, 3) + self.assertEqual(yielded, [i * 100 for i in range(1, 11)]) + self.assertEqual(buffer, [i for i in range(1, 21)] + + ['what?', 'end']) + + def test_for_2(self): + tup = (1, 2, 3) + refs_before = sys.getrefcount(tup) + + async def foo(): + async for i in tup: + print('never going to happen') + + with self.assertRaisesRegex( + TypeError, "async for' requires an object.*__aiter__.*tuple"): + + run_async(foo()) + + self.assertEqual(sys.getrefcount(tup), refs_before) + + def test_for_3(self): + class I: + def __aiter__(self): + return self + + aiter = I() + refs_before = sys.getrefcount(aiter) + + async def foo(): + async for i in aiter: + print('never going to happen') + + with self.assertRaisesRegex( + TypeError, + "async for' received an invalid object.*__aiter.*\: I"): + + run_async(foo()) + + self.assertEqual(sys.getrefcount(aiter), refs_before) + + def test_for_4(self): + class I: + async def __aiter__(self): + return self + + def __anext__(self): + return () + + aiter = I() + refs_before = sys.getrefcount(aiter) + + async def foo(): + async for i in aiter: + print('never going to happen') + + with self.assertRaisesRegex( + TypeError, + "async for' received an invalid object.*__anext__.*tuple"): + + run_async(foo()) + + self.assertEqual(sys.getrefcount(aiter), refs_before) + + def test_for_5(self): + class I: + async def __aiter__(self): + return self + + def __anext__(self): + return 123 + + async def foo(): + async for i in I(): + print('never going to happen') + + with self.assertRaisesRegex( + TypeError, + "async for' received an invalid object.*__anext.*int"): + + run_async(foo()) + + def test_for_6(self): + I = 0 + + class Manager: + async def __aenter__(self): + nonlocal I + I += 10000 + + async def __aexit__(self, *args): + nonlocal I + I += 100000 + + class Iterable: + def __init__(self): + self.i = 0 + + async def __aiter__(self): + return self + + async def __anext__(self): + if self.i > 10: + raise StopAsyncIteration + self.i += 1 + return self.i + + ############## + + manager = Manager() + iterable = Iterable() + mrefs_before = sys.getrefcount(manager) + irefs_before = sys.getrefcount(iterable) + + async def main(): + nonlocal I + + async with manager: + async for i in iterable: + I += 1 + I += 1000 + + run_async(main()) + self.assertEqual(I, 111011) + + self.assertEqual(sys.getrefcount(manager), mrefs_before) + self.assertEqual(sys.getrefcount(iterable), irefs_before) + + ############## + + async def main(): + nonlocal I + + async with Manager(): + async for i in Iterable(): + I += 1 + I += 1000 + + async with Manager(): + async for i in Iterable(): + I += 1 + I += 1000 + + run_async(main()) + self.assertEqual(I, 333033) + + ############## + + async def main(): + nonlocal I + + async with Manager(): + I += 100 + async for i in Iterable(): + I += 1 + else: + I += 10000000 + I += 1000 + + async with Manager(): + I += 100 + async for i in Iterable(): + I += 1 + else: + I += 10000000 + I += 1000 + + run_async(main()) + self.assertEqual(I, 20555255) + + +class CoroAsyncIOCompatTest(unittest.TestCase): + + def test_asyncio_1(self): + import asyncio + + class MyException(Exception): + pass + + buffer = [] + + class CM: + async def __aenter__(self): + buffer.append(1) + await asyncio.sleep(0.01) + buffer.append(2) + return self + + async def __aexit__(self, exc_type, exc_val, exc_tb): + await asyncio.sleep(0.01) + buffer.append(exc_type.__name__) + + async def f(): + async with CM() as c: + await asyncio.sleep(0.01) + raise MyException + buffer.append('unreachable') + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(f()) + except MyException: + pass + finally: + loop.close() + + self.assertEqual(buffer, [1, 2, 'MyException']) + + +class SysSetCoroWrapperTest(unittest.TestCase): + + def test_set_wrapper_1(self): + async def foo(): + return 'spam' + + wrapped = None + def wrap(gen): + nonlocal wrapped + wrapped = gen + return gen + + self.assertIsNone(sys.get_coroutine_wrapper()) + + sys.set_coroutine_wrapper(wrap) + self.assertIs(sys.get_coroutine_wrapper(), wrap) + try: + f = foo() + self.assertTrue(wrapped) + + self.assertEqual(run_async(f), ([], 'spam')) + finally: + sys.set_coroutine_wrapper(None) + + self.assertIsNone(sys.get_coroutine_wrapper()) + + wrapped = None + with silence_coro_gc(): + foo() + self.assertFalse(wrapped) + + def test_set_wrapper_2(self): + self.assertIsNone(sys.get_coroutine_wrapper()) + with self.assertRaisesRegex(TypeError, "callable expected, got int"): + sys.set_coroutine_wrapper(1) + self.assertIsNone(sys.get_coroutine_wrapper()) + + +class CAPITest(unittest.TestCase): + + def test_tp_await_1(self): + from _testcapi import awaitType as at + + async def foo(): + future = at(iter([1])) + return (await future) + + self.assertEqual(foo().send(None), 1) + + def test_tp_await_2(self): + # Test tp_await to __await__ mapping + from _testcapi import awaitType as at + future = at(iter([1])) + self.assertEqual(next(future.__await__()), 1) + + def test_tp_await_3(self): + from _testcapi import awaitType as at + + async def foo(): + future = at(1) + return (await future) + + with self.assertRaisesRegex( + TypeError, "__await__.*returned non-iterator of type 'int'"): + self.assertEqual(foo().send(None), 1) + + +def test_main(): + support.run_unittest(AsyncBadSyntaxTest, + CoroutineTest, + CoroAsyncIOCompatTest, + SysSetCoroWrapperTest, + CAPITest) + + +if __name__=="__main__": + test_main() diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -480,6 +480,24 @@ Names: 0: x""" + +async def async_def(): + await 1 + async for a in b: pass + async with c as d: pass + +code_info_async_def = """\ +Name: async_def +Filename: (.*) +Argument count: 0 +Kw-only arguments: 0 +Number of locals: 2 +Stack size: 17 +Flags: OPTIMIZED, NEWLOCALS, GENERATOR, NOFREE, COROUTINE +Constants: + 0: None + 1: 1""" + class CodeInfoTests(unittest.TestCase): test_pairs = [ (dis.code_info, code_info_code_info), @@ -488,6 +506,7 @@ (expr_str, code_info_expr_str), (simple_stmt_str, code_info_simple_stmt_str), (compound_stmt_str, code_info_compound_stmt_str), + (async_def, code_info_async_def) ] def test_code_info(self): @@ -697,7 +716,7 @@ 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=135, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=138, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=141, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_FINALLY', opcode=122, arg=72, argval=217, argrepr='to 217', offset=142, starts_line=20, is_jump_target=True), + Instruction(opname='SETUP_FINALLY', opcode=122, arg=73, argval=218, argrepr='to 218', offset=142, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=160, argrepr='to 160', offset=145, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=148, starts_line=21, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=151, starts_line=None, is_jump_target=False), @@ -717,7 +736,7 @@ Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=179, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=183, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=213, argrepr='to 213', offset=184, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=27, argval=214, argrepr='to 214', offset=184, starts_line=None, is_jump_target=False), Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=187, starts_line=None, is_jump_target=True), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=188, starts_line=25, is_jump_target=True), Instruction(opname='SETUP_WITH', opcode=143, arg=17, argval=211, argrepr='to 211', offset=191, starts_line=None, is_jump_target=False), @@ -728,17 +747,18 @@ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=207, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=208, starts_line=None, is_jump_target=False), - Instruction(opname='WITH_CLEANUP', opcode=81, arg=None, argval=None, argrepr='', offset=211, starts_line=None, is_jump_target=True), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=213, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=217, 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=220, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=223, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=227, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=228, starts_line=None, is_jump_target=False), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=231, starts_line=None, is_jump_target=False), + Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=211, starts_line=None, is_jump_target=True), + Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=213, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=215, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=218, 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=221, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=224, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=227, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=229, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=232, 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_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -2,6 +2,7 @@ # This just tests whether the parser accepts them all. from test.support import check_syntax_error +import inspect import unittest import sys # testing import * @@ -1034,6 +1035,92 @@ m @= 42 self.assertEqual(m.other, 42) + def test_async_await(self): + async = 1 + await = 2 + self.assertEqual(async, 1) + + def async(): + nonlocal await + await = 10 + async() + self.assertEqual(await, 10) + + self.assertFalse(bool(async.__code__.co_flags & inspect.CO_COROUTINE)) + + async def test(): + def sum(): + async = 1 + await = 41 + return async + await + + if 1: + await someobj() + + self.assertEqual(test.__name__, 'test') + self.assertTrue(bool(test.__code__.co_flags & inspect.CO_COROUTINE)) + + def decorator(func): + setattr(func, '_marked', True) + return func + + @decorator + async def test2(): + return 22 + self.assertTrue(test2._marked) + self.assertEqual(test2.__name__, 'test2') + self.assertTrue(bool(test2.__code__.co_flags & inspect.CO_COROUTINE)) + + def test_async_for(self): + class Done(Exception): pass + + class AIter: + async def __aiter__(self): + return self + async def __anext__(self): + raise StopAsyncIteration + + async def foo(): + async for i in AIter(): + pass + async for i, j in AIter(): + pass + async for i in AIter(): + pass + else: + pass + raise Done + + with self.assertRaises(Done): + foo().send(None) + + def test_async_with(self): + class Done(Exception): pass + + class manager: + async def __aenter__(self): + return (1, 2) + async def __aexit__(self, *exc): + return False + + async def foo(): + async with manager(): + pass + async with manager() as x: + pass + async with manager() as (x, y): + pass + async with manager(), manager(): + pass + async with manager() as x, manager() as y: + pass + async with manager() as x, manager(): + pass + raise Done + + with self.assertRaises(Done): + foo().send(None) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -18,6 +18,7 @@ import unicodedata import unittest import unittest.mock +import warnings try: from concurrent.futures import ThreadPoolExecutor @@ -62,14 +63,16 @@ predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode, inspect.isframe, inspect.isfunction, inspect.ismethod, inspect.ismodule, inspect.istraceback, - inspect.isgenerator, inspect.isgeneratorfunction]) + inspect.isgenerator, inspect.isgeneratorfunction, + inspect.iscoroutine, inspect.iscoroutinefunction]) def istest(self, predicate, exp): obj = eval(exp) self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp)) for other in self.predicates - set([predicate]): - if predicate == inspect.isgeneratorfunction and\ + if (predicate == inspect.isgeneratorfunction or \ + predicate == inspect.iscoroutinefunction) and \ other == inspect.isfunction: continue self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp)) @@ -78,13 +81,21 @@ for i in range(2): yield i +async def coroutine_function_example(self): + return 'spam' + + at types.coroutine +def gen_coroutine_function_example(self): + yield + return 'spam' + class TestPredicates(IsTestBase): - def test_sixteen(self): + def test_eightteen(self): count = len([x for x in dir(inspect) if x.startswith('is')]) # This test is here for remember you to update Doc/library/inspect.rst # which claims there are 16 such functions - expected = 16 + expected = 19 err_msg = "There are %d (not %d) is* functions" % (count, expected) self.assertEqual(count, expected, err_msg) @@ -115,11 +126,64 @@ self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory') self.istest(inspect.isgenerator, '(x for x in range(2))') self.istest(inspect.isgeneratorfunction, 'generator_function_example') + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + self.istest(inspect.iscoroutine, 'coroutine_function_example(1)') + self.istest(inspect.iscoroutinefunction, 'coroutine_function_example') + if hasattr(types, 'MemberDescriptorType'): self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days') else: self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days)) + def test_iscoroutine(self): + gen_coro = gen_coroutine_function_example(1) + coro = coroutine_function_example(1) + + self.assertTrue( + inspect.iscoroutinefunction(gen_coroutine_function_example)) + self.assertTrue(inspect.iscoroutine(gen_coro)) + + self.assertTrue( + inspect.isgeneratorfunction(gen_coroutine_function_example)) + self.assertTrue(inspect.isgenerator(gen_coro)) + + self.assertTrue( + inspect.iscoroutinefunction(coroutine_function_example)) + self.assertTrue(inspect.iscoroutine(coro)) + + self.assertFalse( + inspect.isgeneratorfunction(coroutine_function_example)) + self.assertFalse(inspect.isgenerator(coro)) + + coro.close(); gen_coro.close() # silence warnings + + def test_isawaitable(self): + def gen(): yield + self.assertFalse(inspect.isawaitable(gen())) + + coro = coroutine_function_example(1) + gen_coro = gen_coroutine_function_example(1) + + self.assertTrue( + inspect.isawaitable(coro)) + self.assertTrue( + inspect.isawaitable(gen_coro)) + + class Future: + def __await__(): + pass + self.assertTrue(inspect.isawaitable(Future())) + self.assertFalse(inspect.isawaitable(Future)) + + class NotFuture: pass + not_fut = NotFuture() + not_fut.__await__ = lambda: None + self.assertFalse(inspect.isawaitable(not_fut)) + + coro.close(); gen_coro.close() # silence warnings + def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) self.assertTrue(inspect.isroutine([].count)) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -49,6 +49,21 @@ t = node.wholeText self.confirm(t == s, "looking for %r, found %r" % (s, t)) + def testDocumentAsyncAttr(self): + doc = Document() + self.assertFalse(doc.async_) + with self.assertWarns(DeprecationWarning): + self.assertFalse(getattr(doc, 'async', True)) + with self.assertWarns(DeprecationWarning): + setattr(doc, 'async', True) + with self.assertWarns(DeprecationWarning): + self.assertTrue(getattr(doc, 'async', False)) + self.assertTrue(doc.async_) + + self.assertFalse(Document.async_) + with self.assertWarns(DeprecationWarning): + self.assertFalse(getattr(Document, 'async', True)) + def testParseFromBinaryFile(self): with open(tstfile, 'rb') as file: dom = parse(file) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -63,6 +63,22 @@ " if (yield):\n" " yield x\n") + def test_await_statement(self): + self.check_suite("async def f():\n await smth()") + self.check_suite("async def f():\n foo = await smth()") + self.check_suite("async def f():\n foo, bar = await smth()") + self.check_suite("async def f():\n (await smth())") + self.check_suite("async def f():\n foo((await smth()))") + self.check_suite("async def f():\n await foo(); return 42") + + def test_async_with_statement(self): + self.check_suite("async def f():\n async with 1: pass") + self.check_suite("async def f():\n async with a as b, c as d: pass") + + def test_async_for_statement(self): + self.check_suite("async def f():\n async for i in (): pass") + self.check_suite("async def f():\n async for i, b in (): pass") + def test_nonlocal_statement(self): self.check_suite("def f():\n" " x = 0\n" diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -351,7 +351,9 @@ for name, exc in get_exceptions(builtins): with self.subTest(name): - if exc in (BlockingIOError, ResourceWarning): + if exc in (BlockingIOError, + ResourceWarning, + StopAsyncIteration): continue if exc is not OSError and issubclass(exc, OSError): self.assertEqual(reverse_mapping('builtins', name), diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1025,9 +1025,9 @@ # static type: PyTypeObject s = vsize('P2n15Pl4Pn9Pn11PIP') check(int, s) - # (PyTypeObject + PyNumberMethods + PyMappingMethods + + # (PyTypeObject + PyAsyncMethods + PyNumberMethods + PyMappingMethods + # PySequenceMethods + PyBufferProcs + 4P) - s = vsize('P2n17Pl4Pn9Pn11PIP') + struct.calcsize('34P 3P 10P 2P 4P') + s = vsize('P2n17Pl4Pn9Pn11PIP') + struct.calcsize('34P 3P 3P 10P 2P 4P') # Separate block for PyDictKeysObject with 4 entries s += struct.calcsize("2nPn") + 4*struct.calcsize("n2P") # class diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -641,6 +641,192 @@ NAME 'gr?n' (2, 0) (2, 4) OP '=' (2, 5) (2, 6) STRING "U'green'" (2, 7) (2, 15) + +Async/await extension: + + >>> dump_tokens("async = 1") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + OP '=' (1, 6) (1, 7) + NUMBER '1' (1, 8) (1, 9) + + >>> dump_tokens("a = (async = 1)") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'a' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + OP '(' (1, 4) (1, 5) + NAME 'async' (1, 5) (1, 10) + OP '=' (1, 11) (1, 12) + NUMBER '1' (1, 13) (1, 14) + OP ')' (1, 14) (1, 15) + + >>> dump_tokens("async()") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + OP '(' (1, 5) (1, 6) + OP ')' (1, 6) (1, 7) + + >>> dump_tokens("class async(Bar):pass") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'class' (1, 0) (1, 5) + NAME 'async' (1, 6) (1, 11) + OP '(' (1, 11) (1, 12) + NAME 'Bar' (1, 12) (1, 15) + OP ')' (1, 15) (1, 16) + OP ':' (1, 16) (1, 17) + NAME 'pass' (1, 17) (1, 21) + + >>> dump_tokens("class async:pass") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'class' (1, 0) (1, 5) + NAME 'async' (1, 6) (1, 11) + OP ':' (1, 11) (1, 12) + NAME 'pass' (1, 12) (1, 16) + + >>> dump_tokens("await = 1") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'await' (1, 0) (1, 5) + OP '=' (1, 6) (1, 7) + NUMBER '1' (1, 8) (1, 9) + + >>> dump_tokens("foo.async") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'foo' (1, 0) (1, 3) + OP '.' (1, 3) (1, 4) + NAME 'async' (1, 4) (1, 9) + + >>> dump_tokens("async for a in b: pass") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + NAME 'for' (1, 6) (1, 9) + NAME 'a' (1, 10) (1, 11) + NAME 'in' (1, 12) (1, 14) + NAME 'b' (1, 15) (1, 16) + OP ':' (1, 16) (1, 17) + NAME 'pass' (1, 18) (1, 22) + + >>> dump_tokens("async with a as b: pass") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + NAME 'with' (1, 6) (1, 10) + NAME 'a' (1, 11) (1, 12) + NAME 'as' (1, 13) (1, 15) + NAME 'b' (1, 16) (1, 17) + OP ':' (1, 17) (1, 18) + NAME 'pass' (1, 19) (1, 23) + + >>> dump_tokens("async.foo") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + OP '.' (1, 5) (1, 6) + NAME 'foo' (1, 6) (1, 9) + + >>> dump_tokens("async") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + + >>> dump_tokens("async\\n#comment\\nawait") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + NEWLINE '\\n' (1, 5) (1, 6) + COMMENT '#comment' (2, 0) (2, 8) + NL '\\n' (2, 8) (2, 9) + NAME 'await' (3, 0) (3, 5) + + >>> dump_tokens("async\\n...\\nawait") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + NEWLINE '\\n' (1, 5) (1, 6) + OP '...' (2, 0) (2, 3) + NEWLINE '\\n' (2, 3) (2, 4) + NAME 'await' (3, 0) (3, 5) + + >>> dump_tokens("async\\nawait") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'async' (1, 0) (1, 5) + NEWLINE '\\n' (1, 5) (1, 6) + NAME 'await' (2, 0) (2, 5) + + >>> dump_tokens("foo.async + 1") + ENCODING 'utf-8' (0, 0) (0, 0) + NAME 'foo' (1, 0) (1, 3) + OP '.' (1, 3) (1, 4) + NAME 'async' (1, 4) (1, 9) + OP '+' (1, 10) (1, 11) + NUMBER '1' (1, 12) (1, 13) + + >>> dump_tokens("async def foo(): pass") + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'foo' (1, 10) (1, 13) + OP '(' (1, 13) (1, 14) + OP ')' (1, 14) (1, 15) + OP ':' (1, 15) (1, 16) + NAME 'pass' (1, 17) (1, 21) + + >>> dump_tokens('''async def foo(): + ... def foo(await): + ... await = 1 + ... if 1: + ... await + ... async += 1 + ... ''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'foo' (1, 10) (1, 13) + OP '(' (1, 13) (1, 14) + OP ')' (1, 14) (1, 15) + OP ':' (1, 15) (1, 16) + NEWLINE '\\n' (1, 16) (1, 17) + INDENT ' ' (2, 0) (2, 2) + NAME 'def' (2, 2) (2, 5) + NAME 'foo' (2, 6) (2, 9) + OP '(' (2, 9) (2, 10) + NAME 'await' (2, 10) (2, 15) + OP ')' (2, 15) (2, 16) + OP ':' (2, 16) (2, 17) + NEWLINE '\\n' (2, 17) (2, 18) + INDENT ' ' (3, 0) (3, 4) + NAME 'await' (3, 4) (3, 9) + OP '=' (3, 10) (3, 11) + NUMBER '1' (3, 12) (3, 13) + NEWLINE '\\n' (3, 13) (3, 14) + DEDENT '' (4, 2) (4, 2) + NAME 'if' (4, 2) (4, 4) + NUMBER '1' (4, 5) (4, 6) + OP ':' (4, 6) (4, 7) + NEWLINE '\\n' (4, 7) (4, 8) + INDENT ' ' (5, 0) (5, 4) + AWAIT 'await' (5, 4) (5, 9) + NEWLINE '\\n' (5, 9) (5, 10) + DEDENT '' (6, 0) (6, 0) + DEDENT '' (6, 0) (6, 0) + NAME 'async' (6, 0) (6, 5) + OP '+=' (6, 6) (6, 8) + NUMBER '1' (6, 9) (6, 10) + NEWLINE '\\n' (6, 10) (6, 11) + + >>> dump_tokens('''async def foo(): + ... async for i in 1: pass''') + ENCODING 'utf-8' (0, 0) (0, 0) + ASYNC 'async' (1, 0) (1, 5) + NAME 'def' (1, 6) (1, 9) + NAME 'foo' (1, 10) (1, 13) + OP '(' (1, 13) (1, 14) + OP ')' (1, 14) (1, 15) + OP ':' (1, 15) (1, 16) + NEWLINE '\\n' (1, 16) (1, 17) + INDENT ' ' (2, 0) (2, 2) + ASYNC 'async' (2, 2) (2, 7) + NAME 'for' (2, 8) (2, 11) + NAME 'i' (2, 12) (2, 13) + NAME 'in' (2, 14) (2, 16) + NUMBER '1' (2, 17) (2, 18) + OP ':' (2, 18) (2, 19) + NAME 'pass' (2, 20) (2, 24) + DEDENT '' (3, 0) (3, 0) """ from test import support diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,7 +1,8 @@ # Python test set -- part 6, built-in types from test.support import run_with_locale -import collections +import collections.abc +import inspect import pickle import locale import sys @@ -1172,5 +1173,37 @@ self.assertEqual(ns, ns_roundtrip, pname) +class CoroutineTests(unittest.TestCase): + def test_wrong_args(self): + class Foo: + def __call__(self): + pass + def bar(): pass + + samples = [Foo, Foo(), bar, None, int, 1] + for sample in samples: + with self.assertRaisesRegex(TypeError, 'expects a generator'): + types.coroutine(sample) + + def test_genfunc(self): + def gen(): + yield + + self.assertFalse(isinstance(gen(), collections.abc.Coroutine)) + self.assertFalse(isinstance(gen(), collections.abc.Awaitable)) + + self.assertIs(types.coroutine(gen), gen) + + self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE) + self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE) + + g = gen() + self.assertTrue(g.gi_code.co_flags & inspect.CO_ITERABLE_COROUTINE) + self.assertFalse(g.gi_code.co_flags & inspect.CO_COROUTINE) + self.assertTrue(isinstance(g, collections.abc.Coroutine)) + self.assertTrue(isinstance(g, collections.abc.Awaitable)) + g.close() # silence warning + + if __name__ == '__main__': unittest.main() diff --git a/Lib/token.py b/Lib/token.py --- a/Lib/token.py +++ b/Lib/token.py @@ -64,8 +64,10 @@ RARROW = 51 ELLIPSIS = 52 OP = 53 -ERRORTOKEN = 54 -N_TOKENS = 55 +AWAIT = 54 +ASYNC = 55 +ERRORTOKEN = 56 +N_TOKENS = 57 NT_OFFSET = 256 #--end constants-- diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -274,7 +274,7 @@ self.encoding = tokval continue - if toknum in (NAME, NUMBER): + if toknum in (NAME, NUMBER, ASYNC, AWAIT): tokval += ' ' # Insert a space between two consecutive strings @@ -477,6 +477,10 @@ contline = None indents = [0] + # 'stashed' and 'ctx' are used for async/await parsing + stashed = None + ctx = [('sync', 0)] + if encoding is not None: if encoding == "utf-8-sig": # BOM will already have been stripped. @@ -552,6 +556,11 @@ "unindent does not match any outer indentation level", ("", lnum, pos, line)) indents = indents[:-1] + + cur_indent = indents[-1] + while len(ctx) > 1 and ctx[-1][1] >= cur_indent: + ctx.pop() + yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) else: # continued statement @@ -572,10 +581,16 @@ (initial == '.' and token != '.' and token != '...')): yield TokenInfo(NUMBER, token, spos, epos, line) elif initial in '\r\n': + if stashed: + yield stashed + stashed = None yield TokenInfo(NL if parenlev > 0 else NEWLINE, token, spos, epos, line) elif initial == '#': assert not token.endswith("\n") + if stashed: + yield stashed + stashed = None yield TokenInfo(COMMENT, token, spos, epos, line) elif token in triple_quoted: endprog = _compile(endpats[token]) @@ -603,7 +618,37 @@ else: # ordinary string yield TokenInfo(STRING, token, spos, epos, line) elif initial.isidentifier(): # ordinary name - yield TokenInfo(NAME, token, spos, epos, line) + if token in ('async', 'await'): + if ctx[-1][0] == 'async' and ctx[-1][1] < indents[-1]: + yield TokenInfo( + ASYNC if token == 'async' else AWAIT, + token, spos, epos, line) + continue + + tok = TokenInfo(NAME, token, spos, epos, line) + if token == 'async' and not stashed: + stashed = tok + continue + + if token == 'def': + if (stashed + and stashed.type == NAME + and stashed.string == 'async'): + + ctx.append(('async', indents[-1])) + + yield TokenInfo(ASYNC, stashed.string, + stashed.start, stashed.end, + stashed.line) + stashed = None + else: + ctx.append(('sync', indents[-1])) + + if stashed: + yield stashed + stashed = None + + yield tok elif initial == '\\': # continued stmt continued = 1 else: @@ -611,12 +656,19 @@ parenlev += 1 elif initial in ')]}': parenlev -= 1 + if stashed: + yield stashed + stashed = None yield TokenInfo(OP, token, spos, epos, line) else: yield TokenInfo(ERRORTOKEN, line[pos], (lnum, pos), (lnum, pos+1), line) pos += 1 + if stashed: + yield stashed + stashed = None + for indent in indents[1:]: # pop remaining indent levels yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '') yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '') diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -43,6 +43,30 @@ del sys, _f, _g, _C, # Not for export +_CO_GENERATOR = 0x20 +_CO_ITERABLE_COROUTINE = 0x100 + +def coroutine(func): + """Convert regular generator function to a coroutine.""" + + # TODO: Implement this in C. + + if (not isinstance(func, (FunctionType, MethodType)) or + not isinstance(getattr(func, '__code__', None), CodeType) or + not (func.__code__.co_flags & _CO_GENERATOR)): + raise TypeError('coroutine() expects a generator function') + + co = func.__code__ + func.__code__ = CodeType( + co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, + co.co_flags | _CO_ITERABLE_COROUTINE, + co.co_code, + co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, + co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) + + return func + + # Provide a PEP 3115 compliant mechanism for class creation def new_class(name, bases=(), kwds=None, exec_body=None): """Create a class object dynamically using the appropriate metaclass.""" diff --git a/Lib/xml/dom/xmlbuilder.py b/Lib/xml/dom/xmlbuilder.py --- a/Lib/xml/dom/xmlbuilder.py +++ b/Lib/xml/dom/xmlbuilder.py @@ -1,6 +1,7 @@ """Implementation of the DOM Level 3 'LS-Load' feature.""" import copy +import warnings import xml.dom from xml.dom.NodeFilter import NodeFilter @@ -331,13 +332,33 @@ del NodeFilter +class _AsyncDeprecatedProperty: + def warn(self, cls): + clsname = cls.__name__ + warnings.warn( + "{cls}.async is deprecated; use {cls}.async_".format(cls=clsname), + DeprecationWarning) + + def __get__(self, instance, cls): + self.warn(cls) + if instance is not None: + return instance.async_ + return False + + def __set__(self, instance, value): + self.warn(type(instance)) + setattr(instance, 'async_', value) + + class DocumentLS: """Mixin to create documents that conform to the load/save spec.""" - async = False + async = _AsyncDeprecatedProperty() + async_ = False def _get_async(self): return False + def _set_async(self, async): if async: raise xml.dom.NotSupportedErr( @@ -363,6 +384,9 @@ return snode.toxml() +del _AsyncDeprecatedProperty + + class DOMImplementationLS: MODE_SYNCHRONOUS = 1 MODE_ASYNCHRONOUS = 2 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3944,6 +3944,98 @@ }; +typedef struct { + PyObject_HEAD + PyObject *ao_iterator; +} awaitObject; + + +static PyObject * +awaitObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *v; + awaitObject *ao; + + if (!PyArg_UnpackTuple(args, "awaitObject", 1, 1, &v)) + return NULL; + + ao = (awaitObject *)type->tp_alloc(type, 0); + if (ao == NULL) { + return NULL; + } + + Py_INCREF(v); + ao->ao_iterator = v; + + return (PyObject *)ao; +} + + +static void +awaitObject_dealloc(awaitObject *ao) +{ + Py_CLEAR(ao->ao_iterator); + Py_TYPE(ao)->tp_free(ao); +} + + +static PyObject * +awaitObject_await(awaitObject *ao) +{ + Py_INCREF(ao->ao_iterator); + return ao->ao_iterator; +} + +static PyAsyncMethods awaitType_as_async = { + (getawaitablefunc)awaitObject_await, /* am_await */ + 0, /* am_aiter */ + 0 /* am_anext */ +}; + + +static PyTypeObject awaitType = { + PyVarObject_HEAD_INIT(NULL, 0) + "awaitType", + sizeof(awaitObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)awaitObject_dealloc, /* destructor tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + &awaitType_as_async, /* tp_as_async */ + 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 */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + "C level type with tp_as_async", + 0, /* traverseproc tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + awaitObject_new, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + + static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, "_testcapi", @@ -3977,6 +4069,11 @@ Py_INCREF(&matmulType); PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType); + if (PyType_Ready(&awaitType) < 0) + return NULL; + Py_INCREF(&awaitType); + PyModule_AddObject(m, "awaitType", (PyObject *)&awaitType); + PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX)); PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN)); PyModule_AddObject(m, "UCHAR_MAX", PyLong_FromLong(UCHAR_MAX)); diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -1041,6 +1041,8 @@ VALIDATER(or_test); VALIDATER(test_nocond); VALIDATER(lambdef_nocond); VALIDATER(yield_arg); +VALIDATER(async_funcdef); VALIDATER(async_stmt); +VALIDATER(atom_expr); #undef VALIDATER @@ -1608,6 +1610,7 @@ || (ntype == try_stmt) || (ntype == with_stmt) || (ntype == funcdef) + || (ntype == async_stmt) || (ntype == classdef) || (ntype == decorated)) res = validate_node(tree); @@ -2440,27 +2443,60 @@ /* power: * - * power: atom trailer* ('**' factor)* + * power: atom_expr trailer* ['**' factor] */ static int validate_power(node *tree) { - int pos = 1; int nch = NCH(tree); int res = (validate_ntype(tree, power) && (nch >= 1) - && validate_atom(CHILD(tree, 0))); - - while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer)) - res = validate_trailer(CHILD(tree, pos++)); - if (res && (pos < nch)) { - if (!is_even(nch - pos)) { + && validate_atom_expr(CHILD(tree, 0))); + + if (nch > 1) { + if (nch != 3) { err_string("illegal number of nodes for 'power'"); return (0); } - for ( ; res && (pos < (nch - 1)); pos += 2) - res = (validate_doublestar(CHILD(tree, pos)) - && validate_factor(CHILD(tree, pos + 1))); + res = (validate_doublestar(CHILD(tree, 1)) + && validate_factor(CHILD(tree, 2))); } + + return (res); +} + + +/* atom_expr: + * + * atom_expr: [AWAIT] atom trailer* + */ +static int +validate_atom_expr(node *tree) +{ + int start = 0; + int nch = NCH(tree); + int res; + int pos; + + res = validate_ntype(tree, atom_expr) && (nch >= 1); + if (!res) { + return (res); + } + + if (TYPE(CHILD(tree, 0)) == AWAIT) { + start = 1; + if (nch < 2) { + err_string("illegal number of nodes for 'atom_expr'"); + return (0); + } + } + + res = validate_atom(CHILD(tree, start)); + if (res) { + pos = start + 1; + while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer)) + res = validate_trailer(CHILD(tree, pos++)); + } + return (res); } @@ -2482,9 +2518,9 @@ if (res && (nch == 3)) { if (TYPE(CHILD(tree, 1))==yield_expr) - res = validate_yield_expr(CHILD(tree, 1)); + res = validate_yield_expr(CHILD(tree, 1)); else - res = validate_testlist_comp(CHILD(tree, 1)); + res = validate_testlist_comp(CHILD(tree, 1)); } break; case LSQB: @@ -2658,6 +2694,55 @@ return res; } +/* async_funcdef: ASYNC funcdef */ + +static int +validate_async_funcdef(node *tree) +{ + int nch = NCH(tree); + int res = validate_ntype(tree, async_funcdef); + if (res) { + if (nch == 2) { + res = (validate_ntype(CHILD(tree, 0), ASYNC) + && validate_funcdef(CHILD(tree, 1))); + } + else { + res = 0; + err_string("illegal number of children for async_funcdef"); + } + } + return res; +} + + +/* async_stmt: ASYNC (funcdef | with_stmt | for_stmt) */ + +static int +validate_async_stmt(node *tree) +{ + int nch = NCH(tree); + int res = (validate_ntype(tree, async_stmt) + && validate_ntype(CHILD(tree, 0), ASYNC)); + + if (nch != 2) { + res = 0; + err_string("illegal number of children for async_stmt"); + } else { + if (TYPE(CHILD(tree, 1)) == funcdef) { + res = validate_funcdef(CHILD(tree, 1)); + } + else if (TYPE(CHILD(tree, 1)) == with_stmt) { + res = validate_with_stmt(CHILD(tree, 1)); + } + else if (TYPE(CHILD(tree, 1)) == for_stmt) { + res = validate_for(CHILD(tree, 1)); + } + } + + return res; +} + + /* decorated * decorators (classdef | funcdef) @@ -3085,6 +3170,12 @@ /* * Definition nodes. */ + case async_funcdef: + res = validate_async_funcdef(tree); + break; + case async_stmt: + res = validate_async_stmt(tree); + break; case funcdef: res = validate_funcdef(tree); break; diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -473,6 +473,13 @@ /* + * StopAsyncIteration extends Exception + */ +SimpleExtendsException(PyExc_Exception, StopAsyncIteration, + "Signal the end from iterator.__anext__()."); + + +/* * StopIteration extends Exception */ @@ -2468,6 +2475,7 @@ PRE_INIT(BaseException) PRE_INIT(Exception) PRE_INIT(TypeError) + PRE_INIT(StopAsyncIteration) PRE_INIT(StopIteration) PRE_INIT(GeneratorExit) PRE_INIT(SystemExit) @@ -2538,6 +2546,7 @@ POST_INIT(BaseException) POST_INIT(Exception) POST_INIT(TypeError) + POST_INIT(StopAsyncIteration) POST_INIT(StopIteration) POST_INIT(GeneratorExit) POST_INIT(SystemExit) diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -196,6 +196,7 @@ case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: + case SETUP_ASYNC_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; @@ -203,7 +204,8 @@ case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH + || setup_op == SETUP_ASYNC_WITH) { in_finally[blockstack_top-1] = 1; } else { @@ -218,7 +220,8 @@ * 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) { + if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH + || setup_op == SETUP_ASYNC_WITH) { blockstack_top--; } } @@ -281,6 +284,7 @@ case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: + case SETUP_ASYNC_WITH: delta_iblock++; break; diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -24,6 +24,19 @@ PyObject *res; PyObject *error_type, *error_value, *error_traceback; + /* If `gen` is a coroutine, and if it was never awaited on, + issue a RuntimeWarning. */ + if (gen->gi_code != NULL + && ((PyCodeObject *)gen->gi_code)->co_flags & (CO_COROUTINE + | CO_ITERABLE_COROUTINE) + && gen->gi_frame != NULL + && gen->gi_frame->f_lasti == -1 + && !PyErr_Occurred() + && PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "coroutine '%.50S' was never awaited", + gen->gi_qualname)) + return; + if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL) /* Generator isn't paused, so no need to close */ return; @@ -135,7 +148,7 @@ * a leaking StopIteration into RuntimeError (with its cause * set appropriately). */ if ((((PyCodeObject *)gen->gi_code)->co_flags & - CO_FUTURE_GENERATOR_STOP) + (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE)) && PyErr_ExceptionMatches(PyExc_StopIteration)) { PyObject *exc, *val, *val2, *tb; @@ -402,6 +415,12 @@ static PyObject * gen_iternext(PyGenObject *gen) { + if (((PyCodeObject*)gen->gi_code)->co_flags & CO_COROUTINE) { + PyErr_SetString(PyExc_TypeError, + "coroutine-objects do not support iteration"); + return NULL; + } + return gen_send_ex(gen, NULL, 0); } @@ -459,8 +478,14 @@ static PyObject * gen_repr(PyGenObject *gen) { - return PyUnicode_FromFormat("", - gen->gi_qualname, gen); + if (PyGen_CheckCoroutineExact(gen)) { + return PyUnicode_FromFormat("", + gen->gi_qualname, gen); + } + else { + return PyUnicode_FromFormat("", + gen->gi_qualname, gen); + } } static PyObject * @@ -496,6 +521,19 @@ return op->gi_qualname; } +static PyObject * +gen_get_iter(PyGenObject *gen) +{ + if (((PyCodeObject*)gen->gi_code)->co_flags & CO_COROUTINE) { + PyErr_SetString(PyExc_TypeError, + "coroutine-objects do not support iteration"); + return NULL; + } + + Py_INCREF(gen); + return gen; +} + static int gen_set_qualname(PyGenObject *op, PyObject *value) { @@ -547,7 +585,7 @@ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_reserved */ + 0, /* tp_as_async */ (reprfunc)gen_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -565,7 +603,7 @@ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ + (getiterfunc)gen_get_iter, /* tp_iter */ (iternextfunc)gen_iternext, /* tp_iternext */ gen_methods, /* tp_methods */ gen_memberlist, /* tp_members */ @@ -642,3 +680,57 @@ /* No blocks except loops, it's safe to skip finalization. */ return 0; } + +/* + * This helper function returns an awaitable for `o`: + * - `o` if `o` is a coroutine-object; + * - `type(o)->tp_as_async->am_await(o)` + * + * Raises a TypeError if it's not possible to return + * an awaitable and returns NULL. + */ +PyObject * +_PyGen_GetAwaitableIter(PyObject *o) +{ + getawaitablefunc getter = NULL; + PyTypeObject *ot; + + if (PyGen_CheckCoroutineExact(o)) { + /* Fast path. It's a central function for 'await'. */ + Py_INCREF(o); + return o; + } + + ot = Py_TYPE(o); + if (ot->tp_as_async != NULL) { + getter = ot->tp_as_async->am_await; + } + if (getter != NULL) { + PyObject *res = (*getter)(o); + if (res != NULL) { + if (!PyIter_Check(res)) { + PyErr_Format(PyExc_TypeError, + "__await__() returned non-iterator " + "of type '%.100s'", + Py_TYPE(res)->tp_name); + Py_CLEAR(res); + } + else { + if (PyGen_CheckCoroutineExact(res)) { + /* __await__ must return an *iterator*, not + a coroutine or another awaitable (see PEP 492) */ + PyErr_SetString(PyExc_TypeError, + "__await__() returned a coroutine"); + Py_CLEAR(res); + } + } + } + return res; + } + + PyErr_Format(PyExc_TypeError, + "object %.100s can't be used in 'await' expression", + ot->tp_name); + + return NULL; +} diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2506,6 +2506,7 @@ type->tp_flags |= Py_TPFLAGS_HAVE_GC; /* Initialize essential fields */ + type->tp_as_async = &et->as_async; type->tp_as_number = &et->as_number; type->tp_as_sequence = &et->as_sequence; type->tp_as_mapping = &et->as_mapping; @@ -2751,6 +2752,7 @@ } /* Initialize essential fields */ + type->tp_as_async = &res->as_async; type->tp_as_number = &res->as_number; type->tp_as_sequence = &res->as_sequence; type->tp_as_mapping = &res->as_mapping; @@ -4566,6 +4568,7 @@ #define COPYSLOT(SLOT) \ if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT +#define COPYASYNC(SLOT) COPYSLOT(tp_as_async->SLOT) #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT) #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT) #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT) @@ -4615,6 +4618,15 @@ COPYNUM(nb_inplace_matrix_multiply); } + if (type->tp_as_async != NULL && base->tp_as_async != NULL) { + basebase = base->tp_base; + if (basebase->tp_as_async == NULL) + basebase = NULL; + COPYASYNC(am_await); + COPYASYNC(am_aiter); + COPYASYNC(am_anext); + } + if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) { basebase = base->tp_base; if (basebase->tp_as_sequence == NULL) @@ -4884,6 +4896,8 @@ /* Some more special stuff */ base = type->tp_base; if (base != NULL) { + if (type->tp_as_async == NULL) + type->tp_as_async = base->tp_as_async; if (type->tp_as_number == NULL) type->tp_as_number = base->tp_as_number; if (type->tp_as_sequence == NULL) @@ -4904,16 +4918,6 @@ goto error; } - /* Warn for a type that implements tp_compare (now known as - tp_reserved) but not tp_richcompare. */ - if (type->tp_reserved && !type->tp_richcompare) { - PyErr_Format(PyExc_TypeError, - "Type %.100s defines tp_reserved (formerly tp_compare) " - "but not tp_richcompare. Comparisons may not behave as intended.", - type->tp_name); - goto error; - } - /* All done -- set the ready flag */ assert(type->tp_dict != NULL); type->tp_flags = @@ -6265,6 +6269,59 @@ PyErr_Restore(error_type, error_value, error_traceback); } +static PyObject * +slot_am_await(PyObject *self) +{ + PyObject *func, *res; + _Py_IDENTIFIER(__await__); + + func = lookup_method(self, &PyId___await__); + if (func != NULL) { + res = PyEval_CallObject(func, NULL); + Py_DECREF(func); + return res; + } + PyErr_Format(PyExc_AttributeError, + "object %.50s does not have __await__ method", + Py_TYPE(self)->tp_name); + return NULL; +} + +static PyObject * +slot_am_aiter(PyObject *self) +{ + PyObject *func, *res; + _Py_IDENTIFIER(__aiter__); + + func = lookup_method(self, &PyId___aiter__); + if (func != NULL) { + res = PyEval_CallObject(func, NULL); + Py_DECREF(func); + return res; + } + PyErr_Format(PyExc_AttributeError, + "object %.50s does not have __aiter__ method", + Py_TYPE(self)->tp_name); + return NULL; +} + +static PyObject * +slot_am_anext(PyObject *self) +{ + PyObject *func, *res; + _Py_IDENTIFIER(__anext__); + + func = lookup_method(self, &PyId___anext__); + if (func != NULL) { + res = PyEval_CallObject(func, NULL); + Py_DECREF(func); + return res; + } + PyErr_Format(PyExc_AttributeError, + "object %.50s does not have __anext__ method", + Py_TYPE(self)->tp_name); + return NULL; +} /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions. @@ -6281,6 +6338,7 @@ #undef TPSLOT #undef FLSLOT +#undef AMSLOT #undef ETSLOT #undef SQSLOT #undef MPSLOT @@ -6299,6 +6357,8 @@ #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ PyDoc_STR(DOC)} +#define AMSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ + ETSLOT(NAME, as_async.SLOT, FUNCTION, WRAPPER, DOC) #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC) #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ @@ -6378,6 +6438,13 @@ "Create and return new object. See help(type) for accurate signature."), TPSLOT("__del__", tp_finalize, slot_tp_finalize, (wrapperfunc)wrap_del, ""), + AMSLOT("__await__", am_await, slot_am_await, wrap_unaryfunc, + "__await__($self, /)\n--\n\nReturn an iterator to be used in await expression."), + AMSLOT("__aiter__", am_aiter, slot_am_aiter, wrap_unaryfunc, + "__aiter__($self, /)\n--\n\nReturn an awaitable, that resolves in asynchronous iterator."), + AMSLOT("__anext__", am_anext, slot_am_anext, wrap_unaryfunc, + "__anext__($self, /)\n--\n\nReturn a value or raise StopAsyncIteration."), + BINSLOT("__add__", nb_add, slot_nb_add, "+"), RBINSLOT("__radd__", nb_add, slot_nb_add, @@ -6530,6 +6597,10 @@ ptr = (char *)type->tp_as_number; offset -= offsetof(PyHeapTypeObject, as_number); } + else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_async)) { + ptr = (char *)type->tp_as_async; + offset -= offsetof(PyHeapTypeObject, as_async); + } else { ptr = (char *)type; } diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -75,3 +75,6 @@ offsetof(PyHeapTypeObject, ht_type.tp_free), offsetof(PyHeapTypeObject, as_number.nb_matrix_multiply), offsetof(PyHeapTypeObject, as_number.nb_inplace_matrix_multiply), +offsetof(PyHeapTypeObject, as_async.am_await), +offsetof(PyHeapTypeObject, as_async.am_aiter), +offsetof(PyHeapTypeObject, as_async.am_anext), diff --git a/Objects/typeslots.py b/Objects/typeslots.py --- a/Objects/typeslots.py +++ b/Objects/typeslots.py @@ -12,6 +12,8 @@ member = m.group(1) if member.startswith("tp_"): member = "ht_type."+member + elif member.startswith("am_"): + member = "as_async."+member elif member.startswith("nb_"): member = "as_number."+member elif member.startswith("mp_"): diff --git a/Parser/Python.asdl b/Parser/Python.asdl --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -10,7 +10,10 @@ | Suite(stmt* body) stmt = FunctionDef(identifier name, arguments args, - stmt* body, expr* decorator_list, expr? returns) + stmt* body, expr* decorator_list, expr? returns) + | AsyncFunctionDef(identifier name, arguments args, + stmt* body, expr* decorator_list, expr? returns) + | ClassDef(identifier name, expr* bases, keyword* keywords, @@ -24,9 +27,11 @@ -- use 'orelse' because else is a keyword in target languages | For(expr target, expr iter, stmt* body, stmt* orelse) + | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse) | While(expr test, stmt* body, stmt* orelse) | If(expr test, stmt* body, stmt* orelse) | With(withitem* items, stmt* body) + | AsyncWith(withitem* items, stmt* body) | Raise(expr? exc, expr? cause) | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) @@ -57,6 +62,7 @@ | DictComp(expr key, expr value, comprehension* generators) | GeneratorExp(expr elt, comprehension* generators) -- the grammar constrains where yield expressions can occur + | Await(expr value) | Yield(expr? value) | YieldFrom(expr value) -- need sequences for compare to distinguish between diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -103,6 +103,8 @@ "ELLIPSIS", /* This table must match the #defines in token.h! */ "OP", + "AWAIT", + "ASYNC", "", "" }; @@ -124,6 +126,11 @@ tok->tabsize = TABSIZE; tok->indent = 0; tok->indstack[0] = 0; + + tok->def = 0; + tok->defstack[0] = 0; + tok->deftypestack[0] = 0; + tok->atbol = 1; tok->pendin = 0; tok->prompt = tok->nextprompt = NULL; @@ -1335,6 +1342,11 @@ int c; int blankline, nonascii; + int tok_len; + struct tok_state ahead_tok; + char *ahead_tok_start = NULL, *ahead_top_end = NULL; + int ahead_tok_kind; + *p_start = *p_end = NULL; nextline: tok->start = NULL; @@ -1422,6 +1434,11 @@ if (tok->pendin != 0) { if (tok->pendin < 0) { tok->pendin++; + + while (tok->def && tok->defstack[tok->def] >= tok->indent) { + tok->def--; + } + return DEDENT; } else { @@ -1481,6 +1498,57 @@ return ERRORTOKEN; *p_start = tok->start; *p_end = tok->cur; + + tok_len = tok->cur - tok->start; + if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { + + if (tok->def + 1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return ERRORTOKEN; + } + + if (tok->def && tok->deftypestack[tok->def] == 3) { + tok->deftypestack[tok->def] = 2; + } + else { + tok->def++; + tok->defstack[tok->def] = tok->indent; + tok->deftypestack[tok->def] = 1; + } + } + else if (tok_len == 5) { + if (memcmp(tok->start, "async", 5) == 0) { + memcpy(&ahead_tok, tok, sizeof(ahead_tok)); + + ahead_tok_kind = tok_get(&ahead_tok, &ahead_tok_start, + &ahead_top_end); + + if (ahead_tok_kind == NAME && + ahead_tok.cur - ahead_tok.start == 3 && + memcmp(ahead_tok.start, "def", 3) == 0) { + + tok->def++; + tok->defstack[tok->def] = tok->indent; + tok->deftypestack[tok->def] = 3; + + return ASYNC; + } + else if (tok->def && tok->deftypestack[tok->def] == 2 + && tok->defstack[tok->def] < tok->indent) { + + return ASYNC; + } + + } + else if (memcmp(tok->start, "await", 5) == 0 + && tok->def && tok->deftypestack[tok->def] == 2 + && tok->defstack[tok->def] < tok->indent) { + + return AWAIT; + } + } + return NAME; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -65,6 +65,13 @@ const char* enc; /* Encoding for the current str. */ const char* str; const char* input; /* Tokenizer's newline translated copy of the string. */ + + int defstack[MAXINDENT]; /* stack if funcs & indents where they + were defined */ + int deftypestack[MAXINDENT]; /* stack of func types + (0 not func; 1: "def name"; + 2: "async def name") */ + int def; /* Length of stack of func types */ }; extern struct tok_state *PyTokenizer_FromString(const char *, int); diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -45,6 +45,14 @@ "decorator_list", "returns", }; +static PyTypeObject *AsyncFunctionDef_type; +static char *AsyncFunctionDef_fields[]={ + "name", + "args", + "body", + "decorator_list", + "returns", +}; static PyTypeObject *ClassDef_type; _Py_IDENTIFIER(bases); _Py_IDENTIFIER(keywords); @@ -87,6 +95,13 @@ "body", "orelse", }; +static PyTypeObject *AsyncFor_type; +static char *AsyncFor_fields[]={ + "target", + "iter", + "body", + "orelse", +}; static PyTypeObject *While_type; _Py_IDENTIFIER(test); static char *While_fields[]={ @@ -106,6 +121,11 @@ "items", "body", }; +static PyTypeObject *AsyncWith_type; +static char *AsyncWith_fields[]={ + "items", + "body", +}; static PyTypeObject *Raise_type; _Py_IDENTIFIER(exc); _Py_IDENTIFIER(cause); @@ -228,6 +248,10 @@ "elt", "generators", }; +static PyTypeObject *Await_type; +static char *Await_fields[]={ + "value", +}; static PyTypeObject *Yield_type; static char *Yield_fields[]={ "value", @@ -806,6 +830,9 @@ FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, 5); if (!FunctionDef_type) return 0; + AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type, + AsyncFunctionDef_fields, 5); + if (!AsyncFunctionDef_type) return 0; ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5); if (!ClassDef_type) return 0; Return_type = make_type("Return", stmt_type, Return_fields, 1); @@ -818,12 +845,16 @@ if (!AugAssign_type) return 0; For_type = make_type("For", stmt_type, For_fields, 4); if (!For_type) return 0; + AsyncFor_type = make_type("AsyncFor", stmt_type, AsyncFor_fields, 4); + if (!AsyncFor_type) return 0; While_type = make_type("While", stmt_type, While_fields, 3); if (!While_type) return 0; If_type = make_type("If", stmt_type, If_fields, 3); if (!If_type) return 0; With_type = make_type("With", stmt_type, With_fields, 2); if (!With_type) return 0; + AsyncWith_type = make_type("AsyncWith", stmt_type, AsyncWith_fields, 2); + if (!AsyncWith_type) return 0; Raise_type = make_type("Raise", stmt_type, Raise_fields, 2); if (!Raise_type) return 0; Try_type = make_type("Try", stmt_type, Try_fields, 4); @@ -872,6 +903,8 @@ GeneratorExp_type = make_type("GeneratorExp", expr_type, GeneratorExp_fields, 2); if (!GeneratorExp_type) return 0; + Await_type = make_type("Await", expr_type, Await_fields, 1); + if (!Await_type) return 0; Yield_type = make_type("Yield", expr_type, Yield_fields, 1); if (!Yield_type) return 0; YieldFrom_type = make_type("YieldFrom", expr_type, YieldFrom_fields, 1); @@ -1201,6 +1234,36 @@ } stmt_ty +AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq + * decorator_list, expr_ty returns, int lineno, int col_offset, + PyArena *arena) +{ + stmt_ty p; + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field name is required for AsyncFunctionDef"); + return NULL; + } + if (!args) { + PyErr_SetString(PyExc_ValueError, + "field args is required for AsyncFunctionDef"); + return NULL; + } + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = AsyncFunctionDef_kind; + p->v.AsyncFunctionDef.name = name; + p->v.AsyncFunctionDef.args = args; + p->v.AsyncFunctionDef.body = body; + p->v.AsyncFunctionDef.decorator_list = decorator_list; + p->v.AsyncFunctionDef.returns = returns; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + +stmt_ty ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena *arena) @@ -1335,6 +1398,34 @@ } stmt_ty +AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int + lineno, int col_offset, PyArena *arena) +{ + stmt_ty p; + if (!target) { + PyErr_SetString(PyExc_ValueError, + "field target is required for AsyncFor"); + return NULL; + } + if (!iter) { + PyErr_SetString(PyExc_ValueError, + "field iter is required for AsyncFor"); + return NULL; + } + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = AsyncFor_kind; + p->v.AsyncFor.target = target; + p->v.AsyncFor.iter = iter; + p->v.AsyncFor.body = body; + p->v.AsyncFor.orelse = orelse; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + +stmt_ty While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int col_offset, PyArena *arena) { @@ -1395,6 +1486,22 @@ } stmt_ty +AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, + PyArena *arena) +{ + stmt_ty p; + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = AsyncWith_kind; + p->v.AsyncWith.items = items; + p->v.AsyncWith.body = body; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + +stmt_ty Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena) { stmt_ty p; @@ -1822,6 +1929,25 @@ } expr_ty +Await(expr_ty value, int lineno, int col_offset, PyArena *arena) +{ + expr_ty p; + if (!value) { + PyErr_SetString(PyExc_ValueError, + "field value is required for Await"); + return NULL; + } + p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = Await_kind; + p->v.Await.value = value; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + +expr_ty Yield(expr_ty value, int lineno, int col_offset, PyArena *arena) { expr_ty p; @@ -2409,6 +2535,36 @@ goto failed; Py_DECREF(value); break; + case AsyncFunctionDef_kind: + result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_identifier(o->v.AsyncFunctionDef.name); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_name, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_arguments(o->v.AsyncFunctionDef.args); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.AsyncFunctionDef.body, ast2obj_stmt); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.AsyncFunctionDef.decorator_list, + ast2obj_expr); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.AsyncFunctionDef.returns); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) + goto failed; + Py_DECREF(value); + break; case ClassDef_kind: result = PyType_GenericNew(ClassDef_type, NULL, NULL); if (!result) goto failed; @@ -2513,6 +2669,30 @@ goto failed; Py_DECREF(value); break; + case AsyncFor_kind: + result = PyType_GenericNew(AsyncFor_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.AsyncFor.target); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_target, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.AsyncFor.iter); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.AsyncFor.body, ast2obj_stmt); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.AsyncFor.orelse, ast2obj_stmt); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) + goto failed; + Py_DECREF(value); + break; case While_kind: result = PyType_GenericNew(While_type, NULL, NULL); if (!result) goto failed; @@ -2565,6 +2745,20 @@ goto failed; Py_DECREF(value); break; + case AsyncWith_kind: + result = PyType_GenericNew(AsyncWith_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_list(o->v.AsyncWith.items, ast2obj_withitem); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_items, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.AsyncWith.body, ast2obj_stmt); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) + goto failed; + Py_DECREF(value); + break; case Raise_kind: result = PyType_GenericNew(Raise_type, NULL, NULL); if (!result) goto failed; @@ -2878,6 +3072,15 @@ goto failed; Py_DECREF(value); break; + case Await_kind: + result = PyType_GenericNew(Await_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.Await.value); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) + goto failed; + Py_DECREF(value); + break; case Yield_kind: result = PyType_GenericNew(Yield_type, NULL, NULL); if (!result) goto failed; @@ -3832,6 +4035,102 @@ if (*out == NULL) goto failed; return 0; } + isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFunctionDef_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + identifier name; + arguments_ty args; + asdl_seq* body; + asdl_seq* decorator_list; + expr_ty returns; + + if (_PyObject_HasAttrId(obj, &PyId_name)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_name); + if (tmp == NULL) goto failed; + res = obj2ast_identifier(tmp, &name, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from AsyncFunctionDef"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_args)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_args); + if (tmp == NULL) goto failed; + res = obj2ast_arguments(tmp, &args, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from AsyncFunctionDef"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_body)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_body); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = _Py_asdl_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty value; + res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(body, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFunctionDef"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + decorator_list = _Py_asdl_seq_new(len, arena); + if (decorator_list == NULL) goto failed; + for (i = 0; i < len; i++) { + expr_ty value; + res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(decorator_list, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from AsyncFunctionDef"); + return 1; + } + if (exists_not_none(obj, &PyId_returns)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_returns); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &returns, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + returns = NULL; + } + *out = AsyncFunctionDef(name, args, body, decorator_list, returns, + lineno, col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } isinstance = PyObject_IsInstance(obj, (PyObject*)ClassDef_type); if (isinstance == -1) { return 1; @@ -4188,6 +4487,90 @@ if (*out == NULL) goto failed; return 0; } + isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFor_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty target; + expr_ty iter; + asdl_seq* body; + asdl_seq* orelse; + + if (_PyObject_HasAttrId(obj, &PyId_target)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_target); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &target, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AsyncFor"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_iter)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_iter); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &iter, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from AsyncFor"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_body)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_body); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncFor field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = _Py_asdl_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty value; + res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(body, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFor"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncFor field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + orelse = _Py_asdl_seq_new(len, arena); + if (orelse == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty value; + res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(orelse, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from AsyncFor"); + return 1; + } + *out = AsyncFor(target, iter, body, orelse, lineno, col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } isinstance = PyObject_IsInstance(obj, (PyObject*)While_type); if (isinstance == -1) { return 1; @@ -4392,6 +4775,66 @@ if (*out == NULL) goto failed; return 0; } + isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncWith_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + asdl_seq* items; + asdl_seq* body; + + if (_PyObject_HasAttrId(obj, &PyId_items)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_items); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncWith field \"items\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + items = _Py_asdl_seq_new(len, arena); + if (items == NULL) goto failed; + for (i = 0; i < len; i++) { + withitem_ty value; + res = obj2ast_withitem(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(items, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from AsyncWith"); + return 1; + } + if (_PyObject_HasAttrId(obj, &PyId_body)) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = _PyObject_GetAttrId(obj, &PyId_body); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncWith field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = _Py_asdl_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty value; + res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(body, i, value); + } + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncWith"); + return 1; + } + *out = AsyncWith(items, body, lineno, col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } isinstance = PyObject_IsInstance(obj, (PyObject*)Raise_type); if (isinstance == -1) { return 1; @@ -5326,6 +5769,28 @@ if (*out == NULL) goto failed; return 0; } + isinstance = PyObject_IsInstance(obj, (PyObject*)Await_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty value; + + if (_PyObject_HasAttrId(obj, &PyId_value)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_value); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &value, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } else { + PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Await"); + return 1; + } + *out = Await(value, lineno, col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } isinstance = PyObject_IsInstance(obj, (PyObject*)Yield_type); if (isinstance == -1) { return 1; @@ -6782,6 +7247,8 @@ if (PyDict_SetItemString(d, "stmt", (PyObject*)stmt_type) < 0) return NULL; if (PyDict_SetItemString(d, "FunctionDef", (PyObject*)FunctionDef_type) < 0) return NULL; + if (PyDict_SetItemString(d, "AsyncFunctionDef", + (PyObject*)AsyncFunctionDef_type) < 0) return NULL; if (PyDict_SetItemString(d, "ClassDef", (PyObject*)ClassDef_type) < 0) return NULL; if (PyDict_SetItemString(d, "Return", (PyObject*)Return_type) < 0) return @@ -6793,10 +7260,14 @@ if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0) return NULL; if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL; + if (PyDict_SetItemString(d, "AsyncFor", (PyObject*)AsyncFor_type) < 0) + return NULL; if (PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return NULL; if (PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return NULL; if (PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return NULL; + if (PyDict_SetItemString(d, "AsyncWith", (PyObject*)AsyncWith_type) < 0) + return NULL; if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return NULL; if (PyDict_SetItemString(d, "Try", (PyObject*)Try_type) < 0) return NULL; @@ -6837,6 +7308,8 @@ return NULL; if (PyDict_SetItemString(d, "GeneratorExp", (PyObject*)GeneratorExp_type) < 0) return NULL; + if (PyDict_SetItemString(d, "Await", (PyObject*)Await_type) < 0) return + NULL; if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return NULL; if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) < 0) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -219,6 +219,8 @@ return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load); case YieldFrom_kind: return validate_expr(exp->v.YieldFrom.value, Load); + case Await_kind: + return validate_expr(exp->v.Await.value, Load); case Compare_kind: if (!asdl_seq_LEN(exp->v.Compare.comparators)) { PyErr_SetString(PyExc_ValueError, "Compare with no comparators"); @@ -336,6 +338,11 @@ validate_expr(stmt->v.For.iter, Load) && validate_body(stmt->v.For.body, "For") && validate_stmts(stmt->v.For.orelse); + case AsyncFor_kind: + return validate_expr(stmt->v.AsyncFor.target, Store) && + validate_expr(stmt->v.AsyncFor.iter, Load) && + validate_body(stmt->v.AsyncFor.body, "AsyncFor") && + validate_stmts(stmt->v.AsyncFor.orelse); case While_kind: return validate_expr(stmt->v.While.test, Load) && validate_body(stmt->v.While.body, "While") && @@ -354,6 +361,16 @@ return 0; } return validate_body(stmt->v.With.body, "With"); + case AsyncWith_kind: + if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) + return 0; + for (i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) { + withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i); + if (!validate_expr(item->context_expr, Load) || + (item->optional_vars && !validate_expr(item->optional_vars, Store))) + return 0; + } + return validate_body(stmt->v.AsyncWith.body, "AsyncWith"); case Raise_kind: if (stmt->v.Raise.exc) { return validate_expr(stmt->v.Raise.exc, Load) && @@ -405,6 +422,12 @@ return validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal"); case Expr_kind: return validate_expr(stmt->v.Expr.value, Load); + case AsyncFunctionDef_kind: + return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") && + validate_arguments(stmt->v.AsyncFunctionDef.args) && + validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && + (!stmt->v.AsyncFunctionDef.returns || + validate_expr(stmt->v.AsyncFunctionDef.returns, Load)); case Pass_kind: case Break_kind: case Continue_kind: @@ -503,6 +526,9 @@ static expr_ty ast_for_testlist(struct compiling *, const node *); static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *); +static stmt_ty ast_for_with_stmt(struct compiling *, const node *, int); +static stmt_ty ast_for_for_stmt(struct compiling *, const node *, int); + /* Note different signature for ast_for_call */ static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); @@ -941,6 +967,9 @@ case YieldFrom_kind: expr_name = "yield expression"; break; + case Await_kind: + expr_name = "await expression"; + break; case ListComp_kind: expr_name = "list comprehension"; break; @@ -1480,7 +1509,8 @@ } static stmt_ty -ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) +ast_for_funcdef_impl(struct compiling *c, const node *n, + asdl_seq *decorator_seq, int is_async) { /* funcdef: 'def' NAME parameters ['->' test] ':' suite */ identifier name; @@ -1509,14 +1539,68 @@ if (!body) return NULL; - return FunctionDef(name, args, body, decorator_seq, returns, LINENO(n), - n->n_col_offset, c->c_arena); + if (is_async) + return AsyncFunctionDef(name, args, body, decorator_seq, returns, + LINENO(n), + n->n_col_offset, c->c_arena); + else + return FunctionDef(name, args, body, decorator_seq, returns, + LINENO(n), + n->n_col_offset, c->c_arena); +} + +static stmt_ty +ast_for_async_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) +{ + /* async_funcdef: ASYNC funcdef */ + REQ(n, async_funcdef); + REQ(CHILD(n, 0), ASYNC); + REQ(CHILD(n, 1), funcdef); + + return ast_for_funcdef_impl(c, CHILD(n, 1), decorator_seq, + 1 /* is_async */); +} + +static stmt_ty +ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) +{ + /* funcdef: 'def' NAME parameters ['->' test] ':' suite */ + return ast_for_funcdef_impl(c, n, decorator_seq, + 0 /* is_async */); +} + + +static stmt_ty +ast_for_async_stmt(struct compiling *c, const node *n) +{ + /* async_stmt: ASYNC (funcdef | with_stmt | for_stmt) */ + REQ(n, async_stmt); + REQ(CHILD(n, 0), ASYNC); + + switch (TYPE(CHILD(n, 1))) { + case funcdef: + return ast_for_funcdef_impl(c, CHILD(n, 1), NULL, + 1 /* is_async */); + case with_stmt: + return ast_for_with_stmt(c, CHILD(n, 1), + 1 /* is_async */); + + case for_stmt: + return ast_for_for_stmt(c, CHILD(n, 1), + 1 /* is_async */); + + default: + PyErr_Format(PyExc_SystemError, + "invalid async stament: %s", + STR(CHILD(n, 1))); + return NULL; + } } static stmt_ty ast_for_decorated(struct compiling *c, const node *n) { - /* decorated: decorators (classdef | funcdef) */ + /* decorated: decorators (classdef | funcdef | async_funcdef) */ stmt_ty thing = NULL; asdl_seq *decorator_seq = NULL; @@ -1527,12 +1611,15 @@ return NULL; assert(TYPE(CHILD(n, 1)) == funcdef || + TYPE(CHILD(n, 1)) == async_funcdef || TYPE(CHILD(n, 1)) == classdef); if (TYPE(CHILD(n, 1)) == funcdef) { thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq); } else if (TYPE(CHILD(n, 1)) == classdef) { thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq); + } else if (TYPE(CHILD(n, 1)) == async_funcdef) { + thing = ast_for_async_funcdef(c, CHILD(n, 1), decorator_seq); } /* we count the decorators in when talking about the class' or * function's line number */ @@ -2271,19 +2358,29 @@ } static expr_ty -ast_for_power(struct compiling *c, const node *n) +ast_for_atom_expr(struct compiling *c, const node *n) { - /* power: atom trailer* ('**' factor)* - */ - int i; + int i, nch, start = 0; expr_ty e, tmp; - REQ(n, power); - e = ast_for_atom(c, CHILD(n, 0)); + + REQ(n, atom_expr); + nch = NCH(n); + + if (TYPE(CHILD(n, 0)) == AWAIT) { + start = 1; + assert(nch > 1); + } + + e = ast_for_atom(c, CHILD(n, start)); if (!e) return NULL; - if (NCH(n) == 1) + if (nch == 1) return e; - for (i = 1; i < NCH(n); i++) { + if (start && nch == 2) { + return Await(e, LINENO(n), n->n_col_offset, c->c_arena); + } + + for (i = start + 1; i < nch; i++) { node *ch = CHILD(n, i); if (TYPE(ch) != trailer) break; @@ -2294,6 +2391,28 @@ tmp->col_offset = e->col_offset; e = tmp; } + + if (start) { + /* there was an AWAIT */ + return Await(e, LINENO(n), n->n_col_offset, c->c_arena); + } + else { + return e; + } +} + +static expr_ty +ast_for_power(struct compiling *c, const node *n) +{ + /* power: atom trailer* ('**' factor)* + */ + expr_ty e; + REQ(n, power); + e = ast_for_atom_expr(c, CHILD(n, 0)); + if (!e) + return NULL; + if (NCH(n) == 1) + return e; if (TYPE(CHILD(n, NCH(n) - 1)) == factor) { expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1)); if (!f) @@ -2338,7 +2457,9 @@ arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power - power: atom trailer* ('**' factor)* + power: atom_expr ['**' factor] + atom_expr: [AWAIT] atom trailer* + yield_expr: 'yield' [yield_arg] */ asdl_seq *seq; @@ -3403,7 +3524,7 @@ } static stmt_ty -ast_for_for_stmt(struct compiling *c, const node *n) +ast_for_for_stmt(struct compiling *c, const node *n, int is_async) { asdl_seq *_target, *seq = NULL, *suite_seq; expr_ty expression; @@ -3437,8 +3558,14 @@ if (!suite_seq) return NULL; - return For(target, expression, suite_seq, seq, LINENO(n), n->n_col_offset, - c->c_arena); + if (is_async) + return AsyncFor(target, expression, suite_seq, seq, + LINENO(n), n->n_col_offset, + c->c_arena); + else + return For(target, expression, suite_seq, seq, + LINENO(n), n->n_col_offset, + c->c_arena); } static excepthandler_ty @@ -3585,7 +3712,7 @@ /* with_stmt: 'with' with_item (',' with_item)* ':' suite */ static stmt_ty -ast_for_with_stmt(struct compiling *c, const node *n) +ast_for_with_stmt(struct compiling *c, const node *n, int is_async) { int i, n_items; asdl_seq *items, *body; @@ -3607,7 +3734,10 @@ if (!body) return NULL; - return With(items, body, LINENO(n), n->n_col_offset, c->c_arena); + if (is_async) + return AsyncWith(items, body, LINENO(n), n->n_col_offset, c->c_arena); + else + return With(items, body, LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty @@ -3714,7 +3844,7 @@ } else { /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt - | funcdef | classdef | decorated + | funcdef | classdef | decorated | async_stmt */ node *ch = CHILD(n, 0); REQ(n, compound_stmt); @@ -3724,17 +3854,19 @@ case while_stmt: return ast_for_while_stmt(c, ch); case for_stmt: - return ast_for_for_stmt(c, ch); + return ast_for_for_stmt(c, ch, 0); case try_stmt: return ast_for_try_stmt(c, ch); case with_stmt: - return ast_for_with_stmt(c, ch); + return ast_for_with_stmt(c, ch, 0); case funcdef: return ast_for_funcdef(c, ch, NULL); case classdef: return ast_for_classdef(c, ch, NULL); case decorated: return ast_for_decorated(c, ch); + case async_stmt: + return ast_for_async_stmt(c, ch); default: PyErr_Format(PyExc_SystemError, "unhandled small_stmt: TYPE=%d NCH=%d\n", diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1926,11 +1926,133 @@ goto fast_block_end; } + TARGET(GET_AITER) { + getaiterfunc getter = NULL; + PyObject *iter = NULL; + PyObject *awaitable = NULL; + PyObject *obj = TOP(); + PyTypeObject *type = Py_TYPE(obj); + + if (type->tp_as_async != NULL) + getter = type->tp_as_async->am_aiter; + + if (getter != NULL) { + iter = (*getter)(obj); + Py_DECREF(obj); + if (iter == NULL) { + SET_TOP(NULL); + goto error; + } + } + else { + SET_TOP(NULL); + PyErr_Format( + PyExc_TypeError, + "'async for' requires an object with " + "__aiter__ method, got %.100s", + type->tp_name); + Py_DECREF(obj); + goto error; + } + + awaitable = _PyGen_GetAwaitableIter(iter); + if (awaitable == NULL) { + SET_TOP(NULL); + PyErr_Format( + PyExc_TypeError, + "'async for' received an invalid object " + "from __aiter__: %.100s", + Py_TYPE(iter)->tp_name); + + Py_DECREF(iter); + goto error; + } else + Py_DECREF(iter); + + SET_TOP(awaitable); + DISPATCH(); + } + + TARGET(GET_ANEXT) { + aiternextfunc getter = NULL; + PyObject *next_iter = NULL; + PyObject *awaitable = NULL; + PyObject *aiter = TOP(); + PyTypeObject *type = Py_TYPE(aiter); + + if (type->tp_as_async != NULL) + getter = type->tp_as_async->am_anext; + + if (getter != NULL) { + next_iter = (*getter)(aiter); + if (next_iter == NULL) { + goto error; + } + } + else { + PyErr_Format( + PyExc_TypeError, + "'async for' requires an iterator with " + "__anext__ method, got %.100s", + type->tp_name); + goto error; + } + + awaitable = _PyGen_GetAwaitableIter(next_iter); + if (awaitable == NULL) { + PyErr_Format( + PyExc_TypeError, + "'async for' received an invalid object " + "from __anext__: %.100s", + Py_TYPE(next_iter)->tp_name); + + Py_DECREF(next_iter); + goto error; + } else + Py_DECREF(next_iter); + + PUSH(awaitable); + DISPATCH(); + } + + TARGET(GET_AWAITABLE) { + PyObject *iterable = TOP(); + PyObject *iter = _PyGen_GetAwaitableIter(iterable); + + Py_DECREF(iterable); + + SET_TOP(iter); /* Even if it's NULL */ + + if (iter == NULL) { + goto error; + } + + DISPATCH(); + } + TARGET(YIELD_FROM) { PyObject *v = POP(); PyObject *reciever = TOP(); int err; if (PyGen_CheckExact(reciever)) { + if ( + (((PyCodeObject*) \ + ((PyGenObject*)reciever)->gi_code)->co_flags & + CO_COROUTINE) + && !(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) + { + /* If we're yielding-from a coroutine object from a regular + generator object - raise an error. */ + + Py_CLEAR(v); + Py_CLEAR(reciever); + SET_TOP(NULL); + + PyErr_SetString(PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "from a generator"); + goto error; + } retval = _PyGen_Send((PyGenObject *)reciever, v); } else { _Py_IDENTIFIER(send); @@ -2822,11 +2944,26 @@ TARGET(GET_ITER) { /* before: [obj]; after [getiter(obj)] */ PyObject *iterable = TOP(); - PyObject *iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; + PyObject *iter; + /* If we have a generator object on top -- keep it there, + it's already an iterator. + + This is needed to allow use of 'async def' coroutines + in 'yield from' expression from generator-based coroutines + (decorated with types.coroutine()). + + 'yield from' is compiled to GET_ITER..YIELD_FROM combination, + but since coroutines raise TypeError in their 'tp_iter' we + need a way for them to "pass through" the GET_ITER. + */ + if (!PyGen_CheckExact(iterable)) { + /* `iterable` is not a generator. */ + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + } PREDICT(FOR_ITER); DISPATCH(); } @@ -2883,6 +3020,39 @@ DISPATCH(); } + TARGET(BEFORE_ASYNC_WITH) { + _Py_IDENTIFIER(__aexit__); + _Py_IDENTIFIER(__aenter__); + + PyObject *mgr = TOP(); + PyObject *exit = special_lookup(mgr, &PyId___aexit__), + *enter; + PyObject *res; + if (exit == NULL) + goto error; + SET_TOP(exit); + enter = special_lookup(mgr, &PyId___aenter__); + Py_DECREF(mgr); + if (enter == NULL) + goto error; + res = PyObject_CallFunctionObjArgs(enter, NULL); + Py_DECREF(enter); + if (res == NULL) + goto error; + PUSH(res); + DISPATCH(); + } + + TARGET(SETUP_ASYNC_WITH) { + PyObject *res = POP(); + /* Setup the finally block before pushing the result + of __aenter__ on the stack. */ + PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, + STACK_LEVEL()); + PUSH(res); + DISPATCH(); + } + TARGET(SETUP_WITH) { _Py_IDENTIFIER(__exit__); _Py_IDENTIFIER(__enter__); @@ -2909,7 +3079,7 @@ DISPATCH(); } - TARGET(WITH_CLEANUP) { + TARGET(WITH_CLEANUP_START) { /* At the top of the stack are 1-6 values indicating how/why we entered the finally clause: - TOP = None @@ -2937,7 +3107,6 @@ PyObject *exit_func; PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res; - int err; if (exc == Py_None) { (void)POP(); exit_func = TOP(); @@ -2987,10 +3156,23 @@ if (res == NULL) goto error; + PUSH(exc); + PUSH(res); + PREDICT(WITH_CLEANUP_FINISH); + DISPATCH(); + } + + PREDICTED(WITH_CLEANUP_FINISH); + TARGET(WITH_CLEANUP_FINISH) { + PyObject *res = POP(); + PyObject *exc = POP(); + int err; + if (exc != Py_None) err = PyObject_IsTrue(res); else err = 0; + Py_DECREF(res); if (err < 0) @@ -3751,6 +3933,9 @@ } if (co->co_flags & CO_GENERATOR) { + PyObject *gen; + PyObject *coroutine_wrapper; + /* Don't need to keep the reference to f_back, it will be set * when the generator is resumed. */ Py_CLEAR(f->f_back); @@ -3759,7 +3944,19 @@ /* Create a new generator that owns the ready to run frame * and return that as the value. */ - return PyGen_NewWithQualName(f, name, qualname); + gen = PyGen_NewWithQualName(f, name, qualname); + if (gen == NULL) + return NULL; + + if (co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) { + coroutine_wrapper = PyEval_GetCoroutineWrapper(); + if (coroutine_wrapper != NULL) { + PyObject *wrapped = + PyObject_CallFunction(coroutine_wrapper, "N", gen); + gen = wrapped; + } + } + return gen; } retval = PyEval_EvalFrameEx(f,0); @@ -4205,6 +4402,24 @@ || (tstate->c_profilefunc != NULL)); } +void +PyEval_SetCoroutineWrapper(PyObject *wrapper) +{ + PyThreadState *tstate = PyThreadState_GET(); + + Py_CLEAR(tstate->coroutine_wrapper); + + Py_XINCREF(wrapper); + tstate->coroutine_wrapper = wrapper; +} + +PyObject * +PyEval_GetCoroutineWrapper() +{ + PyThreadState *tstate = PyThreadState_GET(); + return tstate->coroutine_wrapper; +} + PyObject * PyEval_GetBuiltins(void) { diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -92,6 +92,7 @@ COMPILER_SCOPE_MODULE, COMPILER_SCOPE_CLASS, COMPILER_SCOPE_FUNCTION, + COMPILER_SCOPE_ASYNC_FUNCTION, COMPILER_SCOPE_LAMBDA, COMPILER_SCOPE_COMPREHENSION, }; @@ -193,6 +194,8 @@ static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty, int); +static int compiler_async_with(struct compiler *, stmt_ty, int); +static int compiler_async_for(struct compiler *, stmt_ty); static int compiler_call_helper(struct compiler *c, Py_ssize_t n, asdl_seq *args, asdl_seq *keywords); @@ -673,7 +676,9 @@ parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(parent); - if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { + if (u->u_scope_type == COMPILER_SCOPE_FUNCTION + || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION + || u->u_scope_type == COMPILER_SCOPE_CLASS) { assert(u->u_name); mangled = _Py_Mangle(parent->u_private, u->u_name); if (!mangled) @@ -687,6 +692,7 @@ if (!force_global) { if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION + || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION || parent->u_scope_type == COMPILER_SCOPE_LAMBDA) { dot_locals_str = _PyUnicode_FromId(&dot_locals); if (dot_locals_str == NULL) @@ -927,7 +933,9 @@ return 0; case SETUP_WITH: return 7; - case WITH_CLEANUP: + case WITH_CLEANUP_START: + return 1; + case WITH_CLEANUP_FINISH: return -1; /* XXX Sometimes more */ case RETURN_VALUE: return -1; @@ -1048,6 +1056,16 @@ return -1; case DELETE_DEREF: return 0; + case GET_AWAITABLE: + return 0; + case SETUP_ASYNC_WITH: + return 6; + case BEFORE_ASYNC_WITH: + return 1; + case GET_AITER: + return 0; + case GET_ANEXT: + return 1; default: return PY_INVALID_STACK_EFFECT; } @@ -1642,19 +1660,43 @@ } static int -compiler_function(struct compiler *c, stmt_ty s) +compiler_function(struct compiler *c, stmt_ty s, int is_async) { PyCodeObject *co; PyObject *qualname, *first_const = Py_None; - arguments_ty args = s->v.FunctionDef.args; - expr_ty returns = s->v.FunctionDef.returns; - asdl_seq* decos = s->v.FunctionDef.decorator_list; + arguments_ty args; + expr_ty returns; + identifier name; + asdl_seq* decos; + asdl_seq *body; stmt_ty st; Py_ssize_t i, n, arglength; int docstring, kw_default_count = 0; int num_annotations; - - assert(s->kind == FunctionDef_kind); + int scope_type; + + + if (is_async) { + assert(s->kind == AsyncFunctionDef_kind); + + args = s->v.AsyncFunctionDef.args; + returns = s->v.AsyncFunctionDef.returns; + decos = s->v.AsyncFunctionDef.decorator_list; + name = s->v.AsyncFunctionDef.name; + body = s->v.AsyncFunctionDef.body; + + scope_type = COMPILER_SCOPE_ASYNC_FUNCTION; + } else { + assert(s->kind == FunctionDef_kind); + + args = s->v.FunctionDef.args; + returns = s->v.FunctionDef.returns; + decos = s->v.FunctionDef.decorator_list; + name = s->v.FunctionDef.name; + body = s->v.FunctionDef.body; + + scope_type = COMPILER_SCOPE_FUNCTION; + } if (!compiler_decorators(c, decos)) return 0; @@ -1672,12 +1714,12 @@ return 0; assert((num_annotations & 0xFFFF) == num_annotations); - if (!compiler_enter_scope(c, s->v.FunctionDef.name, - COMPILER_SCOPE_FUNCTION, (void *)s, + if (!compiler_enter_scope(c, name, + scope_type, (void *)s, s->lineno)) return 0; - st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); + st = (stmt_ty)asdl_seq_GET(body, 0); docstring = compiler_isdocstring(st); if (docstring && c->c_optimize < 2) first_const = st->v.Expr.value->v.Str.s; @@ -1688,10 +1730,10 @@ c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - n = asdl_seq_LEN(s->v.FunctionDef.body); + n = asdl_seq_LEN(body); /* if there was a docstring, we need to skip the first statement */ for (i = docstring; i < n; i++) { - st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i); + st = (stmt_ty)asdl_seq_GET(body, i); VISIT_IN_SCOPE(c, stmt, st); } co = assemble(c, 1); @@ -1711,12 +1753,19 @@ Py_DECREF(qualname); Py_DECREF(co); + if (is_async) { + co->co_flags |= CO_COROUTINE; + /* An async function is always a generator, even + if there is no 'yield' expressions in it. */ + co->co_flags |= CO_GENERATOR; + } + /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); } - return compiler_nameop(c, s->v.FunctionDef.name, Store); + return compiler_nameop(c, name, Store); } static int @@ -1989,6 +2038,92 @@ return 1; } + +static int +compiler_async_for(struct compiler *c, stmt_ty s) +{ + static PyObject *stopiter_error = NULL; + basicblock *try, *except, *end, *after_try, *try_cleanup, + *after_loop, *after_loop_else; + + if (stopiter_error == NULL) { + stopiter_error = PyUnicode_InternFromString("StopAsyncIteration"); + if (stopiter_error == NULL) + return 0; + } + + try = compiler_new_block(c); + except = compiler_new_block(c); + end = compiler_new_block(c); + after_try = compiler_new_block(c); + try_cleanup = compiler_new_block(c); + after_loop = compiler_new_block(c); + after_loop_else = compiler_new_block(c); + + if (try == NULL || except == NULL || end == NULL + || after_try == NULL || try_cleanup == NULL) + return 0; + + ADDOP_JREL(c, SETUP_LOOP, after_loop); + if (!compiler_push_fblock(c, LOOP, try)) + return 0; + + VISIT(c, expr, s->v.AsyncFor.iter); + ADDOP(c, GET_AITER); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, YIELD_FROM); + + compiler_use_next_block(c, try); + + + ADDOP_JREL(c, SETUP_EXCEPT, except); + if (!compiler_push_fblock(c, EXCEPT, try)) + 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); + compiler_pop_fblock(c, EXCEPT, try); + ADDOP_JREL(c, JUMP_FORWARD, after_try); + + + compiler_use_next_block(c, except); + ADDOP(c, DUP_TOP); + ADDOP_O(c, LOAD_GLOBAL, stopiter_error, names); + ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, try_cleanup); + + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + ADDOP(c, POP_EXCEPT); /* for SETUP_EXCEPT */ + ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */ + ADDOP_JABS(c, JUMP_ABSOLUTE, after_loop_else); + + + compiler_use_next_block(c, try_cleanup); + ADDOP(c, END_FINALLY); + + 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_use_next_block(c, after_loop); + ADDOP_JABS(c, JUMP_ABSOLUTE, end); + + compiler_use_next_block(c, after_loop_else); + VISIT_SEQ(c, stmt, s->v.For.orelse); + + compiler_use_next_block(c, end); + + return 1; +} + static int compiler_while(struct compiler *c, stmt_ty s) { @@ -2515,7 +2650,7 @@ switch (s->kind) { case FunctionDef_kind: - return compiler_function(c, s); + return compiler_function(c, s, 0); case ClassDef_kind: return compiler_class(c, s); case Return_kind: @@ -2594,7 +2729,14 @@ return compiler_continue(c); case With_kind: return compiler_with(c, s, 0); + case AsyncFunctionDef_kind: + return compiler_function(c, s, 1); + case AsyncWith_kind: + return compiler_async_with(c, s, 0); + case AsyncFor_kind: + return compiler_async_for(c, s); } + return 1; } @@ -3471,6 +3613,102 @@ } } + +/* + Implements the async with statement. + + The semantics outlined in that PEP are as follows: + + async with EXPR as VAR: + BLOCK + + It is implemented roughly as: + + context = EXPR + exit = context.__aexit__ # not calling it + value = await context.__aenter__() + try: + VAR = value # if VAR present in the syntax + BLOCK + finally: + if an exception was raised: + exc = copy of (exception, instance, traceback) + else: + exc = (None, None, None) + if not (await exit(*exc)): + raise + */ +static int +compiler_async_with(struct compiler *c, stmt_ty s, int pos) +{ + basicblock *block, *finally; + withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos); + + assert(s->kind == AsyncWith_kind); + + block = compiler_new_block(c); + finally = compiler_new_block(c); + if (!block || !finally) + return 0; + + /* Evaluate EXPR */ + VISIT(c, expr, item->context_expr); + + ADDOP(c, BEFORE_ASYNC_WITH); + ADDOP(c, GET_AWAITABLE); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, YIELD_FROM); + + ADDOP_JREL(c, SETUP_ASYNC_WITH, finally); + + /* SETUP_ASYNC_WITH pushes a finally block. */ + compiler_use_next_block(c, block); + if (!compiler_push_fblock(c, FINALLY_TRY, block)) { + return 0; + } + + if (item->optional_vars) { + VISIT(c, expr, item->optional_vars); + } + else { + /* Discard result from context.__aenter__() */ + ADDOP(c, POP_TOP); + } + + pos++; + if (pos == asdl_seq_LEN(s->v.AsyncWith.items)) + /* BLOCK code */ + VISIT_SEQ(c, stmt, s->v.AsyncWith.body) + else if (!compiler_async_with(c, s, pos)) + return 0; + + /* End of try block; start the finally block */ + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, FINALLY_TRY, block); + + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, finally); + if (!compiler_push_fblock(c, FINALLY_END, finally)) + return 0; + + /* Finally block starts; context.__exit__ is on the stack under + the exception or return information. Just issue our magic + opcode. */ + ADDOP(c, WITH_CLEANUP_START); + + ADDOP(c, GET_AWAITABLE); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, YIELD_FROM); + + ADDOP(c, WITH_CLEANUP_FINISH); + + /* Finally block ends. */ + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, finally); + return 1; +} + + /* Implements the with statement from PEP 343. @@ -3544,7 +3782,8 @@ /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic opcode. */ - ADDOP(c, WITH_CLEANUP); + ADDOP(c, WITH_CLEANUP_START); + ADDOP(c, WITH_CLEANUP_FINISH); /* Finally block ends. */ ADDOP(c, END_FINALLY); @@ -3595,6 +3834,8 @@ case Yield_kind: if (c->u->u_ste->ste_type != FunctionBlock) return compiler_error(c, "'yield' outside function"); + if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) + return compiler_error(c, "'yield' inside async function"); if (e->v.Yield.value) { VISIT(c, expr, e->v.Yield.value); } @@ -3606,11 +3847,28 @@ case YieldFrom_kind: if (c->u->u_ste->ste_type != FunctionBlock) return compiler_error(c, "'yield' outside function"); + + if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) + return compiler_error(c, "'yield from' inside async function"); + VISIT(c, expr, e->v.YieldFrom.value); ADDOP(c, GET_ITER); ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, YIELD_FROM); break; + case Await_kind: + if (c->u->u_ste->ste_type != FunctionBlock) + return compiler_error(c, "'await' outside function"); + + /* this check won't be triggered while we have AWAIT token */ + if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) + return compiler_error(c, "'await' outside async function"); + + VISIT(c, expr, e->v.Await.value); + ADDOP(c, GET_AWAITABLE); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, YIELD_FROM); + break; case Compare_kind: return compiler_compare(c, e); case Call_kind: diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -92,393 +92,406 @@ static arc arcs_5_0[1] = { {16, 1}, }; -static arc arcs_5_1[2] = { +static arc arcs_5_1[3] = { {18, 2}, {19, 2}, + {20, 2}, }; static arc arcs_5_2[1] = { {0, 2}, }; static state states_5[3] = { {1, arcs_5_0}, - {2, arcs_5_1}, + {3, arcs_5_1}, {1, arcs_5_2}, }; static arc arcs_6_0[1] = { - {20, 1}, + {21, 1}, }; static arc arcs_6_1[1] = { - {21, 2}, + {19, 2}, }; static arc arcs_6_2[1] = { - {22, 3}, -}; -static arc arcs_6_3[2] = { - {23, 4}, - {25, 5}, -}; -static arc arcs_6_4[1] = { - {24, 6}, -}; -static arc arcs_6_5[1] = { - {26, 7}, -}; -static arc arcs_6_6[1] = { - {25, 5}, -}; -static arc arcs_6_7[1] = { - {0, 7}, -}; -static state states_6[8] = { + {0, 2}, +}; +static state states_6[3] = { {1, arcs_6_0}, {1, arcs_6_1}, {1, arcs_6_2}, - {2, arcs_6_3}, - {1, arcs_6_4}, - {1, arcs_6_5}, - {1, arcs_6_6}, - {1, arcs_6_7}, }; static arc arcs_7_0[1] = { + {22, 1}, +}; +static arc arcs_7_1[1] = { + {23, 2}, +}; +static arc arcs_7_2[1] = { + {24, 3}, +}; +static arc arcs_7_3[2] = { + {25, 4}, + {27, 5}, +}; +static arc arcs_7_4[1] = { + {26, 6}, +}; +static arc arcs_7_5[1] = { + {28, 7}, +}; +static arc arcs_7_6[1] = { + {27, 5}, +}; +static arc arcs_7_7[1] = { + {0, 7}, +}; +static state states_7[8] = { + {1, arcs_7_0}, + {1, arcs_7_1}, + {1, arcs_7_2}, + {2, arcs_7_3}, + {1, arcs_7_4}, + {1, arcs_7_5}, + {1, arcs_7_6}, + {1, arcs_7_7}, +}; +static arc arcs_8_0[1] = { {13, 1}, }; -static arc arcs_7_1[2] = { +static arc arcs_8_1[2] = { + {29, 2}, + {15, 3}, +}; +static arc arcs_8_2[1] = { + {15, 3}, +}; +static arc arcs_8_3[1] = { + {0, 3}, +}; +static state states_8[4] = { + {1, arcs_8_0}, + {2, arcs_8_1}, + {1, arcs_8_2}, + {1, arcs_8_3}, +}; +static arc arcs_9_0[3] = { + {30, 1}, + {33, 2}, + {34, 3}, +}; +static arc arcs_9_1[3] = { + {31, 4}, + {32, 5}, + {0, 1}, +}; +static arc arcs_9_2[3] = { + {30, 6}, + {32, 7}, + {0, 2}, +}; +static arc arcs_9_3[1] = { + {30, 8}, +}; +static arc arcs_9_4[1] = { + {26, 9}, +}; +static arc arcs_9_5[4] = { + {30, 10}, + {33, 11}, + {34, 3}, + {0, 5}, +}; +static arc arcs_9_6[2] = { + {32, 7}, + {0, 6}, +}; +static arc arcs_9_7[2] = { + {30, 12}, + {34, 3}, +}; +static arc arcs_9_8[1] = { + {0, 8}, +}; +static arc arcs_9_9[2] = { + {32, 5}, + {0, 9}, +}; +static arc arcs_9_10[3] = { + {32, 5}, + {31, 4}, + {0, 10}, +}; +static arc arcs_9_11[3] = { + {30, 13}, + {32, 14}, + {0, 11}, +}; +static arc arcs_9_12[3] = { + {32, 7}, + {31, 15}, + {0, 12}, +}; +static arc arcs_9_13[2] = { + {32, 14}, + {0, 13}, +}; +static arc arcs_9_14[2] = { + {30, 16}, + {34, 3}, +}; +static arc arcs_9_15[1] = { + {26, 6}, +}; +static arc arcs_9_16[3] = { + {32, 14}, + {31, 17}, + {0, 16}, +}; +static arc arcs_9_17[1] = { + {26, 13}, +}; +static state states_9[18] = { + {3, arcs_9_0}, + {3, arcs_9_1}, + {3, arcs_9_2}, + {1, arcs_9_3}, + {1, arcs_9_4}, + {4, arcs_9_5}, + {2, arcs_9_6}, + {2, arcs_9_7}, + {1, arcs_9_8}, + {2, arcs_9_9}, + {3, arcs_9_10}, + {3, arcs_9_11}, + {3, arcs_9_12}, + {2, arcs_9_13}, + {2, arcs_9_14}, + {1, arcs_9_15}, + {3, arcs_9_16}, + {1, arcs_9_17}, +}; +static arc arcs_10_0[1] = { + {23, 1}, +}; +static arc arcs_10_1[2] = { {27, 2}, - {15, 3}, -}; -static arc arcs_7_2[1] = { - {15, 3}, -}; -static arc arcs_7_3[1] = { + {0, 1}, +}; +static arc arcs_10_2[1] = { + {26, 3}, +}; +static arc arcs_10_3[1] = { {0, 3}, }; -static state states_7[4] = { - {1, arcs_7_0}, - {2, arcs_7_1}, - {1, arcs_7_2}, - {1, arcs_7_3}, -}; -static arc arcs_8_0[3] = { - {28, 1}, - {31, 2}, - {32, 3}, -}; -static arc arcs_8_1[3] = { - {29, 4}, - {30, 5}, +static state states_10[4] = { + {1, arcs_10_0}, + {2, arcs_10_1}, + {1, arcs_10_2}, + {1, arcs_10_3}, +}; +static arc arcs_11_0[3] = { + {36, 1}, + {33, 2}, + {34, 3}, +}; +static arc arcs_11_1[3] = { + {31, 4}, + {32, 5}, {0, 1}, }; -static arc arcs_8_2[3] = { - {28, 6}, - {30, 7}, +static arc arcs_11_2[3] = { + {36, 6}, + {32, 7}, {0, 2}, }; -static arc arcs_8_3[1] = { - {28, 8}, -}; -static arc arcs_8_4[1] = { - {24, 9}, -}; -static arc arcs_8_5[4] = { - {28, 10}, - {31, 11}, - {32, 3}, +static arc arcs_11_3[1] = { + {36, 8}, +}; +static arc arcs_11_4[1] = { + {26, 9}, +}; +static arc arcs_11_5[4] = { + {36, 10}, + {33, 11}, + {34, 3}, {0, 5}, }; -static arc arcs_8_6[2] = { - {30, 7}, +static arc arcs_11_6[2] = { + {32, 7}, {0, 6}, }; -static arc arcs_8_7[2] = { - {28, 12}, - {32, 3}, -}; -static arc arcs_8_8[1] = { +static arc arcs_11_7[2] = { + {36, 12}, + {34, 3}, +}; +static arc arcs_11_8[1] = { {0, 8}, }; -static arc arcs_8_9[2] = { - {30, 5}, +static arc arcs_11_9[2] = { + {32, 5}, {0, 9}, }; -static arc arcs_8_10[3] = { - {30, 5}, - {29, 4}, +static arc arcs_11_10[3] = { + {32, 5}, + {31, 4}, {0, 10}, }; -static arc arcs_8_11[3] = { - {28, 13}, - {30, 14}, +static arc arcs_11_11[3] = { + {36, 13}, + {32, 14}, {0, 11}, }; -static arc arcs_8_12[3] = { - {30, 7}, - {29, 15}, +static arc arcs_11_12[3] = { + {32, 7}, + {31, 15}, {0, 12}, }; -static arc arcs_8_13[2] = { - {30, 14}, +static arc arcs_11_13[2] = { + {32, 14}, {0, 13}, }; -static arc arcs_8_14[2] = { - {28, 16}, - {32, 3}, -}; -static arc arcs_8_15[1] = { - {24, 6}, -}; -static arc arcs_8_16[3] = { - {30, 14}, - {29, 17}, +static arc arcs_11_14[2] = { + {36, 16}, + {34, 3}, +}; +static arc arcs_11_15[1] = { + {26, 6}, +}; +static arc arcs_11_16[3] = { + {32, 14}, + {31, 17}, {0, 16}, }; -static arc arcs_8_17[1] = { - {24, 13}, -}; -static state states_8[18] = { - {3, arcs_8_0}, - {3, arcs_8_1}, - {3, arcs_8_2}, - {1, arcs_8_3}, - {1, arcs_8_4}, - {4, arcs_8_5}, - {2, arcs_8_6}, - {2, arcs_8_7}, - {1, arcs_8_8}, - {2, arcs_8_9}, - {3, arcs_8_10}, - {3, arcs_8_11}, - {3, arcs_8_12}, - {2, arcs_8_13}, - {2, arcs_8_14}, - {1, arcs_8_15}, - {3, arcs_8_16}, - {1, arcs_8_17}, -}; -static arc arcs_9_0[1] = { - {21, 1}, -}; -static arc arcs_9_1[2] = { - {25, 2}, +static arc arcs_11_17[1] = { + {26, 13}, +}; +static state states_11[18] = { + {3, arcs_11_0}, + {3, arcs_11_1}, + {3, arcs_11_2}, + {1, arcs_11_3}, + {1, arcs_11_4}, + {4, arcs_11_5}, + {2, arcs_11_6}, + {2, arcs_11_7}, + {1, arcs_11_8}, + {2, arcs_11_9}, + {3, arcs_11_10}, + {3, arcs_11_11}, + {3, arcs_11_12}, + {2, arcs_11_13}, + {2, arcs_11_14}, + {1, arcs_11_15}, + {3, arcs_11_16}, + {1, arcs_11_17}, +}; +static arc arcs_12_0[1] = { + {23, 1}, +}; +static arc arcs_12_1[1] = { {0, 1}, }; -static arc arcs_9_2[1] = { - {24, 3}, -}; -static arc arcs_9_3[1] = { - {0, 3}, -}; -static state states_9[4] = { - {1, arcs_9_0}, - {2, arcs_9_1}, - {1, arcs_9_2}, - {1, arcs_9_3}, -}; -static arc arcs_10_0[3] = { - {34, 1}, - {31, 2}, - {32, 3}, -}; -static arc arcs_10_1[3] = { - {29, 4}, - {30, 5}, - {0, 1}, -}; -static arc arcs_10_2[3] = { - {34, 6}, - {30, 7}, - {0, 2}, -}; -static arc arcs_10_3[1] = { - {34, 8}, -}; -static arc arcs_10_4[1] = { - {24, 9}, -}; -static arc arcs_10_5[4] = { - {34, 10}, - {31, 11}, - {32, 3}, - {0, 5}, -}; -static arc arcs_10_6[2] = { - {30, 7}, - {0, 6}, -}; -static arc arcs_10_7[2] = { - {34, 12}, - {32, 3}, -}; -static arc arcs_10_8[1] = { - {0, 8}, -}; -static arc arcs_10_9[2] = { - {30, 5}, - {0, 9}, -}; -static arc arcs_10_10[3] = { - {30, 5}, - {29, 4}, - {0, 10}, -}; -static arc arcs_10_11[3] = { - {34, 13}, - {30, 14}, - {0, 11}, -}; -static arc arcs_10_12[3] = { - {30, 7}, - {29, 15}, - {0, 12}, -}; -static arc arcs_10_13[2] = { - {30, 14}, - {0, 13}, -}; -static arc arcs_10_14[2] = { - {34, 16}, - {32, 3}, -}; -static arc arcs_10_15[1] = { - {24, 6}, -}; -static arc arcs_10_16[3] = { - {30, 14}, - {29, 17}, - {0, 16}, -}; -static arc arcs_10_17[1] = { - {24, 13}, -}; -static state states_10[18] = { - {3, arcs_10_0}, - {3, arcs_10_1}, - {3, arcs_10_2}, - {1, arcs_10_3}, - {1, arcs_10_4}, - {4, arcs_10_5}, - {2, arcs_10_6}, - {2, arcs_10_7}, - {1, arcs_10_8}, - {2, arcs_10_9}, - {3, arcs_10_10}, - {3, arcs_10_11}, - {3, arcs_10_12}, - {2, arcs_10_13}, - {2, arcs_10_14}, - {1, arcs_10_15}, - {3, arcs_10_16}, - {1, arcs_10_17}, -}; -static arc arcs_11_0[1] = { - {21, 1}, -}; -static arc arcs_11_1[1] = { - {0, 1}, -}; -static state states_11[2] = { - {1, arcs_11_0}, - {1, arcs_11_1}, -}; -static arc arcs_12_0[2] = { +static state states_12[2] = { + {1, arcs_12_0}, + {1, arcs_12_1}, +}; +static arc arcs_13_0[2] = { {3, 1}, {4, 1}, }; -static arc arcs_12_1[1] = { +static arc arcs_13_1[1] = { {0, 1}, }; -static state states_12[2] = { - {2, arcs_12_0}, - {1, arcs_12_1}, -}; -static arc arcs_13_0[1] = { - {35, 1}, -}; -static arc arcs_13_1[2] = { - {36, 2}, +static state states_13[2] = { + {2, arcs_13_0}, + {1, arcs_13_1}, +}; +static arc arcs_14_0[1] = { + {37, 1}, +}; +static arc arcs_14_1[2] = { + {38, 2}, {2, 3}, }; -static arc arcs_13_2[2] = { - {35, 1}, +static arc arcs_14_2[2] = { + {37, 1}, {2, 3}, }; -static arc arcs_13_3[1] = { +static arc arcs_14_3[1] = { {0, 3}, }; -static state states_13[4] = { - {1, arcs_13_0}, - {2, arcs_13_1}, - {2, arcs_13_2}, - {1, arcs_13_3}, -}; -static arc arcs_14_0[8] = { - {37, 1}, - {38, 1}, +static state states_14[4] = { + {1, arcs_14_0}, + {2, arcs_14_1}, + {2, arcs_14_2}, + {1, arcs_14_3}, +}; +static arc arcs_15_0[8] = { {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, -}; -static arc arcs_14_1[1] = { + {45, 1}, + {46, 1}, +}; +static arc arcs_15_1[1] = { {0, 1}, }; -static state states_14[2] = { - {8, arcs_14_0}, - {1, arcs_14_1}, -}; -static arc arcs_15_0[1] = { - {45, 1}, -}; -static arc arcs_15_1[3] = { - {46, 2}, - {29, 3}, +static state states_15[2] = { + {8, arcs_15_0}, + {1, arcs_15_1}, +}; +static arc arcs_16_0[1] = { + {47, 1}, +}; +static arc arcs_16_1[3] = { + {48, 2}, + {31, 3}, {0, 1}, }; -static arc arcs_15_2[2] = { - {47, 4}, +static arc arcs_16_2[2] = { + {49, 4}, {9, 4}, }; -static arc arcs_15_3[2] = { +static arc arcs_16_3[2] = { + {49, 5}, {47, 5}, - {45, 5}, -}; -static arc arcs_15_4[1] = { +}; +static arc arcs_16_4[1] = { {0, 4}, }; -static arc arcs_15_5[2] = { - {29, 3}, +static arc arcs_16_5[2] = { + {31, 3}, {0, 5}, }; -static state states_15[6] = { - {1, arcs_15_0}, - {3, arcs_15_1}, - {2, arcs_15_2}, - {2, arcs_15_3}, - {1, arcs_15_4}, - {2, arcs_15_5}, -}; -static arc arcs_16_0[2] = { - {24, 1}, - {48, 1}, -}; -static arc arcs_16_1[2] = { - {30, 2}, +static state states_16[6] = { + {1, arcs_16_0}, + {3, arcs_16_1}, + {2, arcs_16_2}, + {2, arcs_16_3}, + {1, arcs_16_4}, + {2, arcs_16_5}, +}; +static arc arcs_17_0[2] = { + {26, 1}, + {50, 1}, +}; +static arc arcs_17_1[2] = { + {32, 2}, {0, 1}, }; -static arc arcs_16_2[3] = { - {24, 1}, - {48, 1}, +static arc arcs_17_2[3] = { + {26, 1}, + {50, 1}, {0, 2}, }; -static state states_16[3] = { - {2, arcs_16_0}, - {2, arcs_16_1}, - {3, arcs_16_2}, -}; -static arc arcs_17_0[13] = { - {49, 1}, - {50, 1}, +static state states_17[3] = { + {2, arcs_17_0}, + {2, arcs_17_1}, + {3, arcs_17_2}, +}; +static arc arcs_18_0[13] = { {51, 1}, {52, 1}, {53, 1}, @@ -490,64 +503,56 @@ {59, 1}, {60, 1}, {61, 1}, -}; -static arc arcs_17_1[1] = { + {62, 1}, + {63, 1}, +}; +static arc arcs_18_1[1] = { {0, 1}, }; -static state states_17[2] = { - {13, arcs_17_0}, - {1, arcs_17_1}, -}; -static arc arcs_18_0[1] = { - {62, 1}, -}; -static arc arcs_18_1[1] = { - {63, 2}, -}; -static arc arcs_18_2[1] = { - {0, 2}, -}; -static state states_18[3] = { - {1, arcs_18_0}, +static state states_18[2] = { + {13, arcs_18_0}, {1, arcs_18_1}, - {1, arcs_18_2}, }; static arc arcs_19_0[1] = { {64, 1}, }; static arc arcs_19_1[1] = { - {0, 1}, -}; -static state states_19[2] = { + {65, 2}, +}; +static arc arcs_19_2[1] = { + {0, 2}, +}; +static state states_19[3] = { {1, arcs_19_0}, {1, arcs_19_1}, -}; -static arc arcs_20_0[5] = { - {65, 1}, + {1, arcs_19_2}, +}; +static arc arcs_20_0[1] = { {66, 1}, +}; +static arc arcs_20_1[1] = { + {0, 1}, +}; +static state states_20[2] = { + {1, arcs_20_0}, + {1, arcs_20_1}, +}; +static arc arcs_21_0[5] = { {67, 1}, {68, 1}, {69, 1}, -}; -static arc arcs_20_1[1] = { - {0, 1}, -}; -static state states_20[2] = { - {5, arcs_20_0}, - {1, arcs_20_1}, -}; -static arc arcs_21_0[1] = { {70, 1}, + {71, 1}, }; static arc arcs_21_1[1] = { {0, 1}, }; static state states_21[2] = { - {1, arcs_21_0}, + {5, arcs_21_0}, {1, arcs_21_1}, }; static arc arcs_22_0[1] = { - {71, 1}, + {72, 1}, }; static arc arcs_22_1[1] = { {0, 1}, @@ -557,148 +562,139 @@ {1, arcs_22_1}, }; static arc arcs_23_0[1] = { - {72, 1}, -}; -static arc arcs_23_1[2] = { + {73, 1}, +}; +static arc arcs_23_1[1] = { + {0, 1}, +}; +static state states_23[2] = { + {1, arcs_23_0}, + {1, arcs_23_1}, +}; +static arc arcs_24_0[1] = { + {74, 1}, +}; +static arc arcs_24_1[2] = { {9, 2}, {0, 1}, }; -static arc arcs_23_2[1] = { +static arc arcs_24_2[1] = { {0, 2}, }; -static state states_23[3] = { - {1, arcs_23_0}, - {2, arcs_23_1}, - {1, arcs_23_2}, -}; -static arc arcs_24_0[1] = { - {47, 1}, -}; -static arc arcs_24_1[1] = { +static state states_24[3] = { + {1, arcs_24_0}, + {2, arcs_24_1}, + {1, arcs_24_2}, +}; +static arc arcs_25_0[1] = { + {49, 1}, +}; +static arc arcs_25_1[1] = { {0, 1}, }; -static state states_24[2] = { - {1, arcs_24_0}, - {1, arcs_24_1}, -}; -static arc arcs_25_0[1] = { - {73, 1}, -}; -static arc arcs_25_1[2] = { - {24, 2}, +static state states_25[2] = { + {1, arcs_25_0}, + {1, arcs_25_1}, +}; +static arc arcs_26_0[1] = { + {75, 1}, +}; +static arc arcs_26_1[2] = { + {26, 2}, {0, 1}, }; -static arc arcs_25_2[2] = { - {74, 3}, +static arc arcs_26_2[2] = { + {76, 3}, {0, 2}, }; -static arc arcs_25_3[1] = { - {24, 4}, -}; -static arc arcs_25_4[1] = { +static arc arcs_26_3[1] = { + {26, 4}, +}; +static arc arcs_26_4[1] = { {0, 4}, }; -static state states_25[5] = { - {1, arcs_25_0}, - {2, arcs_25_1}, - {2, arcs_25_2}, - {1, arcs_25_3}, - {1, arcs_25_4}, -}; -static arc arcs_26_0[2] = { - {75, 1}, +static state states_26[5] = { + {1, arcs_26_0}, + {2, arcs_26_1}, + {2, arcs_26_2}, + {1, arcs_26_3}, + {1, arcs_26_4}, +}; +static arc arcs_27_0[2] = { + {77, 1}, + {78, 1}, +}; +static arc arcs_27_1[1] = { + {0, 1}, +}; +static state states_27[2] = { + {2, arcs_27_0}, + {1, arcs_27_1}, +}; +static arc arcs_28_0[1] = { + {79, 1}, +}; +static arc arcs_28_1[1] = { + {80, 2}, +}; +static arc arcs_28_2[1] = { + {0, 2}, +}; +static state states_28[3] = { + {1, arcs_28_0}, + {1, arcs_28_1}, + {1, arcs_28_2}, +}; +static arc arcs_29_0[1] = { {76, 1}, }; -static arc arcs_26_1[1] = { +static arc arcs_29_1[3] = { + {81, 2}, + {82, 2}, + {12, 3}, +}; +static arc arcs_29_2[4] = { + {81, 2}, + {82, 2}, + {12, 3}, + {79, 4}, +}; +static arc arcs_29_3[1] = { + {79, 4}, +}; +static arc arcs_29_4[3] = { + {33, 5}, + {13, 6}, + {83, 5}, +}; +static arc arcs_29_5[1] = { + {0, 5}, +}; +static arc arcs_29_6[1] = { + {83, 7}, +}; +static arc arcs_29_7[1] = { + {15, 5}, +}; +static state states_29[8] = { + {1, arcs_29_0}, + {3, arcs_29_1}, + {4, arcs_29_2}, + {1, arcs_29_3}, + {3, arcs_29_4}, + {1, arcs_29_5}, + {1, arcs_29_6}, + {1, arcs_29_7}, +}; +static arc arcs_30_0[1] = { + {23, 1}, +}; +static arc arcs_30_1[2] = { + {85, 2}, {0, 1}, }; -static state states_26[2] = { - {2, arcs_26_0}, - {1, arcs_26_1}, -}; -static arc arcs_27_0[1] = { - {77, 1}, -}; -static arc arcs_27_1[1] = { - {78, 2}, -}; -static arc arcs_27_2[1] = { - {0, 2}, -}; -static state states_27[3] = { - {1, arcs_27_0}, - {1, arcs_27_1}, - {1, arcs_27_2}, -}; -static arc arcs_28_0[1] = { - {74, 1}, -}; -static arc arcs_28_1[3] = { - {79, 2}, - {80, 2}, - {12, 3}, -}; -static arc arcs_28_2[4] = { - {79, 2}, - {80, 2}, - {12, 3}, - {77, 4}, -}; -static arc arcs_28_3[1] = { - {77, 4}, -}; -static arc arcs_28_4[3] = { - {31, 5}, - {13, 6}, - {81, 5}, -}; -static arc arcs_28_5[1] = { - {0, 5}, -}; -static arc arcs_28_6[1] = { - {81, 7}, -}; -static arc arcs_28_7[1] = { - {15, 5}, -}; -static state states_28[8] = { - {1, arcs_28_0}, - {3, arcs_28_1}, - {4, arcs_28_2}, - {1, arcs_28_3}, - {3, arcs_28_4}, - {1, arcs_28_5}, - {1, arcs_28_6}, - {1, arcs_28_7}, -}; -static arc arcs_29_0[1] = { - {21, 1}, -}; -static arc arcs_29_1[2] = { - {83, 2}, - {0, 1}, -}; -static arc arcs_29_2[1] = { - {21, 3}, -}; -static arc arcs_29_3[1] = { - {0, 3}, -}; -static state states_29[4] = { - {1, arcs_29_0}, - {2, arcs_29_1}, - {1, arcs_29_2}, - {1, arcs_29_3}, -}; -static arc arcs_30_0[1] = { - {12, 1}, -}; -static arc arcs_30_1[2] = { - {83, 2}, - {0, 1}, -}; static arc arcs_30_2[1] = { - {21, 3}, + {23, 3}, }; static arc arcs_30_3[1] = { {0, 3}, @@ -710,37 +706,45 @@ {1, arcs_30_3}, }; static arc arcs_31_0[1] = { - {82, 1}, + {12, 1}, }; static arc arcs_31_1[2] = { - {30, 2}, + {85, 2}, {0, 1}, }; -static arc arcs_31_2[2] = { - {82, 1}, - {0, 2}, -}; -static state states_31[3] = { +static arc arcs_31_2[1] = { + {23, 3}, +}; +static arc arcs_31_3[1] = { + {0, 3}, +}; +static state states_31[4] = { {1, arcs_31_0}, {2, arcs_31_1}, - {2, arcs_31_2}, + {1, arcs_31_2}, + {1, arcs_31_3}, }; static arc arcs_32_0[1] = { {84, 1}, }; static arc arcs_32_1[2] = { - {30, 0}, + {32, 2}, {0, 1}, }; -static state states_32[2] = { +static arc arcs_32_2[2] = { + {84, 1}, + {0, 2}, +}; +static state states_32[3] = { {1, arcs_32_0}, {2, arcs_32_1}, + {2, arcs_32_2}, }; static arc arcs_33_0[1] = { - {21, 1}, + {86, 1}, }; static arc arcs_33_1[2] = { - {79, 0}, + {32, 0}, {0, 1}, }; static state states_33[2] = { @@ -748,28 +752,24 @@ {2, arcs_33_1}, }; static arc arcs_34_0[1] = { - {85, 1}, -}; -static arc arcs_34_1[1] = { - {21, 2}, -}; -static arc arcs_34_2[2] = { - {30, 1}, - {0, 2}, -}; -static state states_34[3] = { + {23, 1}, +}; +static arc arcs_34_1[2] = { + {81, 0}, + {0, 1}, +}; +static state states_34[2] = { {1, arcs_34_0}, - {1, arcs_34_1}, - {2, arcs_34_2}, + {2, arcs_34_1}, }; static arc arcs_35_0[1] = { - {86, 1}, + {87, 1}, }; static arc arcs_35_1[1] = { - {21, 2}, + {23, 2}, }; static arc arcs_35_2[2] = { - {30, 1}, + {32, 1}, {0, 2}, }; static state states_35[3] = { @@ -778,432 +778,438 @@ {2, arcs_35_2}, }; static arc arcs_36_0[1] = { - {87, 1}, + {88, 1}, }; static arc arcs_36_1[1] = { - {24, 2}, + {23, 2}, }; static arc arcs_36_2[2] = { - {30, 3}, + {32, 1}, {0, 2}, }; -static arc arcs_36_3[1] = { - {24, 4}, -}; -static arc arcs_36_4[1] = { - {0, 4}, -}; -static state states_36[5] = { +static state states_36[3] = { {1, arcs_36_0}, {1, arcs_36_1}, {2, arcs_36_2}, - {1, arcs_36_3}, - {1, arcs_36_4}, -}; -static arc arcs_37_0[8] = { - {88, 1}, +}; +static arc arcs_37_0[1] = { {89, 1}, +}; +static arc arcs_37_1[1] = { + {26, 2}, +}; +static arc arcs_37_2[2] = { + {32, 3}, + {0, 2}, +}; +static arc arcs_37_3[1] = { + {26, 4}, +}; +static arc arcs_37_4[1] = { + {0, 4}, +}; +static state states_37[5] = { + {1, arcs_37_0}, + {1, arcs_37_1}, + {2, arcs_37_2}, + {1, arcs_37_3}, + {1, arcs_37_4}, +}; +static arc arcs_38_0[9] = { {90, 1}, {91, 1}, {92, 1}, + {93, 1}, + {94, 1}, {19, 1}, {18, 1}, {17, 1}, -}; -static arc arcs_37_1[1] = { + {95, 1}, +}; +static arc arcs_38_1[1] = { {0, 1}, }; -static state states_37[2] = { - {8, arcs_37_0}, - {1, arcs_37_1}, -}; -static arc arcs_38_0[1] = { - {93, 1}, -}; -static arc arcs_38_1[1] = { - {24, 2}, -}; -static arc arcs_38_2[1] = { - {25, 3}, -}; -static arc arcs_38_3[1] = { - {26, 4}, -}; -static arc arcs_38_4[3] = { - {94, 1}, - {95, 5}, +static state states_38[2] = { + {9, arcs_38_0}, + {1, arcs_38_1}, +}; +static arc arcs_39_0[1] = { + {21, 1}, +}; +static arc arcs_39_1[3] = { + {19, 2}, + {94, 2}, + {92, 2}, +}; +static arc arcs_39_2[1] = { + {0, 2}, +}; +static state states_39[3] = { + {1, arcs_39_0}, + {3, arcs_39_1}, + {1, arcs_39_2}, +}; +static arc arcs_40_0[1] = { + {96, 1}, +}; +static arc arcs_40_1[1] = { + {26, 2}, +}; +static arc arcs_40_2[1] = { + {27, 3}, +}; +static arc arcs_40_3[1] = { + {28, 4}, +}; +static arc arcs_40_4[3] = { + {97, 1}, + {98, 5}, {0, 4}, }; -static arc arcs_38_5[1] = { - {25, 6}, -}; -static arc arcs_38_6[1] = { - {26, 7}, -}; -static arc arcs_38_7[1] = { +static arc arcs_40_5[1] = { + {27, 6}, +}; +static arc arcs_40_6[1] = { + {28, 7}, +}; +static arc arcs_40_7[1] = { {0, 7}, }; -static state states_38[8] = { - {1, arcs_38_0}, - {1, arcs_38_1}, - {1, arcs_38_2}, - {1, arcs_38_3}, - {3, arcs_38_4}, - {1, arcs_38_5}, - {1, arcs_38_6}, - {1, arcs_38_7}, -}; -static arc arcs_39_0[1] = { - {96, 1}, -}; -static arc arcs_39_1[1] = { - {24, 2}, -}; -static arc arcs_39_2[1] = { - {25, 3}, -}; -static arc arcs_39_3[1] = { - {26, 4}, -}; -static arc arcs_39_4[2] = { - {95, 5}, - {0, 4}, -}; -static arc arcs_39_5[1] = { - {25, 6}, -}; -static arc arcs_39_6[1] = { - {26, 7}, -}; -static arc arcs_39_7[1] = { - {0, 7}, -}; -static state states_39[8] = { - {1, arcs_39_0}, - {1, arcs_39_1}, - {1, arcs_39_2}, - {1, arcs_39_3}, - {2, arcs_39_4}, - {1, arcs_39_5}, - {1, arcs_39_6}, - {1, arcs_39_7}, -}; -static arc arcs_40_0[1] = { - {97, 1}, -}; -static arc arcs_40_1[1] = { - {63, 2}, -}; -static arc arcs_40_2[1] = { - {98, 3}, -}; -static arc arcs_40_3[1] = { - {9, 4}, -}; -static arc arcs_40_4[1] = { - {25, 5}, -}; -static arc arcs_40_5[1] = { - {26, 6}, -}; -static arc arcs_40_6[2] = { - {95, 7}, - {0, 6}, -}; -static arc arcs_40_7[1] = { - {25, 8}, -}; -static arc arcs_40_8[1] = { - {26, 9}, -}; -static arc arcs_40_9[1] = { - {0, 9}, -}; -static state states_40[10] = { +static state states_40[8] = { {1, arcs_40_0}, {1, arcs_40_1}, {1, arcs_40_2}, {1, arcs_40_3}, - {1, arcs_40_4}, + {3, arcs_40_4}, {1, arcs_40_5}, - {2, arcs_40_6}, + {1, arcs_40_6}, {1, arcs_40_7}, - {1, arcs_40_8}, - {1, arcs_40_9}, }; static arc arcs_41_0[1] = { {99, 1}, }; static arc arcs_41_1[1] = { - {25, 2}, + {26, 2}, }; static arc arcs_41_2[1] = { - {26, 3}, -}; -static arc arcs_41_3[2] = { - {100, 4}, - {101, 5}, -}; -static arc arcs_41_4[1] = { - {25, 6}, + {27, 3}, +}; +static arc arcs_41_3[1] = { + {28, 4}, +}; +static arc arcs_41_4[2] = { + {98, 5}, + {0, 4}, }; static arc arcs_41_5[1] = { - {25, 7}, + {27, 6}, }; static arc arcs_41_6[1] = { - {26, 8}, + {28, 7}, }; static arc arcs_41_7[1] = { - {26, 9}, -}; -static arc arcs_41_8[4] = { - {100, 4}, - {95, 10}, - {101, 5}, - {0, 8}, -}; -static arc arcs_41_9[1] = { - {0, 9}, -}; -static arc arcs_41_10[1] = { - {25, 11}, -}; -static arc arcs_41_11[1] = { - {26, 12}, -}; -static arc arcs_41_12[2] = { - {101, 5}, - {0, 12}, -}; -static state states_41[13] = { + {0, 7}, +}; +static state states_41[8] = { {1, arcs_41_0}, {1, arcs_41_1}, {1, arcs_41_2}, - {2, arcs_41_3}, - {1, arcs_41_4}, + {1, arcs_41_3}, + {2, arcs_41_4}, {1, arcs_41_5}, {1, arcs_41_6}, {1, arcs_41_7}, - {4, arcs_41_8}, - {1, arcs_41_9}, - {1, arcs_41_10}, - {1, arcs_41_11}, - {2, arcs_41_12}, }; static arc arcs_42_0[1] = { - {102, 1}, + {100, 1}, }; static arc arcs_42_1[1] = { - {103, 2}, -}; -static arc arcs_42_2[2] = { - {30, 1}, - {25, 3}, + {65, 2}, +}; +static arc arcs_42_2[1] = { + {101, 3}, }; static arc arcs_42_3[1] = { - {26, 4}, + {9, 4}, }; static arc arcs_42_4[1] = { - {0, 4}, -}; -static state states_42[5] = { + {27, 5}, +}; +static arc arcs_42_5[1] = { + {28, 6}, +}; +static arc arcs_42_6[2] = { + {98, 7}, + {0, 6}, +}; +static arc arcs_42_7[1] = { + {27, 8}, +}; +static arc arcs_42_8[1] = { + {28, 9}, +}; +static arc arcs_42_9[1] = { + {0, 9}, +}; +static state states_42[10] = { {1, arcs_42_0}, {1, arcs_42_1}, - {2, arcs_42_2}, + {1, arcs_42_2}, {1, arcs_42_3}, {1, arcs_42_4}, + {1, arcs_42_5}, + {2, arcs_42_6}, + {1, arcs_42_7}, + {1, arcs_42_8}, + {1, arcs_42_9}, }; static arc arcs_43_0[1] = { - {24, 1}, -}; -static arc arcs_43_1[2] = { - {83, 2}, - {0, 1}, + {102, 1}, +}; +static arc arcs_43_1[1] = { + {27, 2}, }; static arc arcs_43_2[1] = { - {104, 3}, -}; -static arc arcs_43_3[1] = { - {0, 3}, -}; -static state states_43[4] = { + {28, 3}, +}; +static arc arcs_43_3[2] = { + {103, 4}, + {104, 5}, +}; +static arc arcs_43_4[1] = { + {27, 6}, +}; +static arc arcs_43_5[1] = { + {27, 7}, +}; +static arc arcs_43_6[1] = { + {28, 8}, +}; +static arc arcs_43_7[1] = { + {28, 9}, +}; +static arc arcs_43_8[4] = { + {103, 4}, + {98, 10}, + {104, 5}, + {0, 8}, +}; +static arc arcs_43_9[1] = { + {0, 9}, +}; +static arc arcs_43_10[1] = { + {27, 11}, +}; +static arc arcs_43_11[1] = { + {28, 12}, +}; +static arc arcs_43_12[2] = { + {104, 5}, + {0, 12}, +}; +static state states_43[13] = { {1, arcs_43_0}, - {2, arcs_43_1}, + {1, arcs_43_1}, {1, arcs_43_2}, - {1, arcs_43_3}, + {2, arcs_43_3}, + {1, arcs_43_4}, + {1, arcs_43_5}, + {1, arcs_43_6}, + {1, arcs_43_7}, + {4, arcs_43_8}, + {1, arcs_43_9}, + {1, arcs_43_10}, + {1, arcs_43_11}, + {2, arcs_43_12}, }; static arc arcs_44_0[1] = { {105, 1}, }; -static arc arcs_44_1[2] = { - {24, 2}, - {0, 1}, +static arc arcs_44_1[1] = { + {106, 2}, }; static arc arcs_44_2[2] = { - {83, 3}, - {0, 2}, + {32, 1}, + {27, 3}, }; static arc arcs_44_3[1] = { - {21, 4}, + {28, 4}, }; static arc arcs_44_4[1] = { {0, 4}, }; static state states_44[5] = { {1, arcs_44_0}, - {2, arcs_44_1}, + {1, arcs_44_1}, {2, arcs_44_2}, {1, arcs_44_3}, {1, arcs_44_4}, }; -static arc arcs_45_0[2] = { +static arc arcs_45_0[1] = { + {26, 1}, +}; +static arc arcs_45_1[2] = { + {85, 2}, + {0, 1}, +}; +static arc arcs_45_2[1] = { + {107, 3}, +}; +static arc arcs_45_3[1] = { + {0, 3}, +}; +static state states_45[4] = { + {1, arcs_45_0}, + {2, arcs_45_1}, + {1, arcs_45_2}, + {1, arcs_45_3}, +}; +static arc arcs_46_0[1] = { + {108, 1}, +}; +static arc arcs_46_1[2] = { + {26, 2}, + {0, 1}, +}; +static arc arcs_46_2[2] = { + {85, 3}, + {0, 2}, +}; +static arc arcs_46_3[1] = { + {23, 4}, +}; +static arc arcs_46_4[1] = { + {0, 4}, +}; +static state states_46[5] = { + {1, arcs_46_0}, + {2, arcs_46_1}, + {2, arcs_46_2}, + {1, arcs_46_3}, + {1, arcs_46_4}, +}; +static arc arcs_47_0[2] = { {3, 1}, {2, 2}, }; -static arc arcs_45_1[1] = { - {0, 1}, -}; -static arc arcs_45_2[1] = { - {106, 3}, -}; -static arc arcs_45_3[1] = { - {6, 4}, -}; -static arc arcs_45_4[2] = { - {6, 4}, - {107, 1}, -}; -static state states_45[5] = { - {2, arcs_45_0}, - {1, arcs_45_1}, - {1, arcs_45_2}, - {1, arcs_45_3}, - {2, arcs_45_4}, -}; -static arc arcs_46_0[2] = { - {108, 1}, - {109, 2}, -}; -static arc arcs_46_1[2] = { - {93, 3}, - {0, 1}, -}; -static arc arcs_46_2[1] = { - {0, 2}, -}; -static arc arcs_46_3[1] = { - {108, 4}, -}; -static arc arcs_46_4[1] = { - {95, 5}, -}; -static arc arcs_46_5[1] = { - {24, 2}, -}; -static state states_46[6] = { - {2, arcs_46_0}, - {2, arcs_46_1}, - {1, arcs_46_2}, - {1, arcs_46_3}, - {1, arcs_46_4}, - {1, arcs_46_5}, -}; -static arc arcs_47_0[2] = { - {108, 1}, - {111, 1}, -}; static arc arcs_47_1[1] = { {0, 1}, }; -static state states_47[2] = { +static arc arcs_47_2[1] = { + {109, 3}, +}; +static arc arcs_47_3[1] = { + {6, 4}, +}; +static arc arcs_47_4[2] = { + {6, 4}, + {110, 1}, +}; +static state states_47[5] = { {2, arcs_47_0}, {1, arcs_47_1}, -}; -static arc arcs_48_0[1] = { - {112, 1}, + {1, arcs_47_2}, + {1, arcs_47_3}, + {2, arcs_47_4}, +}; +static arc arcs_48_0[2] = { + {111, 1}, + {112, 2}, }; static arc arcs_48_1[2] = { - {33, 2}, - {25, 3}, + {96, 3}, + {0, 1}, }; static arc arcs_48_2[1] = { - {25, 3}, + {0, 2}, }; static arc arcs_48_3[1] = { - {24, 4}, + {111, 4}, }; static arc arcs_48_4[1] = { - {0, 4}, -}; -static state states_48[5] = { - {1, arcs_48_0}, + {98, 5}, +}; +static arc arcs_48_5[1] = { + {26, 2}, +}; +static state states_48[6] = { + {2, arcs_48_0}, {2, arcs_48_1}, {1, arcs_48_2}, {1, arcs_48_3}, {1, arcs_48_4}, -}; -static arc arcs_49_0[1] = { - {112, 1}, -}; -static arc arcs_49_1[2] = { - {33, 2}, - {25, 3}, -}; -static arc arcs_49_2[1] = { - {25, 3}, -}; -static arc arcs_49_3[1] = { - {110, 4}, -}; -static arc arcs_49_4[1] = { + {1, arcs_48_5}, +}; +static arc arcs_49_0[2] = { + {111, 1}, + {114, 1}, +}; +static arc arcs_49_1[1] = { + {0, 1}, +}; +static state states_49[2] = { + {2, arcs_49_0}, + {1, arcs_49_1}, +}; +static arc arcs_50_0[1] = { + {115, 1}, +}; +static arc arcs_50_1[2] = { + {35, 2}, + {27, 3}, +}; +static arc arcs_50_2[1] = { + {27, 3}, +}; +static arc arcs_50_3[1] = { + {26, 4}, +}; +static arc arcs_50_4[1] = { {0, 4}, }; -static state states_49[5] = { - {1, arcs_49_0}, - {2, arcs_49_1}, - {1, arcs_49_2}, - {1, arcs_49_3}, - {1, arcs_49_4}, -}; -static arc arcs_50_0[1] = { - {113, 1}, -}; -static arc arcs_50_1[2] = { - {114, 0}, - {0, 1}, -}; -static state states_50[2] = { +static state states_50[5] = { {1, arcs_50_0}, {2, arcs_50_1}, + {1, arcs_50_2}, + {1, arcs_50_3}, + {1, arcs_50_4}, }; static arc arcs_51_0[1] = { {115, 1}, }; static arc arcs_51_1[2] = { - {116, 0}, - {0, 1}, -}; -static state states_51[2] = { + {35, 2}, + {27, 3}, +}; +static arc arcs_51_2[1] = { + {27, 3}, +}; +static arc arcs_51_3[1] = { + {113, 4}, +}; +static arc arcs_51_4[1] = { + {0, 4}, +}; +static state states_51[5] = { {1, arcs_51_0}, {2, arcs_51_1}, -}; -static arc arcs_52_0[2] = { - {117, 1}, - {118, 2}, -}; -static arc arcs_52_1[1] = { - {115, 2}, -}; -static arc arcs_52_2[1] = { - {0, 2}, -}; -static state states_52[3] = { - {2, arcs_52_0}, - {1, arcs_52_1}, - {1, arcs_52_2}, + {1, arcs_51_2}, + {1, arcs_51_3}, + {1, arcs_51_4}, +}; +static arc arcs_52_0[1] = { + {116, 1}, +}; +static arc arcs_52_1[2] = { + {117, 0}, + {0, 1}, +}; +static state states_52[2] = { + {1, arcs_52_0}, + {2, arcs_52_1}, }; static arc arcs_53_0[1] = { - {104, 1}, + {118, 1}, }; static arc arcs_53_1[2] = { {119, 0}, @@ -1213,75 +1219,79 @@ {1, arcs_53_0}, {2, arcs_53_1}, }; -static arc arcs_54_0[10] = { +static arc arcs_54_0[2] = { {120, 1}, - {121, 1}, - {122, 1}, + {121, 2}, +}; +static arc arcs_54_1[1] = { + {118, 2}, +}; +static arc arcs_54_2[1] = { + {0, 2}, +}; +static state states_54[3] = { + {2, arcs_54_0}, + {1, arcs_54_1}, + {1, arcs_54_2}, +}; +static arc arcs_55_0[1] = { + {107, 1}, +}; +static arc arcs_55_1[2] = { + {122, 0}, + {0, 1}, +}; +static state states_55[2] = { + {1, arcs_55_0}, + {2, arcs_55_1}, +}; +static arc arcs_56_0[10] = { {123, 1}, {124, 1}, {125, 1}, {126, 1}, - {98, 1}, - {117, 2}, - {127, 3}, -}; -static arc arcs_54_1[1] = { + {127, 1}, + {128, 1}, + {129, 1}, + {101, 1}, + {120, 2}, + {130, 3}, +}; +static arc arcs_56_1[1] = { {0, 1}, }; -static arc arcs_54_2[1] = { - {98, 1}, -}; -static arc arcs_54_3[2] = { - {117, 1}, +static arc arcs_56_2[1] = { + {101, 1}, +}; +static arc arcs_56_3[2] = { + {120, 1}, {0, 3}, }; -static state states_54[4] = { - {10, arcs_54_0}, - {1, arcs_54_1}, - {1, arcs_54_2}, - {2, arcs_54_3}, -}; -static arc arcs_55_0[1] = { - {31, 1}, -}; -static arc arcs_55_1[1] = { - {104, 2}, -}; -static arc arcs_55_2[1] = { +static state states_56[4] = { + {10, arcs_56_0}, + {1, arcs_56_1}, + {1, arcs_56_2}, + {2, arcs_56_3}, +}; +static arc arcs_57_0[1] = { + {33, 1}, +}; +static arc arcs_57_1[1] = { + {107, 2}, +}; +static arc arcs_57_2[1] = { {0, 2}, }; -static state states_55[3] = { - {1, arcs_55_0}, - {1, arcs_55_1}, - {1, arcs_55_2}, -}; -static arc arcs_56_0[1] = { - {128, 1}, -}; -static arc arcs_56_1[2] = { - {129, 0}, - {0, 1}, -}; -static state states_56[2] = { - {1, arcs_56_0}, - {2, arcs_56_1}, -}; -static arc arcs_57_0[1] = { - {130, 1}, -}; -static arc arcs_57_1[2] = { - {131, 0}, - {0, 1}, -}; -static state states_57[2] = { +static state states_57[3] = { {1, arcs_57_0}, - {2, arcs_57_1}, + {1, arcs_57_1}, + {1, arcs_57_2}, }; static arc arcs_58_0[1] = { - {132, 1}, + {131, 1}, }; static arc arcs_58_1[2] = { - {133, 0}, + {132, 0}, {0, 1}, }; static state states_58[2] = { @@ -1289,404 +1299,316 @@ {2, arcs_58_1}, }; static arc arcs_59_0[1] = { - {134, 1}, -}; -static arc arcs_59_1[3] = { - {135, 0}, + {133, 1}, +}; +static arc arcs_59_1[2] = { + {134, 0}, + {0, 1}, +}; +static state states_59[2] = { + {1, arcs_59_0}, + {2, arcs_59_1}, +}; +static arc arcs_60_0[1] = { + {135, 1}, +}; +static arc arcs_60_1[2] = { {136, 0}, {0, 1}, }; -static state states_59[2] = { - {1, arcs_59_0}, - {3, arcs_59_1}, -}; -static arc arcs_60_0[1] = { +static state states_60[2] = { + {1, arcs_60_0}, + {2, arcs_60_1}, +}; +static arc arcs_61_0[1] = { {137, 1}, }; -static arc arcs_60_1[3] = { +static arc arcs_61_1[3] = { {138, 0}, {139, 0}, {0, 1}, }; -static state states_60[2] = { - {1, arcs_60_0}, - {3, arcs_60_1}, -}; -static arc arcs_61_0[1] = { +static state states_61[2] = { + {1, arcs_61_0}, + {3, arcs_61_1}, +}; +static arc arcs_62_0[1] = { {140, 1}, }; -static arc arcs_61_1[6] = { - {31, 0}, - {11, 0}, +static arc arcs_62_1[3] = { {141, 0}, {142, 0}, - {143, 0}, {0, 1}, }; -static state states_61[2] = { - {1, arcs_61_0}, - {6, arcs_61_1}, -}; -static arc arcs_62_0[4] = { - {138, 1}, - {139, 1}, - {144, 1}, - {145, 2}, -}; -static arc arcs_62_1[1] = { - {140, 2}, -}; -static arc arcs_62_2[1] = { +static state states_62[2] = { + {1, arcs_62_0}, + {3, arcs_62_1}, +}; +static arc arcs_63_0[1] = { + {143, 1}, +}; +static arc arcs_63_1[6] = { + {33, 0}, + {11, 0}, + {144, 0}, + {145, 0}, + {146, 0}, + {0, 1}, +}; +static state states_63[2] = { + {1, arcs_63_0}, + {6, arcs_63_1}, +}; +static arc arcs_64_0[4] = { + {141, 1}, + {142, 1}, + {147, 1}, + {148, 2}, +}; +static arc arcs_64_1[1] = { + {143, 2}, +}; +static arc arcs_64_2[1] = { {0, 2}, }; -static state states_62[3] = { - {4, arcs_62_0}, - {1, arcs_62_1}, - {1, arcs_62_2}, -}; -static arc arcs_63_0[1] = { - {146, 1}, -}; -static arc arcs_63_1[3] = { - {147, 1}, +static state states_64[3] = { + {4, arcs_64_0}, + {1, arcs_64_1}, + {1, arcs_64_2}, +}; +static arc arcs_65_0[1] = { + {149, 1}, +}; +static arc arcs_65_1[2] = { + {34, 2}, + {0, 1}, +}; +static arc arcs_65_2[1] = { + {143, 3}, +}; +static arc arcs_65_3[1] = { + {0, 3}, +}; +static state states_65[4] = { + {1, arcs_65_0}, + {2, arcs_65_1}, + {1, arcs_65_2}, + {1, arcs_65_3}, +}; +static arc arcs_66_0[2] = { + {150, 1}, + {151, 2}, +}; +static arc arcs_66_1[1] = { + {151, 2}, +}; +static arc arcs_66_2[2] = { + {152, 2}, + {0, 2}, +}; +static state states_66[3] = { + {2, arcs_66_0}, + {1, arcs_66_1}, + {2, arcs_66_2}, +}; +static arc arcs_67_0[10] = { + {13, 1}, + {154, 2}, + {156, 3}, + {23, 4}, + {159, 4}, + {160, 5}, + {82, 4}, + {161, 4}, + {162, 4}, + {163, 4}, +}; +static arc arcs_67_1[3] = { + {49, 6}, + {153, 6}, + {15, 4}, +}; +static arc arcs_67_2[2] = { + {153, 7}, + {155, 4}, +}; +static arc arcs_67_3[2] = { + {157, 8}, + {158, 4}, +}; +static arc arcs_67_4[1] = { + {0, 4}, +}; +static arc arcs_67_5[2] = { + {160, 5}, + {0, 5}, +}; +static arc arcs_67_6[1] = { + {15, 4}, +}; +static arc arcs_67_7[1] = { + {155, 4}, +}; +static arc arcs_67_8[1] = { + {158, 4}, +}; +static state states_67[9] = { + {10, arcs_67_0}, + {3, arcs_67_1}, + {2, arcs_67_2}, + {2, arcs_67_3}, + {1, arcs_67_4}, + {2, arcs_67_5}, + {1, arcs_67_6}, + {1, arcs_67_7}, + {1, arcs_67_8}, +}; +static arc arcs_68_0[2] = { + {26, 1}, + {50, 1}, +}; +static arc arcs_68_1[3] = { + {164, 2}, + {32, 3}, + {0, 1}, +}; +static arc arcs_68_2[1] = { + {0, 2}, +}; +static arc arcs_68_3[3] = { + {26, 4}, + {50, 4}, + {0, 3}, +}; +static arc arcs_68_4[2] = { + {32, 3}, + {0, 4}, +}; +static state states_68[5] = { + {2, arcs_68_0}, + {3, arcs_68_1}, + {1, arcs_68_2}, + {3, arcs_68_3}, + {2, arcs_68_4}, +}; +static arc arcs_69_0[3] = { + {13, 1}, + {154, 2}, + {81, 3}, +}; +static arc arcs_69_1[2] = { + {14, 4}, + {15, 5}, +}; +static arc arcs_69_2[1] = { + {165, 6}, +}; +static arc arcs_69_3[1] = { + {23, 5}, +}; +static arc arcs_69_4[1] = { + {15, 5}, +}; +static arc arcs_69_5[1] = { + {0, 5}, +}; +static arc arcs_69_6[1] = { + {155, 5}, +}; +static state states_69[7] = { + {3, arcs_69_0}, + {2, arcs_69_1}, + {1, arcs_69_2}, + {1, arcs_69_3}, + {1, arcs_69_4}, + {1, arcs_69_5}, + {1, arcs_69_6}, +}; +static arc arcs_70_0[1] = { + {166, 1}, +}; +static arc arcs_70_1[2] = { {32, 2}, {0, 1}, }; -static arc arcs_63_2[1] = { - {140, 3}, -}; -static arc arcs_63_3[1] = { +static arc arcs_70_2[2] = { + {166, 1}, + {0, 2}, +}; +static state states_70[3] = { + {1, arcs_70_0}, + {2, arcs_70_1}, + {2, arcs_70_2}, +}; +static arc arcs_71_0[2] = { + {26, 1}, + {27, 2}, +}; +static arc arcs_71_1[2] = { + {27, 2}, + {0, 1}, +}; +static arc arcs_71_2[3] = { + {26, 3}, + {167, 4}, + {0, 2}, +}; +static arc arcs_71_3[2] = { + {167, 4}, {0, 3}, }; -static state states_63[4] = { - {1, arcs_63_0}, - {3, arcs_63_1}, - {1, arcs_63_2}, - {1, arcs_63_3}, -}; -static arc arcs_64_0[10] = { - {13, 1}, - {149, 2}, - {151, 3}, - {21, 4}, - {154, 4}, - {155, 5}, - {80, 4}, - {156, 4}, - {157, 4}, - {158, 4}, -}; -static arc arcs_64_1[3] = { - {47, 6}, - {148, 6}, - {15, 4}, -}; -static arc arcs_64_2[2] = { - {148, 7}, - {150, 4}, -}; -static arc arcs_64_3[2] = { - {152, 8}, - {153, 4}, -}; -static arc arcs_64_4[1] = { +static arc arcs_71_4[1] = { {0, 4}, }; -static arc arcs_64_5[2] = { - {155, 5}, - {0, 5}, -}; -static arc arcs_64_6[1] = { - {15, 4}, -}; -static arc arcs_64_7[1] = { - {150, 4}, -}; -static arc arcs_64_8[1] = { - {153, 4}, -}; -static state states_64[9] = { - {10, arcs_64_0}, - {3, arcs_64_1}, - {2, arcs_64_2}, - {2, arcs_64_3}, - {1, arcs_64_4}, - {2, arcs_64_5}, - {1, arcs_64_6}, - {1, arcs_64_7}, - {1, arcs_64_8}, -}; -static arc arcs_65_0[2] = { - {24, 1}, - {48, 1}, -}; -static arc arcs_65_1[3] = { - {159, 2}, - {30, 3}, +static state states_71[5] = { + {2, arcs_71_0}, + {2, arcs_71_1}, + {3, arcs_71_2}, + {2, arcs_71_3}, + {1, arcs_71_4}, +}; +static arc arcs_72_0[1] = { + {27, 1}, +}; +static arc arcs_72_1[2] = { + {26, 2}, {0, 1}, }; -static arc arcs_65_2[1] = { +static arc arcs_72_2[1] = { {0, 2}, }; -static arc arcs_65_3[3] = { - {24, 4}, - {48, 4}, - {0, 3}, -}; -static arc arcs_65_4[2] = { - {30, 3}, - {0, 4}, -}; -static state states_65[5] = { - {2, arcs_65_0}, - {3, arcs_65_1}, - {1, arcs_65_2}, - {3, arcs_65_3}, - {2, arcs_65_4}, -}; -static arc arcs_66_0[3] = { - {13, 1}, - {149, 2}, - {79, 3}, -}; -static arc arcs_66_1[2] = { - {14, 4}, - {15, 5}, -}; -static arc arcs_66_2[1] = { - {160, 6}, -}; -static arc arcs_66_3[1] = { - {21, 5}, -}; -static arc arcs_66_4[1] = { - {15, 5}, -}; -static arc arcs_66_5[1] = { - {0, 5}, -}; -static arc arcs_66_6[1] = { - {150, 5}, -}; -static state states_66[7] = { - {3, arcs_66_0}, - {2, arcs_66_1}, - {1, arcs_66_2}, - {1, arcs_66_3}, - {1, arcs_66_4}, - {1, arcs_66_5}, - {1, arcs_66_6}, -}; -static arc arcs_67_0[1] = { - {161, 1}, -}; -static arc arcs_67_1[2] = { - {30, 2}, +static state states_72[3] = { + {1, arcs_72_0}, + {2, arcs_72_1}, + {1, arcs_72_2}, +}; +static arc arcs_73_0[2] = { + {107, 1}, + {50, 1}, +}; +static arc arcs_73_1[2] = { + {32, 2}, {0, 1}, }; -static arc arcs_67_2[2] = { - {161, 1}, +static arc arcs_73_2[3] = { + {107, 1}, + {50, 1}, {0, 2}, }; -static state states_67[3] = { - {1, arcs_67_0}, - {2, arcs_67_1}, - {2, arcs_67_2}, -}; -static arc arcs_68_0[2] = { - {24, 1}, - {25, 2}, -}; -static arc arcs_68_1[2] = { - {25, 2}, +static state states_73[3] = { + {2, arcs_73_0}, + {2, arcs_73_1}, + {3, arcs_73_2}, +}; +static arc arcs_74_0[1] = { + {26, 1}, +}; +static arc arcs_74_1[2] = { + {32, 2}, {0, 1}, }; -static arc arcs_68_2[3] = { - {24, 3}, - {162, 4}, - {0, 2}, -}; -static arc arcs_68_3[2] = { - {162, 4}, - {0, 3}, -}; -static arc arcs_68_4[1] = { - {0, 4}, -}; -static state states_68[5] = { - {2, arcs_68_0}, - {2, arcs_68_1}, - {3, arcs_68_2}, - {2, arcs_68_3}, - {1, arcs_68_4}, -}; -static arc arcs_69_0[1] = { - {25, 1}, -}; -static arc arcs_69_1[2] = { - {24, 2}, - {0, 1}, -}; -static arc arcs_69_2[1] = { - {0, 2}, -}; -static state states_69[3] = { - {1, arcs_69_0}, - {2, arcs_69_1}, - {1, arcs_69_2}, -}; -static arc arcs_70_0[2] = { - {104, 1}, - {48, 1}, -}; -static arc arcs_70_1[2] = { - {30, 2}, - {0, 1}, -}; -static arc arcs_70_2[3] = { - {104, 1}, - {48, 1}, - {0, 2}, -}; -static state states_70[3] = { - {2, arcs_70_0}, - {2, arcs_70_1}, - {3, arcs_70_2}, -}; -static arc arcs_71_0[1] = { - {24, 1}, -}; -static arc arcs_71_1[2] = { - {30, 2}, - {0, 1}, -}; -static arc arcs_71_2[2] = { - {24, 1}, - {0, 2}, -}; -static state states_71[3] = { - {1, arcs_71_0}, - {2, arcs_71_1}, - {2, arcs_71_2}, -}; -static arc arcs_72_0[3] = { - {24, 1}, - {32, 2}, - {48, 3}, -}; -static arc arcs_72_1[4] = { - {25, 4}, - {159, 5}, - {30, 6}, - {0, 1}, -}; -static arc arcs_72_2[1] = { - {104, 7}, -}; -static arc arcs_72_3[3] = { - {159, 5}, - {30, 6}, - {0, 3}, -}; -static arc arcs_72_4[1] = { - {24, 7}, -}; -static arc arcs_72_5[1] = { - {0, 5}, -}; -static arc arcs_72_6[3] = { - {24, 8}, - {48, 8}, - {0, 6}, -}; -static arc arcs_72_7[3] = { - {159, 5}, - {30, 9}, - {0, 7}, -}; -static arc arcs_72_8[2] = { - {30, 6}, - {0, 8}, -}; -static arc arcs_72_9[3] = { - {24, 10}, - {32, 11}, - {0, 9}, -}; -static arc arcs_72_10[1] = { - {25, 12}, -}; -static arc arcs_72_11[1] = { - {104, 13}, -}; -static arc arcs_72_12[1] = { - {24, 13}, -}; -static arc arcs_72_13[2] = { - {30, 9}, - {0, 13}, -}; -static state states_72[14] = { - {3, arcs_72_0}, - {4, arcs_72_1}, - {1, arcs_72_2}, - {3, arcs_72_3}, - {1, arcs_72_4}, - {1, arcs_72_5}, - {3, arcs_72_6}, - {3, arcs_72_7}, - {2, arcs_72_8}, - {3, arcs_72_9}, - {1, arcs_72_10}, - {1, arcs_72_11}, - {1, arcs_72_12}, - {2, arcs_72_13}, -}; -static arc arcs_73_0[1] = { - {163, 1}, -}; -static arc arcs_73_1[1] = { - {21, 2}, -}; -static arc arcs_73_2[2] = { - {13, 3}, - {25, 4}, -}; -static arc arcs_73_3[2] = { - {14, 5}, - {15, 6}, -}; -static arc arcs_73_4[1] = { - {26, 7}, -}; -static arc arcs_73_5[1] = { - {15, 6}, -}; -static arc arcs_73_6[1] = { - {25, 4}, -}; -static arc arcs_73_7[1] = { - {0, 7}, -}; -static state states_73[8] = { - {1, arcs_73_0}, - {1, arcs_73_1}, - {2, arcs_73_2}, - {2, arcs_73_3}, - {1, arcs_73_4}, - {1, arcs_73_5}, - {1, arcs_73_6}, - {1, arcs_73_7}, -}; -static arc arcs_74_0[1] = { - {164, 1}, -}; -static arc arcs_74_1[2] = { - {30, 2}, - {0, 1}, -}; static arc arcs_74_2[2] = { - {164, 1}, + {26, 1}, {0, 2}, }; static state states_74[3] = { @@ -1695,344 +1617,477 @@ {2, arcs_74_2}, }; static arc arcs_75_0[3] = { - {24, 1}, + {26, 1}, + {34, 2}, + {50, 3}, +}; +static arc arcs_75_1[4] = { + {27, 4}, + {164, 5}, + {32, 6}, + {0, 1}, +}; +static arc arcs_75_2[1] = { + {107, 7}, +}; +static arc arcs_75_3[3] = { + {164, 5}, + {32, 6}, + {0, 3}, +}; +static arc arcs_75_4[1] = { + {26, 7}, +}; +static arc arcs_75_5[1] = { + {0, 5}, +}; +static arc arcs_75_6[3] = { + {26, 8}, + {50, 8}, + {0, 6}, +}; +static arc arcs_75_7[3] = { + {164, 5}, + {32, 9}, + {0, 7}, +}; +static arc arcs_75_8[2] = { + {32, 6}, + {0, 8}, +}; +static arc arcs_75_9[3] = { + {26, 10}, + {34, 11}, + {0, 9}, +}; +static arc arcs_75_10[1] = { + {27, 12}, +}; +static arc arcs_75_11[1] = { + {107, 13}, +}; +static arc arcs_75_12[1] = { + {26, 13}, +}; +static arc arcs_75_13[2] = { + {32, 9}, + {0, 13}, +}; +static state states_75[14] = { + {3, arcs_75_0}, + {4, arcs_75_1}, + {1, arcs_75_2}, + {3, arcs_75_3}, + {1, arcs_75_4}, + {1, arcs_75_5}, + {3, arcs_75_6}, + {3, arcs_75_7}, + {2, arcs_75_8}, + {3, arcs_75_9}, + {1, arcs_75_10}, + {1, arcs_75_11}, + {1, arcs_75_12}, + {2, arcs_75_13}, +}; +static arc arcs_76_0[1] = { + {168, 1}, +}; +static arc arcs_76_1[1] = { + {23, 2}, +}; +static arc arcs_76_2[2] = { + {13, 3}, + {27, 4}, +}; +static arc arcs_76_3[2] = { + {14, 5}, + {15, 6}, +}; +static arc arcs_76_4[1] = { + {28, 7}, +}; +static arc arcs_76_5[1] = { + {15, 6}, +}; +static arc arcs_76_6[1] = { + {27, 4}, +}; +static arc arcs_76_7[1] = { + {0, 7}, +}; +static state states_76[8] = { + {1, arcs_76_0}, + {1, arcs_76_1}, + {2, arcs_76_2}, + {2, arcs_76_3}, + {1, arcs_76_4}, + {1, arcs_76_5}, + {1, arcs_76_6}, + {1, arcs_76_7}, +}; +static arc arcs_77_0[1] = { + {169, 1}, +}; +static arc arcs_77_1[2] = { {32, 2}, - {48, 3}, -}; -static arc arcs_75_1[3] = { - {159, 3}, - {29, 4}, {0, 1}, }; -static arc arcs_75_2[1] = { - {104, 3}, -}; -static arc arcs_75_3[1] = { - {0, 3}, -}; -static arc arcs_75_4[1] = { - {24, 3}, -}; -static state states_75[5] = { - {3, arcs_75_0}, - {3, arcs_75_1}, - {1, arcs_75_2}, - {1, arcs_75_3}, - {1, arcs_75_4}, -}; -static arc arcs_76_0[2] = { - {159, 1}, - {166, 1}, -}; -static arc arcs_76_1[1] = { +static arc arcs_77_2[2] = { + {169, 1}, + {0, 2}, +}; +static state states_77[3] = { + {1, arcs_77_0}, + {2, arcs_77_1}, + {2, arcs_77_2}, +}; +static arc arcs_78_0[3] = { + {26, 1}, + {34, 2}, + {50, 3}, +}; +static arc arcs_78_1[3] = { + {164, 3}, + {31, 4}, {0, 1}, }; -static state states_76[2] = { - {2, arcs_76_0}, - {1, arcs_76_1}, -}; -static arc arcs_77_0[1] = { - {97, 1}, -}; -static arc arcs_77_1[1] = { - {63, 2}, -}; -static arc arcs_77_2[1] = { - {98, 3}, -}; -static arc arcs_77_3[1] = { - {108, 4}, -}; -static arc arcs_77_4[2] = { - {165, 5}, - {0, 4}, -}; -static arc arcs_77_5[1] = { - {0, 5}, -}; -static state states_77[6] = { - {1, arcs_77_0}, - {1, arcs_77_1}, - {1, arcs_77_2}, - {1, arcs_77_3}, - {2, arcs_77_4}, - {1, arcs_77_5}, -}; -static arc arcs_78_0[1] = { - {93, 1}, -}; -static arc arcs_78_1[1] = { - {110, 2}, -}; -static arc arcs_78_2[2] = { - {165, 3}, - {0, 2}, +static arc arcs_78_2[1] = { + {107, 3}, }; static arc arcs_78_3[1] = { {0, 3}, }; -static state states_78[4] = { - {1, arcs_78_0}, - {1, arcs_78_1}, - {2, arcs_78_2}, +static arc arcs_78_4[1] = { + {26, 3}, +}; +static state states_78[5] = { + {3, arcs_78_0}, + {3, arcs_78_1}, + {1, arcs_78_2}, {1, arcs_78_3}, -}; -static arc arcs_79_0[1] = { - {21, 1}, + {1, arcs_78_4}, +}; +static arc arcs_79_0[2] = { + {164, 1}, + {171, 1}, }; static arc arcs_79_1[1] = { {0, 1}, }; static state states_79[2] = { - {1, arcs_79_0}, + {2, arcs_79_0}, {1, arcs_79_1}, }; static arc arcs_80_0[1] = { - {168, 1}, -}; -static arc arcs_80_1[2] = { - {169, 2}, + {100, 1}, +}; +static arc arcs_80_1[1] = { + {65, 2}, +}; +static arc arcs_80_2[1] = { + {101, 3}, +}; +static arc arcs_80_3[1] = { + {111, 4}, +}; +static arc arcs_80_4[2] = { + {170, 5}, + {0, 4}, +}; +static arc arcs_80_5[1] = { + {0, 5}, +}; +static state states_80[6] = { + {1, arcs_80_0}, + {1, arcs_80_1}, + {1, arcs_80_2}, + {1, arcs_80_3}, + {2, arcs_80_4}, + {1, arcs_80_5}, +}; +static arc arcs_81_0[1] = { + {96, 1}, +}; +static arc arcs_81_1[1] = { + {113, 2}, +}; +static arc arcs_81_2[2] = { + {170, 3}, + {0, 2}, +}; +static arc arcs_81_3[1] = { + {0, 3}, +}; +static state states_81[4] = { + {1, arcs_81_0}, + {1, arcs_81_1}, + {2, arcs_81_2}, + {1, arcs_81_3}, +}; +static arc arcs_82_0[1] = { + {23, 1}, +}; +static arc arcs_82_1[1] = { {0, 1}, }; -static arc arcs_80_2[1] = { +static state states_82[2] = { + {1, arcs_82_0}, + {1, arcs_82_1}, +}; +static arc arcs_83_0[1] = { + {173, 1}, +}; +static arc arcs_83_1[2] = { + {174, 2}, + {0, 1}, +}; +static arc arcs_83_2[1] = { {0, 2}, }; -static state states_80[3] = { - {1, arcs_80_0}, - {2, arcs_80_1}, - {1, arcs_80_2}, -}; -static arc arcs_81_0[2] = { - {74, 1}, +static state states_83[3] = { + {1, arcs_83_0}, + {2, arcs_83_1}, + {1, arcs_83_2}, +}; +static arc arcs_84_0[2] = { + {76, 1}, {9, 2}, }; -static arc arcs_81_1[1] = { - {24, 2}, -}; -static arc arcs_81_2[1] = { +static arc arcs_84_1[1] = { + {26, 2}, +}; +static arc arcs_84_2[1] = { {0, 2}, }; -static state states_81[3] = { - {2, arcs_81_0}, - {1, arcs_81_1}, - {1, arcs_81_2}, -}; -static dfa dfas[82] = { +static state states_84[3] = { + {2, arcs_84_0}, + {1, arcs_84_1}, + {1, arcs_84_2}, +}; +static dfa dfas[85] = { {256, "single_input", 0, 3, states_0, - "\004\050\060\200\000\000\000\100\301\047\341\040\113\000\041\000\000\014\241\174\010\001"}, + "\004\050\340\000\002\000\000\000\005\237\204\003\131\002\010\001\000\140\110\224\017\041"}, {257, "file_input", 0, 2, states_1, - "\204\050\060\200\000\000\000\100\301\047\341\040\113\000\041\000\000\014\241\174\010\001"}, + "\204\050\340\000\002\000\000\000\005\237\204\003\131\002\010\001\000\140\110\224\017\041"}, {258, "eval_input", 0, 3, states_2, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, {259, "decorator", 0, 7, states_3, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {261, "decorated", 0, 3, states_5, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {262, "funcdef", 0, 8, states_6, - "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {263, "parameters", 0, 4, states_7, + {262, "async_funcdef", 0, 3, states_6, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {263, "funcdef", 0, 8, states_7, + "\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {264, "parameters", 0, 4, states_8, "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {264, "typedargslist", 0, 18, states_8, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {265, "tfpdef", 0, 4, states_9, + {265, "typedargslist", 0, 18, states_9, + "\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {266, "tfpdef", 0, 4, states_10, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {267, "varargslist", 0, 18, states_11, + "\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {268, "vfpdef", 0, 2, states_12, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {269, "stmt", 0, 2, states_13, + "\000\050\340\000\002\000\000\000\005\237\204\003\131\002\010\001\000\140\110\224\017\041"}, + {270, "simple_stmt", 0, 4, states_14, + "\000\040\200\000\002\000\000\000\005\237\204\003\000\000\010\001\000\140\110\224\017\040"}, + {271, "small_stmt", 0, 2, states_15, + "\000\040\200\000\002\000\000\000\005\237\204\003\000\000\010\001\000\140\110\224\017\040"}, + {272, "expr_stmt", 0, 6, states_16, + "\000\040\200\000\002\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {273, "testlist_star_expr", 0, 3, states_17, + "\000\040\200\000\002\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {274, "augassign", 0, 2, states_18, + "\000\000\000\000\000\000\370\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {275, "del_stmt", 0, 3, states_19, + "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {276, "pass_stmt", 0, 2, states_20, + "\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {277, "flow_stmt", 0, 2, states_21, + "\000\000\000\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\040"}, + {278, "break_stmt", 0, 2, states_22, + "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"}, + {279, "continue_stmt", 0, 2, states_23, + "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000"}, + {280, "return_stmt", 0, 3, states_24, + "\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000"}, + {281, "yield_stmt", 0, 2, states_25, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040"}, + {282, "raise_stmt", 0, 5, states_26, + "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"}, + {283, "import_stmt", 0, 2, states_27, + "\000\000\000\000\000\000\000\000\000\220\000\000\000\000\000\000\000\000\000\000\000\000"}, + {284, "import_name", 0, 3, states_28, + "\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"}, + {285, "import_from", 0, 8, states_29, + "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000"}, + {286, "import_as_name", 0, 4, states_30, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {287, "dotted_as_name", 0, 4, states_31, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {288, "import_as_names", 0, 3, states_32, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {289, "dotted_as_names", 0, 2, states_33, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {290, "dotted_name", 0, 2, states_34, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {291, "global_stmt", 0, 3, states_35, + "\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000"}, + {292, "nonlocal_stmt", 0, 3, states_36, + "\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000"}, + {293, "assert_stmt", 0, 5, states_37, + "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000"}, + {294, "compound_stmt", 0, 2, states_38, + "\000\010\140\000\000\000\000\000\000\000\000\000\131\002\000\000\000\000\000\000\000\001"}, + {295, "async_stmt", 0, 3, states_39, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {266, "varargslist", 0, 18, states_10, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {267, "vfpdef", 0, 2, states_11, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {268, "stmt", 0, 2, states_12, - "\000\050\060\200\000\000\000\100\301\047\341\040\113\000\041\000\000\014\241\174\010\001"}, - {269, "simple_stmt", 0, 4, states_13, - "\000\040\040\200\000\000\000\100\301\047\341\000\000\000\041\000\000\014\241\174\000\001"}, - {270, "small_stmt", 0, 2, states_14, - "\000\040\040\200\000\000\000\100\301\047\341\000\000\000\041\000\000\014\241\174\000\001"}, - {271, "expr_stmt", 0, 6, states_15, - "\000\040\040\200\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {272, "testlist_star_expr", 0, 3, states_16, - "\000\040\040\200\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {273, "augassign", 0, 2, states_17, - "\000\000\000\000\000\000\376\077\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {274, "del_stmt", 0, 3, states_18, - "\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {275, "pass_stmt", 0, 2, states_19, - "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {276, "flow_stmt", 0, 2, states_20, - "\000\000\000\000\000\000\000\000\300\003\000\000\000\000\000\000\000\000\000\000\000\001"}, - {277, "break_stmt", 0, 2, states_21, - "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {278, "continue_stmt", 0, 2, states_22, - "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {279, "return_stmt", 0, 3, states_23, - "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"}, - {280, "yield_stmt", 0, 2, states_24, + {296, "if_stmt", 0, 8, states_40, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, + {297, "while_stmt", 0, 8, states_41, + "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"}, + {298, "for_stmt", 0, 10, states_42, + "\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + {299, "try_stmt", 0, 13, states_43, + "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, + {300, "with_stmt", 0, 5, states_44, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"}, + {301, "with_item", 0, 4, states_45, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {302, "except_clause", 0, 5, states_46, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000"}, + {303, "suite", 0, 5, states_47, + "\004\040\200\000\002\000\000\000\005\237\204\003\000\000\010\001\000\140\110\224\017\040"}, + {304, "test", 0, 6, states_48, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {305, "test_nocond", 0, 2, states_49, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {306, "lambdef", 0, 5, states_50, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"}, + {307, "lambdef_nocond", 0, 5, states_51, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"}, + {308, "or_test", 0, 2, states_52, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\001\000\140\110\224\017\000"}, + {309, "and_test", 0, 2, states_53, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\001\000\140\110\224\017\000"}, + {310, "not_test", 0, 3, states_54, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\001\000\140\110\224\017\000"}, + {311, "comparison", 0, 2, states_55, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {312, "comp_op", 0, 4, states_56, + "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\371\007\000\000\000\000\000"}, + {313, "star_expr", 0, 3, states_57, + "\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {314, "expr", 0, 2, states_58, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {315, "xor_expr", 0, 2, states_59, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {316, "and_expr", 0, 2, states_60, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {317, "shift_expr", 0, 2, states_61, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {318, "arith_expr", 0, 2, states_62, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {319, "term", 0, 2, states_63, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {320, "factor", 0, 3, states_64, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {321, "power", 0, 4, states_65, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\100\224\017\000"}, + {322, "atom_expr", 0, 3, states_66, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\100\224\017\000"}, + {323, "atom", 0, 9, states_67, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\224\017\000"}, + {324, "testlist_comp", 0, 5, states_68, + "\000\040\200\000\002\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {325, "trailer", 0, 7, states_69, + "\000\040\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\004\000\000"}, + {326, "subscriptlist", 0, 3, states_70, + "\000\040\200\010\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {327, "subscript", 0, 5, states_71, + "\000\040\200\010\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {328, "sliceop", 0, 3, states_72, + "\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {329, "exprlist", 0, 3, states_73, + "\000\040\200\000\002\000\000\000\000\000\004\000\000\000\000\000\000\140\110\224\017\000"}, + {330, "testlist", 0, 3, states_74, + "\000\040\200\000\000\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {331, "dictorsetmaker", 0, 14, states_75, + "\000\040\200\000\006\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {332, "classdef", 0, 8, states_76, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"}, - {281, "raise_stmt", 0, 5, states_25, - "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000"}, - {282, "import_stmt", 0, 2, states_26, - "\000\000\000\000\000\000\000\000\000\044\000\000\000\000\000\000\000\000\000\000\000\000"}, - {283, "import_name", 0, 3, states_27, - "\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, - {284, "import_from", 0, 8, states_28, - "\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000"}, - {285, "import_as_name", 0, 4, states_29, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {286, "dotted_as_name", 0, 4, states_30, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {287, "import_as_names", 0, 3, states_31, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {288, "dotted_as_names", 0, 2, states_32, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {289, "dotted_name", 0, 2, states_33, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {290, "global_stmt", 0, 3, states_34, - "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"}, - {291, "nonlocal_stmt", 0, 3, states_35, - "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000"}, - {292, "assert_stmt", 0, 5, states_36, - "\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000"}, - {293, "compound_stmt", 0, 2, states_37, - "\000\010\020\000\000\000\000\000\000\000\000\040\113\000\000\000\000\000\000\000\010\000"}, - {294, "if_stmt", 0, 8, states_38, - "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, - {295, "while_stmt", 0, 8, states_39, + {333, "arglist", 0, 3, states_77, + "\000\040\200\000\006\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {334, "argument", 0, 5, states_78, + "\000\040\200\000\006\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, + {335, "comp_iter", 0, 2, states_79, + "\000\000\000\000\000\000\000\000\000\000\000\000\021\000\000\000\000\000\000\000\000\000"}, + {336, "comp_for", 0, 6, states_80, + "\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + {337, "comp_if", 0, 4, states_81, "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, - {296, "for_stmt", 0, 10, states_40, - "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, - {297, "try_stmt", 0, 13, states_41, - "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"}, - {298, "with_stmt", 0, 5, states_42, - "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, - {299, "with_item", 0, 4, states_43, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {300, "except_clause", 0, 5, states_44, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"}, - {301, "suite", 0, 5, states_45, - "\004\040\040\200\000\000\000\100\301\047\341\000\000\000\041\000\000\014\241\174\000\001"}, - {302, "test", 0, 6, states_46, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {303, "test_nocond", 0, 2, states_47, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {304, "lambdef", 0, 5, states_48, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, - {305, "lambdef_nocond", 0, 5, states_49, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, - {306, "or_test", 0, 2, states_50, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\040\000\000\014\241\174\000\000"}, - {307, "and_test", 0, 2, states_51, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\040\000\000\014\241\174\000\000"}, - {308, "not_test", 0, 3, states_52, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\040\000\000\014\241\174\000\000"}, - {309, "comparison", 0, 2, states_53, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {310, "comp_op", 0, 4, states_54, - "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\040\377\000\000\000\000\000\000"}, - {311, "star_expr", 0, 3, states_55, - "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {312, "expr", 0, 2, states_56, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {313, "xor_expr", 0, 2, states_57, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {314, "and_expr", 0, 2, states_58, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {315, "shift_expr", 0, 2, states_59, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {316, "arith_expr", 0, 2, states_60, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {317, "term", 0, 2, states_61, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {318, "factor", 0, 3, states_62, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {319, "power", 0, 4, states_63, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\240\174\000\000"}, - {320, "atom", 0, 9, states_64, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\240\174\000\000"}, - {321, "testlist_comp", 0, 5, states_65, - "\000\040\040\200\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {322, "trailer", 0, 7, states_66, - "\000\040\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\040\000\000\000"}, - {323, "subscriptlist", 0, 3, states_67, - "\000\040\040\002\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {324, "subscript", 0, 5, states_68, - "\000\040\040\002\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {325, "sliceop", 0, 3, states_69, - "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {326, "exprlist", 0, 3, states_70, - "\000\040\040\200\000\000\000\000\000\000\001\000\000\000\000\000\000\014\241\174\000\000"}, - {327, "testlist", 0, 3, states_71, - "\000\040\040\000\000\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {328, "dictorsetmaker", 0, 14, states_72, - "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {329, "classdef", 0, 8, states_73, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000"}, - {330, "arglist", 0, 3, states_74, - "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {331, "argument", 0, 5, states_75, - "\000\040\040\200\001\000\000\000\000\000\001\000\000\000\041\000\000\014\241\174\000\000"}, - {332, "comp_iter", 0, 2, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"}, - {333, "comp_for", 0, 6, states_77, - "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, - {334, "comp_if", 0, 4, states_78, - "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, - {335, "encoding_decl", 0, 2, states_79, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {336, "yield_expr", 0, 3, states_80, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"}, - {337, "yield_arg", 0, 3, states_81, - "\000\040\040\000\000\000\000\000\000\004\001\000\000\000\041\000\000\014\241\174\000\000"}, -}; -static label labels[170] = { + {338, "encoding_decl", 0, 2, states_82, + "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {339, "yield_expr", 0, 3, states_83, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040"}, + {340, "yield_arg", 0, 3, states_84, + "\000\040\200\000\000\000\000\000\000\020\004\000\000\000\010\001\000\140\110\224\017\000"}, +}; +static label labels[175] = { {0, "EMPTY"}, {256, 0}, {4, 0}, + {270, 0}, + {294, 0}, + {257, 0}, {269, 0}, - {293, 0}, - {257, 0}, - {268, 0}, {0, 0}, {258, 0}, - {327, 0}, + {330, 0}, {259, 0}, {49, 0}, - {289, 0}, + {290, 0}, {7, 0}, - {330, 0}, + {333, 0}, {8, 0}, {260, 0}, {261, 0}, - {329, 0}, + {332, 0}, + {263, 0}, {262, 0}, + {55, 0}, {1, "def"}, {1, 0}, - {263, 0}, + {264, 0}, {51, 0}, - {302, 0}, + {304, 0}, {11, 0}, - {301, 0}, - {264, 0}, + {303, 0}, {265, 0}, + {266, 0}, {22, 0}, {12, 0}, {16, 0}, {35, 0}, - {266, 0}, {267, 0}, - {270, 0}, + {268, 0}, + {271, 0}, {13, 0}, - {271, 0}, - {274, 0}, + {272, 0}, {275, 0}, {276, 0}, - {282, 0}, - {290, 0}, + {277, 0}, + {283, 0}, {291, 0}, {292, 0}, - {272, 0}, + {293, 0}, {273, 0}, - {336, 0}, - {311, 0}, + {274, 0}, + {339, 0}, + {313, 0}, {36, 0}, {37, 0}, {38, 0}, @@ -2047,36 +2102,37 @@ {46, 0}, {48, 0}, {1, "del"}, - {326, 0}, + {329, 0}, {1, "pass"}, - {277, 0}, {278, 0}, {279, 0}, + {280, 0}, + {282, 0}, {281, 0}, - {280, 0}, {1, "break"}, {1, "continue"}, {1, "return"}, {1, "raise"}, {1, "from"}, - {283, 0}, {284, 0}, + {285, 0}, {1, "import"}, - {288, 0}, + {289, 0}, {23, 0}, {52, 0}, + {288, 0}, + {286, 0}, + {1, "as"}, {287, 0}, - {285, 0}, - {1, "as"}, - {286, 0}, {1, "global"}, {1, "nonlocal"}, {1, "assert"}, - {294, 0}, - {295, 0}, {296, 0}, {297, 0}, {298, 0}, + {299, 0}, + {300, 0}, + {295, 0}, {1, "if"}, {1, "elif"}, {1, "else"}, @@ -2084,26 +2140,26 @@ {1, "for"}, {1, "in"}, {1, "try"}, - {300, 0}, + {302, 0}, {1, "finally"}, {1, "with"}, - {299, 0}, - {312, 0}, + {301, 0}, + {314, 0}, {1, "except"}, {5, 0}, {6, 0}, + {308, 0}, {306, 0}, - {304, 0}, - {303, 0}, {305, 0}, + {307, 0}, {1, "lambda"}, - {307, 0}, + {309, 0}, {1, "or"}, - {308, 0}, + {310, 0}, {1, "and"}, {1, "not"}, - {309, 0}, - {310, 0}, + {311, 0}, + {312, 0}, {20, 0}, {21, 0}, {27, 0}, @@ -2112,52 +2168,54 @@ {28, 0}, {28, 0}, {1, "is"}, - {313, 0}, + {315, 0}, {18, 0}, - {314, 0}, + {316, 0}, {32, 0}, - {315, 0}, + {317, 0}, {19, 0}, - {316, 0}, + {318, 0}, {33, 0}, {34, 0}, - {317, 0}, + {319, 0}, {14, 0}, {15, 0}, - {318, 0}, + {320, 0}, {17, 0}, {24, 0}, {47, 0}, {31, 0}, - {319, 0}, - {320, 0}, + {321, 0}, {322, 0}, - {321, 0}, + {54, 0}, + {323, 0}, + {325, 0}, + {324, 0}, {9, 0}, {10, 0}, {25, 0}, - {328, 0}, + {331, 0}, {26, 0}, {2, 0}, {3, 0}, {1, "None"}, {1, "True"}, {1, "False"}, - {333, 0}, - {323, 0}, - {324, 0}, - {325, 0}, + {336, 0}, + {326, 0}, + {327, 0}, + {328, 0}, {1, "class"}, - {331, 0}, - {332, 0}, {334, 0}, {335, 0}, + {337, 0}, + {338, 0}, {1, "yield"}, - {337, 0}, + {340, 0}, }; grammar _PyParser_Grammar = { - 82, + 85, dfas, - {170, labels}, + {175, labels}, 256 }; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -225,2408 +225,2409 @@ 104,95,105,115,100,105,114,92,0,0,0,115,6,0,0,0, 0,2,6,1,12,1,114,46,0,0,0,105,182,1,0,0, 99,3,0,0,0,0,0,0,0,6,0,0,0,17,0,0, - 0,67,0,0,0,115,192,0,0,0,100,1,0,106,0,0, + 0,67,0,0,0,115,193,0,0,0,100,1,0,106,0,0, 124,0,0,116,1,0,124,0,0,131,1,0,131,2,0,125, 3,0,116,2,0,106,3,0,124,3,0,116,2,0,106,4, 0,116,2,0,106,5,0,66,116,2,0,106,6,0,66,124, - 2,0,100,2,0,64,131,3,0,125,4,0,121,60,0,116, + 2,0,100,2,0,64,131,3,0,125,4,0,121,61,0,116, 7,0,106,8,0,124,4,0,100,3,0,131,2,0,143,20, 0,125,5,0,124,5,0,106,9,0,124,1,0,131,1,0, - 1,87,100,4,0,81,88,116,2,0,106,10,0,124,3,0, - 124,0,0,131,2,0,1,87,110,59,0,4,116,11,0,107, - 10,0,114,187,0,1,1,1,121,17,0,116,2,0,106,12, - 0,124,3,0,131,1,0,1,87,110,18,0,4,116,11,0, - 107,10,0,114,179,0,1,1,1,89,110,1,0,88,130,0, - 0,89,110,1,0,88,100,4,0,83,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, - 3,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,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,218,13,95,119,114,105,116,101,95,97,116,111, - 109,105,99,99,0,0,0,115,26,0,0,0,0,5,24,1, - 9,1,33,1,3,3,21,1,19,1,20,1,13,1,3,1, - 17,1,13,1,5,1,114,55,0,0,0,105,2,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, - 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,87,1,0,0,124,1,0,100,1,0,107,9, - 0,114,76,0,116,0,0,106,1,0,100,2,0,116,2,0, - 131,2,0,1,124,2,0,100,1,0,107,9,0,114,58,0, - 100,3,0,125,3,0,116,3,0,124,3,0,131,1,0,130, - 1,0,124,1,0,114,70,0,100,4,0,110,3,0,100,5, - 0,125,2,0,116,4,0,124,0,0,131,1,0,92,2,0, - 125,4,0,125,5,0,124,5,0,106,5,0,100,6,0,131, - 1,0,92,3,0,125,6,0,125,7,0,125,8,0,116,6, - 0,106,7,0,106,8,0,125,9,0,124,9,0,100,1,0, - 107,8,0,114,154,0,116,9,0,100,7,0,131,1,0,130, - 1,0,100,4,0,106,10,0,124,6,0,114,172,0,124,6, - 0,110,3,0,124,8,0,124,7,0,124,9,0,103,3,0, - 131,1,0,125,10,0,124,2,0,100,1,0,107,8,0,114, - 241,0,116,6,0,106,11,0,106,12,0,100,8,0,107,2, - 0,114,229,0,100,4,0,125,2,0,110,12,0,116,6,0, - 106,11,0,106,12,0,125,2,0,116,13,0,124,2,0,131, - 1,0,125,2,0,124,2,0,100,4,0,107,3,0,114,63, - 1,124,2,0,106,14,0,131,0,0,115,42,1,116,15,0, - 100,9,0,106,16,0,124,2,0,131,1,0,131,1,0,130, - 1,0,100,10,0,106,16,0,124,10,0,116,17,0,124,2, - 0,131,3,0,125,10,0,116,18,0,124,4,0,116,19,0, - 124,10,0,116,20,0,100,8,0,25,23,131,3,0,83,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, + 1,87,100,4,0,81,82,88,116,2,0,106,10,0,124,3, + 0,124,0,0,131,2,0,1,87,110,59,0,4,116,11,0, + 107,10,0,114,188,0,1,1,1,121,17,0,116,2,0,106, + 12,0,124,3,0,131,1,0,1,87,110,18,0,4,116,11, + 0,107,10,0,114,180,0,1,1,1,89,110,1,0,88,130, + 0,0,89,110,1,0,88,100,4,0,83,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,3,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,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,13,95,119,114,105,116,101,95,97,116, + 111,109,105,99,99,0,0,0,115,26,0,0,0,0,5,24, + 1,9,1,33,1,3,3,21,1,20,1,20,1,13,1,3, + 1,17,1,13,1,5,1,114,55,0,0,0,105,2,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,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,87,1,0,0,124,1,0,100,1,0,107, + 9,0,114,76,0,116,0,0,106,1,0,100,2,0,116,2, + 0,131,2,0,1,124,2,0,100,1,0,107,9,0,114,58, + 0,100,3,0,125,3,0,116,3,0,124,3,0,131,1,0, + 130,1,0,124,1,0,114,70,0,100,4,0,110,3,0,100, + 5,0,125,2,0,116,4,0,124,0,0,131,1,0,92,2, + 0,125,4,0,125,5,0,124,5,0,106,5,0,100,6,0, + 131,1,0,92,3,0,125,6,0,125,7,0,125,8,0,116, + 6,0,106,7,0,106,8,0,125,9,0,124,9,0,100,1, + 0,107,8,0,114,154,0,116,9,0,100,7,0,131,1,0, + 130,1,0,100,4,0,106,10,0,124,6,0,114,172,0,124, + 6,0,110,3,0,124,8,0,124,7,0,124,9,0,103,3, + 0,131,1,0,125,10,0,124,2,0,100,1,0,107,8,0, + 114,241,0,116,6,0,106,11,0,106,12,0,100,8,0,107, + 2,0,114,229,0,100,4,0,125,2,0,110,12,0,116,6, + 0,106,11,0,106,12,0,125,2,0,116,13,0,124,2,0, + 131,1,0,125,2,0,124,2,0,100,4,0,107,3,0,114, + 63,1,124,2,0,106,14,0,131,0,0,115,42,1,116,15, + 0,100,9,0,106,16,0,124,2,0,131,1,0,131,1,0, + 130,1,0,100,10,0,106,16,0,124,10,0,116,17,0,124, + 2,0,131,3,0,125,10,0,116,18,0,124,4,0,116,19, + 0,124,10,0,116,20,0,100,8,0,25,23,131,3,0,83, + 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,21,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, + 38,0,0,0,114,32,0,0,0,114,7,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,47, + 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,57,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,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,17,99,97,99,104,101,95,102,114,111,109,95,115,111, + 117,114,99,101,241,0,0,0,115,46,0,0,0,0,18,12, + 1,9,1,7,1,12,1,6,1,12,1,18,1,18,1,24, + 1,12,1,12,1,12,1,36,1,12,1,18,1,9,2,12, + 1,12,1,12,1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0, + 106,2,0,100,1,0,107,8,0,114,30,0,116,3,0,100, + 2,0,131,1,0,130,1,0,116,4,0,124,0,0,131,1, + 0,92,2,0,125,1,0,125,2,0,116,4,0,124,1,0, + 131,1,0,92,2,0,125,1,0,125,3,0,124,3,0,116, + 5,0,107,3,0,114,102,0,116,6,0,100,3,0,106,7, + 0,116,5,0,124,0,0,131,2,0,131,1,0,130,1,0, + 124,2,0,106,8,0,100,4,0,131,1,0,125,4,0,124, + 4,0,100,11,0,107,7,0,114,153,0,116,6,0,100,7, + 0,106,7,0,124,2,0,131,1,0,131,1,0,130,1,0, + 110,125,0,124,4,0,100,6,0,107,2,0,114,22,1,124, + 2,0,106,9,0,100,4,0,100,5,0,131,2,0,100,12, + 0,25,125,5,0,124,5,0,106,10,0,116,11,0,131,1, + 0,115,223,0,116,6,0,100,8,0,106,7,0,116,11,0, + 131,1,0,131,1,0,130,1,0,124,5,0,116,12,0,116, + 11,0,131,1,0,100,1,0,133,2,0,25,125,6,0,124, + 6,0,106,13,0,131,0,0,115,22,1,116,6,0,100,9, + 0,106,7,0,124,5,0,131,1,0,131,1,0,130,1,0, + 124,2,0,106,14,0,100,4,0,131,1,0,100,10,0,25, + 125,7,0,116,15,0,124,1,0,124,7,0,116,16,0,100, + 10,0,25,23,131,2,0,83,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,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,21,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,38, - 0,0,0,114,32,0,0,0,114,7,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,47,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,57,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,17,99,97,99,104,101,95,102,114,111,109,95,115,111,117, - 114,99,101,241,0,0,0,115,46,0,0,0,0,18,12,1, - 9,1,7,1,12,1,6,1,12,1,18,1,18,1,24,1, - 12,1,12,1,12,1,36,1,12,1,18,1,9,2,12,1, - 12,1,12,1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0,106, - 2,0,100,1,0,107,8,0,114,30,0,116,3,0,100,2, - 0,131,1,0,130,1,0,116,4,0,124,0,0,131,1,0, - 92,2,0,125,1,0,125,2,0,116,4,0,124,1,0,131, - 1,0,92,2,0,125,1,0,125,3,0,124,3,0,116,5, - 0,107,3,0,114,102,0,116,6,0,100,3,0,106,7,0, - 116,5,0,124,0,0,131,2,0,131,1,0,130,1,0,124, - 2,0,106,8,0,100,4,0,131,1,0,125,4,0,124,4, - 0,100,11,0,107,7,0,114,153,0,116,6,0,100,7,0, - 106,7,0,124,2,0,131,1,0,131,1,0,130,1,0,110, - 125,0,124,4,0,100,6,0,107,2,0,114,22,1,124,2, - 0,106,9,0,100,4,0,100,5,0,131,2,0,100,12,0, - 25,125,5,0,124,5,0,106,10,0,116,11,0,131,1,0, - 115,223,0,116,6,0,100,8,0,106,7,0,116,11,0,131, - 1,0,131,1,0,130,1,0,124,5,0,116,12,0,116,11, - 0,131,1,0,100,1,0,133,2,0,25,125,6,0,124,6, - 0,106,13,0,131,0,0,115,22,1,116,6,0,100,9,0, - 106,7,0,124,5,0,131,1,0,131,1,0,130,1,0,124, - 2,0,106,14,0,100,4,0,131,1,0,100,10,0,25,125, - 7,0,116,15,0,124,1,0,124,7,0,116,16,0,100,10, - 0,25,23,131,2,0,83,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,58,0,0,0,114, - 56,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,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,59,0, - 0,0,62,2,0,0,0,114,56,0,0,0,114,80,0,0, - 0,233,254,255,255,255,41,17,114,7,0,0,0,114,64,0, - 0,0,114,65,0,0,0,114,66,0,0,0,114,38,0,0, - 0,114,73,0,0,0,114,71,0,0,0,114,47,0,0,0, - 218,5,99,111,117,110,116,114,34,0,0,0,114,9,0,0, - 0,114,72,0,0,0,114,31,0,0,0,114,70,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,76,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,57,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, + 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,58,0,0,0, + 114,56,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,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,59, + 0,0,0,62,2,0,0,0,114,56,0,0,0,114,80,0, + 0,0,233,254,255,255,255,41,17,114,7,0,0,0,114,64, + 0,0,0,114,65,0,0,0,114,66,0,0,0,114,38,0, + 0,0,114,73,0,0,0,114,71,0,0,0,114,47,0,0, + 0,218,5,99,111,117,110,116,114,34,0,0,0,114,9,0, + 0,0,114,72,0,0,0,114,31,0,0,0,114,70,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,76,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,57,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,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,17,115,111,117,114,99,101,95,102,114,111,109,95, + 99,97,99,104,101,29,1,0,0,115,44,0,0,0,0,9, + 18,1,12,1,18,1,18,1,12,1,9,1,15,1,15,1, + 12,1,9,1,15,1,12,1,22,1,15,1,9,1,12,1, + 22,1,12,1,9,1,12,1,19,1,114,85,0,0,0,99, + 1,0,0,0,0,0,0,0,5,0,0,0,12,0,0,0, + 67,0,0,0,115,164,0,0,0,116,0,0,124,0,0,131, + 1,0,100,1,0,107,2,0,114,22,0,100,2,0,83,124, + 0,0,106,1,0,100,3,0,131,1,0,92,3,0,125,1, + 0,125,2,0,125,3,0,124,1,0,12,115,81,0,124,3, + 0,106,2,0,131,0,0,100,7,0,100,8,0,133,2,0, + 25,100,6,0,107,3,0,114,85,0,124,0,0,83,121,16, + 0,116,3,0,124,0,0,131,1,0,125,4,0,87,110,40, + 0,4,116,4,0,116,5,0,102,2,0,107,10,0,114,143, + 0,1,1,1,124,0,0,100,2,0,100,9,0,133,2,0, + 25,125,4,0,89,110,1,0,88,116,6,0,124,4,0,131, + 1,0,114,160,0,124,4,0,83,124,0,0,83,41,10,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,59,0, + 0,0,78,114,58,0,0,0,114,80,0,0,0,114,29,0, + 0,0,90,2,112,121,233,253,255,255,255,233,255,255,255,255, + 114,87,0,0,0,41,7,114,31,0,0,0,114,32,0,0, + 0,218,5,108,111,119,101,114,114,85,0,0,0,114,66,0, + 0,0,114,71,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,78,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, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,15, + 95,103,101,116,95,115,111,117,114,99,101,102,105,108,101,62, + 1,0,0,115,20,0,0,0,0,7,18,1,4,1,24,1, + 35,1,4,1,3,1,16,1,19,1,21,1,114,91,0,0, + 0,99,1,0,0,0,0,0,0,0,1,0,0,0,11,0, + 0,0,67,0,0,0,115,92,0,0,0,124,0,0,106,0, + 0,116,1,0,116,2,0,131,1,0,131,1,0,114,59,0, + 121,14,0,116,3,0,124,0,0,131,1,0,83,87,113,88, + 0,4,116,4,0,107,10,0,114,55,0,1,1,1,89,113, + 88,0,88,110,29,0,124,0,0,106,0,0,116,1,0,116, + 5,0,131,1,0,131,1,0,114,84,0,124,0,0,83,100, + 0,0,83,100,0,0,83,41,1,78,41,6,218,8,101,110, + 100,115,119,105,116,104,218,5,116,117,112,108,101,114,84,0, + 0,0,114,79,0,0,0,114,66,0,0,0,114,74,0,0, + 0,41,1,218,8,102,105,108,101,110,97,109,101,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,11,95,103, + 101,116,95,99,97,99,104,101,100,81,1,0,0,115,16,0, + 0,0,0,1,21,1,3,1,14,1,13,1,8,1,21,1, + 4,2,114,95,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,60,0,0, + 0,121,19,0,116,0,0,124,0,0,131,1,0,106,1,0, + 125,1,0,87,110,24,0,4,116,2,0,107,10,0,114,45, + 0,1,1,1,100,1,0,125,1,0,89,110,1,0,88,124, + 1,0,100,2,0,79,125,1,0,124,1,0,83,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,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,10,95,99,97,108, + 99,95,109,111,100,101,93,1,0,0,115,12,0,0,0,0, + 2,3,1,19,1,13,1,11,3,10,1,114,97,0,0,0, + 218,9,118,101,114,98,111,115,105,116,121,114,29,0,0,0, + 99,1,0,0,0,1,0,0,0,3,0,0,0,4,0,0, + 0,71,0,0,0,115,75,0,0,0,116,0,0,106,1,0, + 106,2,0,124,1,0,107,5,0,114,71,0,124,0,0,106, + 3,0,100,6,0,131,1,0,115,43,0,100,3,0,124,0, + 0,23,125,0,0,116,4,0,124,0,0,106,5,0,124,2, + 0,140,0,0,100,4,0,116,0,0,106,6,0,131,1,1, + 1,100,5,0,83,41,7,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,250,1,35,250,7,105,109,112,111,114, + 116,32,122,2,35,32,114,54,0,0,0,78,41,2,114,99, + 0,0,0,114,100,0,0,0,41,7,114,7,0,0,0,114, + 67,0,0,0,218,7,118,101,114,98,111,115,101,114,9,0, + 0,0,218,5,112,114,105,110,116,114,47,0,0,0,218,6, + 115,116,100,101,114,114,41,3,114,75,0,0,0,114,98,0, + 0,0,218,4,97,114,103,115,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,16,95,118,101,114,98,111,115, + 101,95,109,101,115,115,97,103,101,105,1,0,0,115,8,0, + 0,0,0,2,18,1,15,1,10,1,114,105,0,0,0,99, + 1,0,0,0,0,0,0,0,3,0,0,0,11,0,0,0, + 3,0,0,0,115,84,0,0,0,100,1,0,135,0,0,102, + 1,0,100,2,0,100,3,0,134,1,0,125,1,0,121,13, + 0,116,0,0,106,1,0,125,2,0,87,110,30,0,4,116, + 2,0,107,10,0,114,66,0,1,1,1,100,4,0,100,5, + 0,132,0,0,125,2,0,89,110,1,0,88,124,2,0,124, + 1,0,136,0,0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31, + 0,0,0,115,80,0,0,0,124,1,0,100,0,0,107,8, + 0,114,24,0,124,0,0,106,0,0,125,1,0,110,37,0, + 124,0,0,106,0,0,124,1,0,107,3,0,114,61,0,116, + 1,0,100,1,0,124,1,0,22,100,2,0,124,1,0,131, + 1,1,130,1,0,136,0,0,124,0,0,124,1,0,124,2, + 0,124,3,0,142,2,0,83,41,3,78,122,23,108,111,97, + 100,101,114,32,99,97,110,110,111,116,32,104,97,110,100,108, + 101,32,37,115,218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0, + 90,6,107,119,97,114,103,115,41,1,218,6,109,101,116,104, + 111,100,114,4,0,0,0,114,5,0,0,0,218,19,95,99, + 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, + 114,121,1,0,0,115,10,0,0,0,0,1,12,1,12,1, + 15,1,22,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,92,0,0,0,120,66,0,100,1,0,100,2, + 0,100,3,0,100,4,0,103,4,0,68,93,46,0,125,2, + 0,116,0,0,124,1,0,124,2,0,131,2,0,114,19,0, + 116,1,0,124,0,0,124,2,0,116,2,0,124,1,0,124, + 2,0,131,2,0,131,3,0,1,113,19,0,87,124,0,0, + 106,3,0,106,4,0,124,1,0,106,3,0,131,1,0,1, + 100,0,0,83,41,5,78,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,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,114, + 52,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,5,95,119,114,97,112,131,1,0,0,115,8, + 0,0,0,0,1,25,1,15,1,29,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,3,218,10,95,98,111,111,116, + 115,116,114,97,112,114,120,0,0,0,218,9,78,97,109,101, + 69,114,114,111,114,41,3,114,109,0,0,0,114,110,0,0, + 0,114,120,0,0,0,114,4,0,0,0,41,1,114,109,0, + 0,0,114,5,0,0,0,218,11,95,99,104,101,99,107,95, + 110,97,109,101,113,1,0,0,115,14,0,0,0,0,8,21, + 6,3,1,13,1,13,2,17,5,13,1,114,123,0,0,0, + 99,2,0,0,0,0,0,0,0,5,0,0,0,4,0,0, + 0,67,0,0,0,115,84,0,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,92,2,0,125,2,0,125,3,0,124, + 2,0,100,1,0,107,8,0,114,80,0,116,1,0,124,3, + 0,131,1,0,114,80,0,100,2,0,125,4,0,116,2,0, + 106,3,0,124,4,0,106,4,0,124,3,0,100,3,0,25, + 131,1,0,116,5,0,131,2,0,1,124,2,0,83,41,4, + 122,155,84,114,121,32,116,111,32,102,105,110,100,32,97,32, + 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, + 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,32, + 98,121,32,100,101,108,101,103,97,116,105,110,103,32,116,111, + 10,32,32,32,32,115,101,108,102,46,102,105,110,100,95,108, + 111,97,100,101,114,40,41,46,10,10,32,32,32,32,84,104, + 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, + 114,101,99,97,116,101,100,32,105,110,32,102,97,118,111,114, + 32,111,102,32,102,105,110,100,101,114,46,102,105,110,100,95, + 115,112,101,99,40,41,46,10,10,32,32,32,32,78,122,44, + 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, + 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, + 105,110,103,32,95,95,105,110,105,116,95,95,114,59,0,0, + 0,41,6,218,11,102,105,110,100,95,108,111,97,100,101,114, + 114,31,0,0,0,114,60,0,0,0,114,61,0,0,0,114, + 47,0,0,0,218,13,73,109,112,111,114,116,87,97,114,110, + 105,110,103,41,5,114,108,0,0,0,218,8,102,117,108,108, + 110,97,109,101,218,6,108,111,97,100,101,114,218,8,112,111, + 114,116,105,111,110,115,218,3,109,115,103,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,17,95,102,105,110, + 100,95,109,111,100,117,108,101,95,115,104,105,109,140,1,0, + 0,115,10,0,0,0,0,10,21,1,24,1,6,1,29,1, + 114,130,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,87,0,0,0,116, + 0,0,124,1,0,124,0,0,131,2,0,125,2,0,124,1, + 0,116,1,0,106,2,0,107,6,0,114,70,0,116,1,0, + 106,2,0,124,1,0,25,125,3,0,116,3,0,106,4,0, + 124,2,0,124,3,0,131,2,0,1,116,1,0,106,2,0, + 124,1,0,25,83,116,3,0,106,5,0,124,2,0,131,1, + 0,83,100,1,0,83,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,6,218,16,115, + 112,101,99,95,102,114,111,109,95,108,111,97,100,101,114,114, + 7,0,0,0,218,7,109,111,100,117,108,101,115,114,121,0, + 0,0,90,5,95,101,120,101,99,90,5,95,108,111,97,100, + 41,4,114,108,0,0,0,114,126,0,0,0,218,4,115,112, + 101,99,218,6,109,111,100,117,108,101,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,17,95,108,111,97,100, + 95,109,111,100,117,108,101,95,115,104,105,109,158,1,0,0, + 115,12,0,0,0,0,6,15,1,15,1,13,1,16,1,11, + 2,114,135,0,0,0,99,4,0,0,0,0,0,0,0,11, + 0,0,0,19,0,0,0,67,0,0,0,115,228,1,0,0, + 105,0,0,125,4,0,124,2,0,100,1,0,107,9,0,114, + 31,0,124,2,0,124,4,0,100,2,0,60,110,6,0,100, + 3,0,125,2,0,124,3,0,100,1,0,107,9,0,114,59, + 0,124,3,0,124,4,0,100,4,0,60,124,0,0,100,1, + 0,100,5,0,133,2,0,25,125,5,0,124,0,0,100,5, + 0,100,6,0,133,2,0,25,125,6,0,124,0,0,100,6, + 0,100,7,0,133,2,0,25,125,7,0,124,5,0,116,0, + 0,107,3,0,114,165,0,100,8,0,106,1,0,124,2,0, + 124,5,0,131,2,0,125,8,0,116,2,0,124,8,0,131, + 1,0,1,116,3,0,124,8,0,124,4,0,141,1,0,130, + 1,0,110,113,0,116,4,0,124,6,0,131,1,0,100,5, + 0,107,3,0,114,223,0,100,9,0,106,1,0,124,2,0, + 131,1,0,125,8,0,116,2,0,124,8,0,131,1,0,1, + 116,5,0,124,8,0,131,1,0,130,1,0,110,55,0,116, + 4,0,124,7,0,131,1,0,100,5,0,107,3,0,114,22, + 1,100,10,0,106,1,0,124,2,0,131,1,0,125,8,0, + 116,2,0,124,8,0,131,1,0,1,116,5,0,124,8,0, + 131,1,0,130,1,0,124,1,0,100,1,0,107,9,0,114, + 214,1,121,20,0,116,6,0,124,1,0,100,11,0,25,131, + 1,0,125,9,0,87,110,18,0,4,116,7,0,107,10,0, + 114,74,1,1,1,1,89,110,59,0,88,116,8,0,124,6, + 0,131,1,0,124,9,0,107,3,0,114,133,1,100,12,0, + 106,1,0,124,2,0,131,1,0,125,8,0,116,2,0,124, + 8,0,131,1,0,1,116,3,0,124,8,0,124,4,0,141, + 1,0,130,1,0,121,18,0,124,1,0,100,13,0,25,100, + 14,0,64,125,10,0,87,110,18,0,4,116,7,0,107,10, + 0,114,171,1,1,1,1,89,110,43,0,88,116,8,0,124, + 7,0,131,1,0,124,10,0,107,3,0,114,214,1,116,3, + 0,100,12,0,106,1,0,124,2,0,131,1,0,124,4,0, + 141,1,0,130,1,0,124,0,0,100,7,0,100,1,0,133, + 2,0,25,83,41,15,97,122,1,0,0,86,97,108,105,100, + 97,116,101,32,116,104,101,32,104,101,97,100,101,114,32,111, + 102,32,116,104,101,32,112,97,115,115,101,100,45,105,110,32, + 98,121,116,101,99,111,100,101,32,97,103,97,105,110,115,116, + 32,115,111,117,114,99,101,95,115,116,97,116,115,32,40,105, + 102,10,32,32,32,32,103,105,118,101,110,41,32,97,110,100, + 32,114,101,116,117,114,110,105,110,103,32,116,104,101,32,98, + 121,116,101,99,111,100,101,32,116,104,97,116,32,99,97,110, + 32,98,101,32,99,111,109,112,105,108,101,100,32,98,121,32, + 99,111,109,112,105,108,101,40,41,46,10,10,32,32,32,32, + 65,108,108,32,111,116,104,101,114,32,97,114,103,117,109,101, + 110,116,115,32,97,114,101,32,117,115,101,100,32,116,111,32, + 101,110,104,97,110,99,101,32,101,114,114,111,114,32,114,101, + 112,111,114,116,105,110,103,46,10,10,32,32,32,32,73,109, + 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, + 115,101,100,32,119,104,101,110,32,116,104,101,32,109,97,103, + 105,99,32,110,117,109,98,101,114,32,105,115,32,105,110,99, + 111,114,114,101,99,116,32,111,114,32,116,104,101,32,98,121, + 116,101,99,111,100,101,32,105,115,10,32,32,32,32,102,111, + 117,110,100,32,116,111,32,98,101,32,115,116,97,108,101,46, + 32,69,79,70,69,114,114,111,114,32,105,115,32,114,97,105, + 115,101,100,32,119,104,101,110,32,116,104,101,32,100,97,116, + 97,32,105,115,32,102,111,117,110,100,32,116,111,32,98,101, + 10,32,32,32,32,116,114,117,110,99,97,116,101,100,46,10, + 10,32,32,32,32,78,114,106,0,0,0,122,10,60,98,121, + 116,101,99,111,100,101,62,114,35,0,0,0,114,12,0,0, + 0,233,8,0,0,0,233,12,0,0,0,122,30,98,97,100, + 32,109,97,103,105,99,32,110,117,109,98,101,114,32,105,110, + 32,123,33,114,125,58,32,123,33,114,125,122,43,114,101,97, + 99,104,101,100,32,69,79,70,32,119,104,105,108,101,32,114, + 101,97,100,105,110,103,32,116,105,109,101,115,116,97,109,112, + 32,105,110,32,123,33,114,125,122,48,114,101,97,99,104,101, + 100,32,69,79,70,32,119,104,105,108,101,32,114,101,97,100, + 105,110,103,32,115,105,122,101,32,111,102,32,115,111,117,114, + 99,101,32,105,110,32,123,33,114,125,218,5,109,116,105,109, + 101,122,26,98,121,116,101,99,111,100,101,32,105,115,32,115, + 116,97,108,101,32,102,111,114,32,123,33,114,125,218,4,115, + 105,122,101,108,3,0,0,0,255,127,255,127,3,0,41,9, + 218,12,77,65,71,73,67,95,78,85,77,66,69,82,114,47, + 0,0,0,114,105,0,0,0,114,107,0,0,0,114,31,0, + 0,0,218,8,69,79,70,69,114,114,111,114,114,14,0,0, + 0,218,8,75,101,121,69,114,114,111,114,114,19,0,0,0, + 41,11,114,53,0,0,0,218,12,115,111,117,114,99,101,95, + 115,116,97,116,115,114,106,0,0,0,114,35,0,0,0,90, + 11,101,120,99,95,100,101,116,97,105,108,115,90,5,109,97, + 103,105,99,90,13,114,97,119,95,116,105,109,101,115,116,97, + 109,112,90,8,114,97,119,95,115,105,122,101,114,75,0,0, + 0,218,12,115,111,117,114,99,101,95,109,116,105,109,101,218, + 11,115,111,117,114,99,101,95,115,105,122,101,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,25,95,118,97, + 108,105,100,97,116,101,95,98,121,116,101,99,111,100,101,95, + 104,101,97,100,101,114,173,1,0,0,115,76,0,0,0,0, + 11,6,1,12,1,13,3,6,1,12,1,10,1,16,1,16, + 1,16,1,12,1,18,1,10,1,18,1,18,1,15,1,10, + 1,15,1,18,1,15,1,10,1,12,1,12,1,3,1,20, + 1,13,1,5,2,18,1,15,1,10,1,15,1,3,1,18, + 1,13,1,5,2,18,1,15,1,9,1,114,146,0,0,0, + 99,4,0,0,0,0,0,0,0,5,0,0,0,6,0,0, + 0,67,0,0,0,115,112,0,0,0,116,0,0,106,1,0, + 124,0,0,131,1,0,125,4,0,116,2,0,124,4,0,116, + 3,0,131,2,0,114,75,0,116,4,0,100,1,0,124,2, + 0,131,2,0,1,124,3,0,100,2,0,107,9,0,114,71, + 0,116,5,0,106,6,0,124,4,0,124,3,0,131,2,0, + 1,124,4,0,83,116,7,0,100,3,0,106,8,0,124,2, + 0,131,1,0,100,4,0,124,1,0,100,5,0,124,2,0, + 131,1,2,130,1,0,100,2,0,83,41,6,122,60,67,111, + 109,112,105,108,101,32,98,121,116,101,99,111,100,101,32,97, + 115,32,114,101,116,117,114,110,101,100,32,98,121,32,95,118, + 97,108,105,100,97,116,101,95,98,121,116,101,99,111,100,101, + 95,104,101,97,100,101,114,40,41,46,122,21,99,111,100,101, + 32,111,98,106,101,99,116,32,102,114,111,109,32,123,33,114, + 125,78,122,23,78,111,110,45,99,111,100,101,32,111,98,106, + 101,99,116,32,105,110,32,123,33,114,125,114,106,0,0,0, + 114,35,0,0,0,41,9,218,7,109,97,114,115,104,97,108, + 90,5,108,111,97,100,115,218,10,105,115,105,110,115,116,97, + 110,99,101,218,10,95,99,111,100,101,95,116,121,112,101,114, + 105,0,0,0,218,4,95,105,109,112,90,16,95,102,105,120, + 95,99,111,95,102,105,108,101,110,97,109,101,114,107,0,0, + 0,114,47,0,0,0,41,5,114,53,0,0,0,114,106,0, + 0,0,114,89,0,0,0,114,90,0,0,0,218,4,99,111, + 100,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,17,95,99,111,109,112,105,108,101,95,98,121,116,101, + 99,111,100,101,228,1,0,0,115,16,0,0,0,0,2,15, + 1,15,1,13,1,12,1,16,1,4,2,18,1,114,152,0, + 0,0,114,59,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,76,0,0, + 0,116,0,0,116,1,0,131,1,0,125,3,0,124,3,0, + 106,2,0,116,3,0,124,1,0,131,1,0,131,1,0,1, + 124,3,0,106,2,0,116,3,0,124,2,0,131,1,0,131, + 1,0,1,124,3,0,106,2,0,116,4,0,106,5,0,124, + 0,0,131,1,0,131,1,0,1,124,3,0,83,41,1,122, + 80,67,111,109,112,105,108,101,32,97,32,99,111,100,101,32, + 111,98,106,101,99,116,32,105,110,116,111,32,98,121,116,101, + 99,111,100,101,32,102,111,114,32,119,114,105,116,105,110,103, + 32,111,117,116,32,116,111,32,97,32,98,121,116,101,45,99, + 111,109,112,105,108,101,100,10,32,32,32,32,102,105,108,101, + 46,41,6,218,9,98,121,116,101,97,114,114,97,121,114,140, + 0,0,0,218,6,101,120,116,101,110,100,114,17,0,0,0, + 114,147,0,0,0,90,5,100,117,109,112,115,41,4,114,151, + 0,0,0,114,138,0,0,0,114,145,0,0,0,114,53,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,17,95,99,111,100,101,95,116,111,95,98,121,116,101, + 99,111,100,101,240,1,0,0,115,10,0,0,0,0,3,12, + 1,19,1,19,1,22,1,114,155,0,0,0,99,1,0,0, + 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, + 0,115,89,0,0,0,100,1,0,100,2,0,108,0,0,125, + 1,0,116,1,0,106,2,0,124,0,0,131,1,0,106,3, + 0,125,2,0,124,1,0,106,4,0,124,2,0,131,1,0, + 125,3,0,116,1,0,106,5,0,100,2,0,100,3,0,131, + 2,0,125,4,0,124,4,0,106,6,0,124,0,0,106,6, + 0,124,3,0,100,1,0,25,131,1,0,131,1,0,83,41, + 4,122,121,68,101,99,111,100,101,32,98,121,116,101,115,32, + 114,101,112,114,101,115,101,110,116,105,110,103,32,115,111,117, + 114,99,101,32,99,111,100,101,32,97,110,100,32,114,101,116, + 117,114,110,32,116,104,101,32,115,116,114,105,110,103,46,10, + 10,32,32,32,32,85,110,105,118,101,114,115,97,108,32,110, + 101,119,108,105,110,101,32,115,117,112,112,111,114,116,32,105, + 115,32,117,115,101,100,32,105,110,32,116,104,101,32,100,101, + 99,111,100,105,110,103,46,10,32,32,32,32,114,59,0,0, + 0,78,84,41,7,218,8,116,111,107,101,110,105,122,101,114, + 49,0,0,0,90,7,66,121,116,101,115,73,79,90,8,114, + 101,97,100,108,105,110,101,90,15,100,101,116,101,99,116,95, + 101,110,99,111,100,105,110,103,90,25,73,110,99,114,101,109, + 101,110,116,97,108,78,101,119,108,105,110,101,68,101,99,111, + 100,101,114,218,6,100,101,99,111,100,101,41,5,218,12,115, + 111,117,114,99,101,95,98,121,116,101,115,114,156,0,0,0, + 90,21,115,111,117,114,99,101,95,98,121,116,101,115,95,114, + 101,97,100,108,105,110,101,218,8,101,110,99,111,100,105,110, + 103,90,15,110,101,119,108,105,110,101,95,100,101,99,111,100, + 101,114,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,13,100,101,99,111,100,101,95,115,111,117,114,99,101, + 250,1,0,0,115,10,0,0,0,0,5,12,1,18,1,15, + 1,18,1,114,160,0,0,0,218,6,111,114,105,103,105,110, + 218,10,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,2,0,0,0,5,0,0,0,15,0,0,0,67,0,0, + 0,115,193,0,0,0,116,0,0,124,1,0,100,1,0,131, + 2,0,114,83,0,124,3,0,100,2,0,107,8,0,114,43, + 0,116,1,0,124,0,0,100,3,0,124,1,0,131,1,1, + 83,124,3,0,114,55,0,103,0,0,110,3,0,100,2,0, + 125,4,0,116,1,0,124,0,0,100,3,0,124,1,0,100, + 4,0,124,4,0,131,1,2,83,124,3,0,100,2,0,107, + 8,0,114,165,0,116,0,0,124,1,0,100,5,0,131,2, + 0,114,159,0,121,19,0,124,1,0,106,2,0,124,0,0, + 131,1,0,125,3,0,87,113,165,0,4,116,3,0,107,10, + 0,114,155,0,1,1,1,100,2,0,125,3,0,89,113,165, + 0,88,110,6,0,100,6,0,125,3,0,116,4,0,106,5, + 0,124,0,0,124,1,0,100,7,0,124,2,0,100,5,0, + 124,3,0,131,2,2,83,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, + 218,12,103,101,116,95,102,105,108,101,110,97,109,101,78,114, + 127,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, + 114,162,0,0,0,70,114,161,0,0,0,41,6,114,115,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,162,0,0,0, + 114,107,0,0,0,114,121,0,0,0,218,10,77,111,100,117, + 108,101,83,112,101,99,41,5,114,106,0,0,0,114,127,0, + 0,0,114,161,0,0,0,114,162,0,0,0,90,6,115,101, + 97,114,99,104,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,131,0,0,0,8,2,0,0,115,28,0,0, + 0,0,2,15,1,12,1,16,1,18,1,15,1,7,2,12, + 1,15,1,3,1,19,1,13,1,14,3,6,2,114,131,0, + 0,0,114,127,0,0,0,114,164,0,0,0,99,2,0,0, + 0,2,0,0,0,9,0,0,0,19,0,0,0,67,0,0, + 0,115,89,1,0,0,124,1,0,100,1,0,107,8,0,114, + 73,0,100,2,0,125,1,0,116,0,0,124,2,0,100,3, + 0,131,2,0,114,73,0,121,19,0,124,2,0,106,1,0, + 124,0,0,131,1,0,125,1,0,87,110,18,0,4,116,2, + 0,107,10,0,114,72,0,1,1,1,89,110,1,0,88,116, + 3,0,106,4,0,124,0,0,124,2,0,100,4,0,124,1, + 0,131,2,1,125,4,0,100,5,0,124,4,0,95,5,0, + 124,2,0,100,1,0,107,8,0,114,194,0,120,73,0,116, + 6,0,131,0,0,68,93,58,0,92,2,0,125,5,0,125, + 6,0,124,1,0,106,7,0,116,8,0,124,6,0,131,1, + 0,131,1,0,114,128,0,124,5,0,124,0,0,124,1,0, + 131,2,0,125,2,0,124,2,0,124,4,0,95,9,0,80, + 113,128,0,87,100,1,0,83,124,3,0,116,10,0,107,8, + 0,114,23,1,116,0,0,124,2,0,100,6,0,131,2,0, + 114,32,1,121,19,0,124,2,0,106,11,0,124,0,0,131, + 1,0,125,7,0,87,110,18,0,4,116,2,0,107,10,0, + 114,4,1,1,1,1,89,113,32,1,88,124,7,0,114,32, + 1,103,0,0,124,4,0,95,12,0,110,9,0,124,3,0, + 124,4,0,95,12,0,124,4,0,106,12,0,103,0,0,107, + 2,0,114,85,1,124,1,0,114,85,1,116,13,0,124,1, + 0,131,1,0,100,7,0,25,125,8,0,124,4,0,106,12, + 0,106,14,0,124,8,0,131,1,0,1,124,4,0,83,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,114, + 163,0,0,0,114,161,0,0,0,84,114,162,0,0,0,114, + 59,0,0,0,41,15,114,115,0,0,0,114,163,0,0,0, + 114,107,0,0,0,114,121,0,0,0,114,166,0,0,0,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,92,0,0,0, + 114,93,0,0,0,114,127,0,0,0,218,9,95,80,79,80, + 85,76,65,84,69,114,162,0,0,0,114,164,0,0,0,114, + 38,0,0,0,218,6,97,112,112,101,110,100,41,9,114,106, + 0,0,0,90,8,108,111,99,97,116,105,111,110,114,127,0, + 0,0,114,164,0,0,0,114,133,0,0,0,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,162,0,0,0,90,7,100,105,114,110,97, 109,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,17,115,111,117,114,99,101,95,102,114,111,109,95,99, - 97,99,104,101,29,1,0,0,115,44,0,0,0,0,9,18, - 1,12,1,18,1,18,1,12,1,9,1,15,1,15,1,12, - 1,9,1,15,1,12,1,22,1,15,1,9,1,12,1,22, - 1,12,1,9,1,12,1,19,1,114,85,0,0,0,99,1, - 0,0,0,0,0,0,0,5,0,0,0,12,0,0,0,67, - 0,0,0,115,164,0,0,0,116,0,0,124,0,0,131,1, - 0,100,1,0,107,2,0,114,22,0,100,2,0,83,124,0, - 0,106,1,0,100,3,0,131,1,0,92,3,0,125,1,0, - 125,2,0,125,3,0,124,1,0,12,115,81,0,124,3,0, - 106,2,0,131,0,0,100,7,0,100,8,0,133,2,0,25, - 100,6,0,107,3,0,114,85,0,124,0,0,83,121,16,0, - 116,3,0,124,0,0,131,1,0,125,4,0,87,110,40,0, - 4,116,4,0,116,5,0,102,2,0,107,10,0,114,143,0, - 1,1,1,124,0,0,100,2,0,100,9,0,133,2,0,25, - 125,4,0,89,110,1,0,88,116,6,0,124,4,0,131,1, - 0,114,160,0,124,4,0,83,124,0,0,83,41,10,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,59,0,0, - 0,78,114,58,0,0,0,114,80,0,0,0,114,29,0,0, - 0,90,2,112,121,233,253,255,255,255,233,255,255,255,255,114, - 87,0,0,0,41,7,114,31,0,0,0,114,32,0,0,0, - 218,5,108,111,119,101,114,114,85,0,0,0,114,66,0,0, - 0,114,71,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,78,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,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,15,95, - 103,101,116,95,115,111,117,114,99,101,102,105,108,101,62,1, - 0,0,115,20,0,0,0,0,7,18,1,4,1,24,1,35, - 1,4,1,3,1,16,1,19,1,21,1,114,91,0,0,0, - 99,1,0,0,0,0,0,0,0,1,0,0,0,11,0,0, - 0,67,0,0,0,115,92,0,0,0,124,0,0,106,0,0, - 116,1,0,116,2,0,131,1,0,131,1,0,114,59,0,121, - 14,0,116,3,0,124,0,0,131,1,0,83,87,113,88,0, - 4,116,4,0,107,10,0,114,55,0,1,1,1,89,113,88, - 0,88,110,29,0,124,0,0,106,0,0,116,1,0,116,5, - 0,131,1,0,131,1,0,114,84,0,124,0,0,83,100,0, - 0,83,100,0,0,83,41,1,78,41,6,218,8,101,110,100, - 115,119,105,116,104,218,5,116,117,112,108,101,114,84,0,0, - 0,114,79,0,0,0,114,66,0,0,0,114,74,0,0,0, - 41,1,218,8,102,105,108,101,110,97,109,101,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,11,95,103,101, - 116,95,99,97,99,104,101,100,81,1,0,0,115,16,0,0, - 0,0,1,21,1,3,1,14,1,13,1,8,1,21,1,4, - 2,114,95,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,60,0,0,0, - 121,19,0,116,0,0,124,0,0,131,1,0,106,1,0,125, - 1,0,87,110,24,0,4,116,2,0,107,10,0,114,45,0, - 1,1,1,100,1,0,125,1,0,89,110,1,0,88,124,1, - 0,100,2,0,79,125,1,0,124,1,0,83,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,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,10,95,99,97,108,99, - 95,109,111,100,101,93,1,0,0,115,12,0,0,0,0,2, - 3,1,19,1,13,1,11,3,10,1,114,97,0,0,0,218, - 9,118,101,114,98,111,115,105,116,121,114,29,0,0,0,99, - 1,0,0,0,1,0,0,0,3,0,0,0,4,0,0,0, - 71,0,0,0,115,75,0,0,0,116,0,0,106,1,0,106, - 2,0,124,1,0,107,5,0,114,71,0,124,0,0,106,3, - 0,100,6,0,131,1,0,115,43,0,100,3,0,124,0,0, - 23,125,0,0,116,4,0,124,0,0,106,5,0,124,2,0, - 140,0,0,100,4,0,116,0,0,106,6,0,131,1,1,1, - 100,5,0,83,41,7,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,250,1,35,250,7,105,109,112,111,114,116, - 32,122,2,35,32,114,54,0,0,0,78,41,2,114,99,0, - 0,0,114,100,0,0,0,41,7,114,7,0,0,0,114,67, - 0,0,0,218,7,118,101,114,98,111,115,101,114,9,0,0, - 0,218,5,112,114,105,110,116,114,47,0,0,0,218,6,115, - 116,100,101,114,114,41,3,114,75,0,0,0,114,98,0,0, - 0,218,4,97,114,103,115,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,16,95,118,101,114,98,111,115,101, - 95,109,101,115,115,97,103,101,105,1,0,0,115,8,0,0, - 0,0,2,18,1,15,1,10,1,114,105,0,0,0,99,1, - 0,0,0,0,0,0,0,3,0,0,0,11,0,0,0,3, - 0,0,0,115,84,0,0,0,100,1,0,135,0,0,102,1, - 0,100,2,0,100,3,0,134,1,0,125,1,0,121,13,0, - 116,0,0,106,1,0,125,2,0,87,110,30,0,4,116,2, - 0,107,10,0,114,66,0,1,1,1,100,4,0,100,5,0, - 132,0,0,125,2,0,89,110,1,0,88,124,2,0,124,1, - 0,136,0,0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31,0, - 0,0,115,80,0,0,0,124,1,0,100,0,0,107,8,0, - 114,24,0,124,0,0,106,0,0,125,1,0,110,37,0,124, - 0,0,106,0,0,124,1,0,107,3,0,114,61,0,116,1, - 0,100,1,0,124,1,0,22,100,2,0,124,1,0,131,1, - 1,130,1,0,136,0,0,124,0,0,124,1,0,124,2,0, - 124,3,0,142,2,0,83,41,3,78,122,23,108,111,97,100, - 101,114,32,99,97,110,110,111,116,32,104,97,110,100,108,101, - 32,37,115,218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0,90, - 6,107,119,97,114,103,115,41,1,218,6,109,101,116,104,111, - 100,114,4,0,0,0,114,5,0,0,0,218,19,95,99,104, - 101,99,107,95,110,97,109,101,95,119,114,97,112,112,101,114, - 121,1,0,0,115,10,0,0,0,0,1,12,1,12,1,15, - 1,22,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,92,0,0,0,120,66,0,100,1,0,100,2,0, - 100,3,0,100,4,0,103,4,0,68,93,46,0,125,2,0, - 116,0,0,124,1,0,124,2,0,131,2,0,114,19,0,116, - 1,0,124,0,0,124,2,0,116,2,0,124,1,0,124,2, - 0,131,2,0,131,3,0,1,113,19,0,87,124,0,0,106, - 3,0,106,4,0,124,1,0,106,3,0,131,1,0,1,100, - 0,0,83,41,5,78,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,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,114,52, + 0,114,165,0,0,0,33,2,0,0,115,60,0,0,0,0, + 12,12,4,6,1,15,2,3,1,19,1,13,1,5,8,24, + 1,9,3,12,1,22,1,21,1,15,1,9,1,5,2,4, + 3,12,2,15,1,3,1,19,1,13,1,5,2,6,1,12, + 2,9,1,15,1,6,1,16,1,16,2,114,165,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0, + 0,64,0,0,0,115,121,0,0,0,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,90, + 4,0,100,3,0,90,5,0,100,4,0,90,6,0,101,7, + 0,100,5,0,100,6,0,132,0,0,131,1,0,90,8,0, + 101,7,0,100,7,0,100,8,0,132,0,0,131,1,0,90, + 9,0,101,7,0,100,9,0,100,9,0,100,10,0,100,11, + 0,132,2,0,131,1,0,90,10,0,101,7,0,100,9,0, + 100,12,0,100,13,0,132,1,0,131,1,0,90,11,0,100, + 9,0,83,41,14,218,21,87,105,110,100,111,119,115,82,101, + 103,105,115,116,114,121,70,105,110,100,101,114,122,62,77,101, + 116,97,32,112,97,116,104,32,102,105,110,100,101,114,32,102, + 111,114,32,109,111,100,117,108,101,115,32,100,101,99,108,97, + 114,101,100,32,105,110,32,116,104,101,32,87,105,110,100,111, + 119,115,32,114,101,103,105,115,116,114,121,46,122,59,83,111, + 102,116,119,97,114,101,92,80,121,116,104,111,110,92,80,121, + 116,104,111,110,67,111,114,101,92,123,115,121,115,95,118,101, + 114,115,105,111,110,125,92,77,111,100,117,108,101,115,92,123, + 102,117,108,108,110,97,109,101,125,122,65,83,111,102,116,119, + 97,114,101,92,80,121,116,104,111,110,92,80,121,116,104,111, + 110,67,111,114,101,92,123,115,121,115,95,118,101,114,115,105, + 111,110,125,92,77,111,100,117,108,101,115,92,123,102,117,108, + 108,110,97,109,101,125,92,68,101,98,117,103,70,99,2,0, + 0,0,0,0,0,0,2,0,0,0,11,0,0,0,67,0, + 0,0,115,67,0,0,0,121,23,0,116,0,0,106,1,0, + 116,0,0,106,2,0,124,1,0,131,2,0,83,87,110,37, + 0,4,116,3,0,107,10,0,114,62,0,1,1,1,116,0, + 0,106,1,0,116,0,0,106,4,0,124,1,0,131,2,0, + 83,89,110,1,0,88,100,0,0,83,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,218,3,107,101,121,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,14,95,111,112,101,110,95, + 114,101,103,105,115,116,114,121,111,2,0,0,115,8,0,0, + 0,0,2,3,1,23,1,13,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,16,0,0,0, + 67,0,0,0,115,143,0,0,0,124,0,0,106,0,0,114, + 21,0,124,0,0,106,1,0,125,2,0,110,9,0,124,0, + 0,106,2,0,125,2,0,124,2,0,106,3,0,100,1,0, + 124,1,0,100,2,0,116,4,0,106,5,0,100,0,0,100, + 3,0,133,2,0,25,131,0,2,125,3,0,121,47,0,124, + 0,0,106,6,0,124,3,0,131,1,0,143,25,0,125,4, + 0,116,7,0,106,8,0,124,4,0,100,4,0,131,2,0, + 125,5,0,87,100,0,0,81,82,88,87,110,22,0,4,116, + 9,0,107,10,0,114,138,0,1,1,1,100,0,0,83,89, + 110,1,0,88,124,5,0,83,41,5,78,114,126,0,0,0, + 90,11,115,121,115,95,118,101,114,115,105,111,110,114,80,0, + 0,0,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,47,0,0,0,114,7,0, + 0,0,218,7,118,101,114,115,105,111,110,114,176,0,0,0, + 114,173,0,0,0,90,10,81,117,101,114,121,86,97,108,117, + 101,114,40,0,0,0,41,6,114,174,0,0,0,114,126,0, + 0,0,90,12,114,101,103,105,115,116,114,121,95,107,101,121, + 114,175,0,0,0,90,4,104,107,101,121,218,8,102,105,108, + 101,112,97,116,104,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,16,95,115,101,97,114,99,104,95,114,101, + 103,105,115,116,114,121,118,2,0,0,115,22,0,0,0,0, + 2,9,1,12,2,9,1,15,1,22,1,3,1,18,1,29, + 1,13,1,9,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,14,0,0,0,67, + 0,0,0,115,155,0,0,0,124,0,0,106,0,0,124,1, + 0,131,1,0,125,4,0,124,4,0,100,0,0,107,8,0, + 114,31,0,100,0,0,83,121,14,0,116,1,0,124,4,0, + 131,1,0,1,87,110,22,0,4,116,2,0,107,10,0,114, + 69,0,1,1,1,100,0,0,83,89,110,1,0,88,120,78, + 0,116,3,0,131,0,0,68,93,67,0,92,2,0,125,5, + 0,125,6,0,124,4,0,106,4,0,116,5,0,124,6,0, + 131,1,0,131,1,0,114,80,0,116,6,0,124,1,0,124, + 5,0,124,1,0,124,4,0,131,2,0,100,1,0,124,4, + 0,131,2,1,125,7,0,124,7,0,83,113,80,0,87,100, + 0,0,83,41,2,78,114,161,0,0,0,41,7,114,182,0, + 0,0,114,39,0,0,0,114,40,0,0,0,114,167,0,0, + 0,114,92,0,0,0,114,93,0,0,0,114,131,0,0,0, + 41,8,114,174,0,0,0,114,126,0,0,0,114,35,0,0, + 0,218,6,116,97,114,103,101,116,114,181,0,0,0,114,127, + 0,0,0,114,171,0,0,0,114,133,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,9,102,105, + 110,100,95,115,112,101,99,133,2,0,0,115,24,0,0,0, + 0,2,15,1,12,1,4,1,3,1,14,1,13,1,9,1, + 22,1,21,1,21,1,9,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,3,0,0,0,67,0,0,0,115,45, + 0,0,0,124,0,0,106,0,0,124,1,0,124,2,0,131, + 2,0,125,3,0,124,3,0,100,1,0,107,9,0,114,37, + 0,124,3,0,106,1,0,83,100,1,0,83,100,1,0,83, + 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,184,0,0,0,114,127,0,0,0,41,4,114, + 174,0,0,0,114,126,0,0,0,114,35,0,0,0,114,133, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,5,95,119,114,97,112,131,1,0,0,115,8,0, - 0,0,0,1,25,1,15,1,29,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,3,218,10,95,98,111,111,116,115, - 116,114,97,112,114,120,0,0,0,218,9,78,97,109,101,69, - 114,114,111,114,41,3,114,109,0,0,0,114,110,0,0,0, - 114,120,0,0,0,114,4,0,0,0,41,1,114,109,0,0, - 0,114,5,0,0,0,218,11,95,99,104,101,99,107,95,110, - 97,109,101,113,1,0,0,115,14,0,0,0,0,8,21,6, - 3,1,13,1,13,2,17,5,13,1,114,123,0,0,0,99, - 2,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, - 67,0,0,0,115,84,0,0,0,124,0,0,106,0,0,124, - 1,0,131,1,0,92,2,0,125,2,0,125,3,0,124,2, - 0,100,1,0,107,8,0,114,80,0,116,1,0,124,3,0, - 131,1,0,114,80,0,100,2,0,125,4,0,116,2,0,106, - 3,0,124,4,0,106,4,0,124,3,0,100,3,0,25,131, - 1,0,116,5,0,131,2,0,1,124,2,0,83,41,4,122, - 155,84,114,121,32,116,111,32,102,105,110,100,32,97,32,108, - 111,97,100,101,114,32,102,111,114,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,109,111,100,117,108,101,32,98, - 121,32,100,101,108,101,103,97,116,105,110,103,32,116,111,10, - 32,32,32,32,115,101,108,102,46,102,105,110,100,95,108,111, - 97,100,101,114,40,41,46,10,10,32,32,32,32,84,104,105, - 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,32,105,110,32,102,97,118,111,114,32, - 111,102,32,102,105,110,100,101,114,46,102,105,110,100,95,115, - 112,101,99,40,41,46,10,10,32,32,32,32,78,122,44,78, - 111,116,32,105,109,112,111,114,116,105,110,103,32,100,105,114, - 101,99,116,111,114,121,32,123,125,58,32,109,105,115,115,105, - 110,103,32,95,95,105,110,105,116,95,95,114,59,0,0,0, - 41,6,218,11,102,105,110,100,95,108,111,97,100,101,114,114, - 31,0,0,0,114,60,0,0,0,114,61,0,0,0,114,47, - 0,0,0,218,13,73,109,112,111,114,116,87,97,114,110,105, - 110,103,41,5,114,108,0,0,0,218,8,102,117,108,108,110, - 97,109,101,218,6,108,111,97,100,101,114,218,8,112,111,114, - 116,105,111,110,115,218,3,109,115,103,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,17,95,102,105,110,100, - 95,109,111,100,117,108,101,95,115,104,105,109,140,1,0,0, - 115,10,0,0,0,0,10,21,1,24,1,6,1,29,1,114, - 130,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,87,0,0,0,116,0, - 0,124,1,0,124,0,0,131,2,0,125,2,0,124,1,0, - 116,1,0,106,2,0,107,6,0,114,70,0,116,1,0,106, - 2,0,124,1,0,25,125,3,0,116,3,0,106,4,0,124, - 2,0,124,3,0,131,2,0,1,116,1,0,106,2,0,124, - 1,0,25,83,116,3,0,106,5,0,124,2,0,131,1,0, - 83,100,1,0,83,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,6,218,16,115,112, - 101,99,95,102,114,111,109,95,108,111,97,100,101,114,114,7, - 0,0,0,218,7,109,111,100,117,108,101,115,114,121,0,0, - 0,90,5,95,101,120,101,99,90,5,95,108,111,97,100,41, - 4,114,108,0,0,0,114,126,0,0,0,218,4,115,112,101, - 99,218,6,109,111,100,117,108,101,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,17,95,108,111,97,100,95, - 109,111,100,117,108,101,95,115,104,105,109,158,1,0,0,115, - 12,0,0,0,0,6,15,1,15,1,13,1,16,1,11,2, - 114,135,0,0,0,99,4,0,0,0,0,0,0,0,11,0, - 0,0,19,0,0,0,67,0,0,0,115,228,1,0,0,105, - 0,0,125,4,0,124,2,0,100,1,0,107,9,0,114,31, - 0,124,2,0,124,4,0,100,2,0,60,110,6,0,100,3, - 0,125,2,0,124,3,0,100,1,0,107,9,0,114,59,0, - 124,3,0,124,4,0,100,4,0,60,124,0,0,100,1,0, - 100,5,0,133,2,0,25,125,5,0,124,0,0,100,5,0, - 100,6,0,133,2,0,25,125,6,0,124,0,0,100,6,0, - 100,7,0,133,2,0,25,125,7,0,124,5,0,116,0,0, - 107,3,0,114,165,0,100,8,0,106,1,0,124,2,0,124, - 5,0,131,2,0,125,8,0,116,2,0,124,8,0,131,1, - 0,1,116,3,0,124,8,0,124,4,0,141,1,0,130,1, - 0,110,113,0,116,4,0,124,6,0,131,1,0,100,5,0, - 107,3,0,114,223,0,100,9,0,106,1,0,124,2,0,131, - 1,0,125,8,0,116,2,0,124,8,0,131,1,0,1,116, - 5,0,124,8,0,131,1,0,130,1,0,110,55,0,116,4, - 0,124,7,0,131,1,0,100,5,0,107,3,0,114,22,1, - 100,10,0,106,1,0,124,2,0,131,1,0,125,8,0,116, - 2,0,124,8,0,131,1,0,1,116,5,0,124,8,0,131, - 1,0,130,1,0,124,1,0,100,1,0,107,9,0,114,214, - 1,121,20,0,116,6,0,124,1,0,100,11,0,25,131,1, - 0,125,9,0,87,110,18,0,4,116,7,0,107,10,0,114, - 74,1,1,1,1,89,110,59,0,88,116,8,0,124,6,0, - 131,1,0,124,9,0,107,3,0,114,133,1,100,12,0,106, - 1,0,124,2,0,131,1,0,125,8,0,116,2,0,124,8, - 0,131,1,0,1,116,3,0,124,8,0,124,4,0,141,1, - 0,130,1,0,121,18,0,124,1,0,100,13,0,25,100,14, - 0,64,125,10,0,87,110,18,0,4,116,7,0,107,10,0, - 114,171,1,1,1,1,89,110,43,0,88,116,8,0,124,7, - 0,131,1,0,124,10,0,107,3,0,114,214,1,116,3,0, - 100,12,0,106,1,0,124,2,0,131,1,0,124,4,0,141, - 1,0,130,1,0,124,0,0,100,7,0,100,1,0,133,2, - 0,25,83,41,15,97,122,1,0,0,86,97,108,105,100,97, - 116,101,32,116,104,101,32,104,101,97,100,101,114,32,111,102, - 32,116,104,101,32,112,97,115,115,101,100,45,105,110,32,98, - 121,116,101,99,111,100,101,32,97,103,97,105,110,115,116,32, - 115,111,117,114,99,101,95,115,116,97,116,115,32,40,105,102, - 10,32,32,32,32,103,105,118,101,110,41,32,97,110,100,32, - 114,101,116,117,114,110,105,110,103,32,116,104,101,32,98,121, - 116,101,99,111,100,101,32,116,104,97,116,32,99,97,110,32, - 98,101,32,99,111,109,112,105,108,101,100,32,98,121,32,99, - 111,109,112,105,108,101,40,41,46,10,10,32,32,32,32,65, - 108,108,32,111,116,104,101,114,32,97,114,103,117,109,101,110, - 116,115,32,97,114,101,32,117,115,101,100,32,116,111,32,101, - 110,104,97,110,99,101,32,101,114,114,111,114,32,114,101,112, - 111,114,116,105,110,103,46,10,10,32,32,32,32,73,109,112, - 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, - 101,100,32,119,104,101,110,32,116,104,101,32,109,97,103,105, - 99,32,110,117,109,98,101,114,32,105,115,32,105,110,99,111, - 114,114,101,99,116,32,111,114,32,116,104,101,32,98,121,116, - 101,99,111,100,101,32,105,115,10,32,32,32,32,102,111,117, - 110,100,32,116,111,32,98,101,32,115,116,97,108,101,46,32, - 69,79,70,69,114,114,111,114,32,105,115,32,114,97,105,115, - 101,100,32,119,104,101,110,32,116,104,101,32,100,97,116,97, - 32,105,115,32,102,111,117,110,100,32,116,111,32,98,101,10, - 32,32,32,32,116,114,117,110,99,97,116,101,100,46,10,10, - 32,32,32,32,78,114,106,0,0,0,122,10,60,98,121,116, - 101,99,111,100,101,62,114,35,0,0,0,114,12,0,0,0, - 233,8,0,0,0,233,12,0,0,0,122,30,98,97,100,32, - 109,97,103,105,99,32,110,117,109,98,101,114,32,105,110,32, - 123,33,114,125,58,32,123,33,114,125,122,43,114,101,97,99, - 104,101,100,32,69,79,70,32,119,104,105,108,101,32,114,101, - 97,100,105,110,103,32,116,105,109,101,115,116,97,109,112,32, - 105,110,32,123,33,114,125,122,48,114,101,97,99,104,101,100, - 32,69,79,70,32,119,104,105,108,101,32,114,101,97,100,105, - 110,103,32,115,105,122,101,32,111,102,32,115,111,117,114,99, - 101,32,105,110,32,123,33,114,125,218,5,109,116,105,109,101, - 122,26,98,121,116,101,99,111,100,101,32,105,115,32,115,116, - 97,108,101,32,102,111,114,32,123,33,114,125,218,4,115,105, - 122,101,108,3,0,0,0,255,127,255,127,3,0,41,9,218, - 12,77,65,71,73,67,95,78,85,77,66,69,82,114,47,0, - 0,0,114,105,0,0,0,114,107,0,0,0,114,31,0,0, - 0,218,8,69,79,70,69,114,114,111,114,114,14,0,0,0, - 218,8,75,101,121,69,114,114,111,114,114,19,0,0,0,41, - 11,114,53,0,0,0,218,12,115,111,117,114,99,101,95,115, - 116,97,116,115,114,106,0,0,0,114,35,0,0,0,90,11, - 101,120,99,95,100,101,116,97,105,108,115,90,5,109,97,103, - 105,99,90,13,114,97,119,95,116,105,109,101,115,116,97,109, - 112,90,8,114,97,119,95,115,105,122,101,114,75,0,0,0, - 218,12,115,111,117,114,99,101,95,109,116,105,109,101,218,11, - 115,111,117,114,99,101,95,115,105,122,101,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,25,95,118,97,108, - 105,100,97,116,101,95,98,121,116,101,99,111,100,101,95,104, - 101,97,100,101,114,173,1,0,0,115,76,0,0,0,0,11, - 6,1,12,1,13,3,6,1,12,1,10,1,16,1,16,1, - 16,1,12,1,18,1,10,1,18,1,18,1,15,1,10,1, - 15,1,18,1,15,1,10,1,12,1,12,1,3,1,20,1, - 13,1,5,2,18,1,15,1,10,1,15,1,3,1,18,1, - 13,1,5,2,18,1,15,1,9,1,114,146,0,0,0,99, - 4,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0, - 67,0,0,0,115,112,0,0,0,116,0,0,106,1,0,124, - 0,0,131,1,0,125,4,0,116,2,0,124,4,0,116,3, - 0,131,2,0,114,75,0,116,4,0,100,1,0,124,2,0, - 131,2,0,1,124,3,0,100,2,0,107,9,0,114,71,0, - 116,5,0,106,6,0,124,4,0,124,3,0,131,2,0,1, - 124,4,0,83,116,7,0,100,3,0,106,8,0,124,2,0, - 131,1,0,100,4,0,124,1,0,100,5,0,124,2,0,131, - 1,2,130,1,0,100,2,0,83,41,6,122,60,67,111,109, - 112,105,108,101,32,98,121,116,101,99,111,100,101,32,97,115, - 32,114,101,116,117,114,110,101,100,32,98,121,32,95,118,97, - 108,105,100,97,116,101,95,98,121,116,101,99,111,100,101,95, - 104,101,97,100,101,114,40,41,46,122,21,99,111,100,101,32, - 111,98,106,101,99,116,32,102,114,111,109,32,123,33,114,125, - 78,122,23,78,111,110,45,99,111,100,101,32,111,98,106,101, - 99,116,32,105,110,32,123,33,114,125,114,106,0,0,0,114, - 35,0,0,0,41,9,218,7,109,97,114,115,104,97,108,90, - 5,108,111,97,100,115,218,10,105,115,105,110,115,116,97,110, - 99,101,218,10,95,99,111,100,101,95,116,121,112,101,114,105, - 0,0,0,218,4,95,105,109,112,90,16,95,102,105,120,95, - 99,111,95,102,105,108,101,110,97,109,101,114,107,0,0,0, - 114,47,0,0,0,41,5,114,53,0,0,0,114,106,0,0, - 0,114,89,0,0,0,114,90,0,0,0,218,4,99,111,100, - 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,17,95,99,111,109,112,105,108,101,95,98,121,116,101,99, - 111,100,101,228,1,0,0,115,16,0,0,0,0,2,15,1, - 15,1,13,1,12,1,16,1,4,2,18,1,114,152,0,0, - 0,114,59,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,76,0,0,0, - 116,0,0,116,1,0,131,1,0,125,3,0,124,3,0,106, - 2,0,116,3,0,124,1,0,131,1,0,131,1,0,1,124, - 3,0,106,2,0,116,3,0,124,2,0,131,1,0,131,1, - 0,1,124,3,0,106,2,0,116,4,0,106,5,0,124,0, - 0,131,1,0,131,1,0,1,124,3,0,83,41,1,122,80, - 67,111,109,112,105,108,101,32,97,32,99,111,100,101,32,111, - 98,106,101,99,116,32,105,110,116,111,32,98,121,116,101,99, - 111,100,101,32,102,111,114,32,119,114,105,116,105,110,103,32, - 111,117,116,32,116,111,32,97,32,98,121,116,101,45,99,111, - 109,112,105,108,101,100,10,32,32,32,32,102,105,108,101,46, - 41,6,218,9,98,121,116,101,97,114,114,97,121,114,140,0, - 0,0,218,6,101,120,116,101,110,100,114,17,0,0,0,114, - 147,0,0,0,90,5,100,117,109,112,115,41,4,114,151,0, - 0,0,114,138,0,0,0,114,145,0,0,0,114,53,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,17,95,99,111,100,101,95,116,111,95,98,121,116,101,99, - 111,100,101,240,1,0,0,115,10,0,0,0,0,3,12,1, - 19,1,19,1,22,1,114,155,0,0,0,99,1,0,0,0, - 0,0,0,0,5,0,0,0,4,0,0,0,67,0,0,0, - 115,89,0,0,0,100,1,0,100,2,0,108,0,0,125,1, - 0,116,1,0,106,2,0,124,0,0,131,1,0,106,3,0, - 125,2,0,124,1,0,106,4,0,124,2,0,131,1,0,125, - 3,0,116,1,0,106,5,0,100,2,0,100,3,0,131,2, - 0,125,4,0,124,4,0,106,6,0,124,0,0,106,6,0, - 124,3,0,100,1,0,25,131,1,0,131,1,0,83,41,4, - 122,121,68,101,99,111,100,101,32,98,121,116,101,115,32,114, - 101,112,114,101,115,101,110,116,105,110,103,32,115,111,117,114, - 99,101,32,99,111,100,101,32,97,110,100,32,114,101,116,117, - 114,110,32,116,104,101,32,115,116,114,105,110,103,46,10,10, - 32,32,32,32,85,110,105,118,101,114,115,97,108,32,110,101, - 119,108,105,110,101,32,115,117,112,112,111,114,116,32,105,115, - 32,117,115,101,100,32,105,110,32,116,104,101,32,100,101,99, - 111,100,105,110,103,46,10,32,32,32,32,114,59,0,0,0, - 78,84,41,7,218,8,116,111,107,101,110,105,122,101,114,49, - 0,0,0,90,7,66,121,116,101,115,73,79,90,8,114,101, - 97,100,108,105,110,101,90,15,100,101,116,101,99,116,95,101, - 110,99,111,100,105,110,103,90,25,73,110,99,114,101,109,101, - 110,116,97,108,78,101,119,108,105,110,101,68,101,99,111,100, - 101,114,218,6,100,101,99,111,100,101,41,5,218,12,115,111, - 117,114,99,101,95,98,121,116,101,115,114,156,0,0,0,90, - 21,115,111,117,114,99,101,95,98,121,116,101,115,95,114,101, - 97,100,108,105,110,101,218,8,101,110,99,111,100,105,110,103, - 90,15,110,101,119,108,105,110,101,95,100,101,99,111,100,101, - 114,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,13,100,101,99,111,100,101,95,115,111,117,114,99,101,250, - 1,0,0,115,10,0,0,0,0,5,12,1,18,1,15,1, - 18,1,114,160,0,0,0,218,6,111,114,105,103,105,110,218, - 10,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, - 2,0,0,0,5,0,0,0,15,0,0,0,67,0,0,0, - 115,193,0,0,0,116,0,0,124,1,0,100,1,0,131,2, - 0,114,83,0,124,3,0,100,2,0,107,8,0,114,43,0, - 116,1,0,124,0,0,100,3,0,124,1,0,131,1,1,83, - 124,3,0,114,55,0,103,0,0,110,3,0,100,2,0,125, - 4,0,116,1,0,124,0,0,100,3,0,124,1,0,100,4, - 0,124,4,0,131,1,2,83,124,3,0,100,2,0,107,8, - 0,114,165,0,116,0,0,124,1,0,100,5,0,131,2,0, - 114,159,0,121,19,0,124,1,0,106,2,0,124,0,0,131, - 1,0,125,3,0,87,113,165,0,4,116,3,0,107,10,0, - 114,155,0,1,1,1,100,2,0,125,3,0,89,113,165,0, - 88,110,6,0,100,6,0,125,3,0,116,4,0,106,5,0, - 124,0,0,124,1,0,100,7,0,124,2,0,100,5,0,124, - 3,0,131,2,2,83,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,218, - 12,103,101,116,95,102,105,108,101,110,97,109,101,78,114,127, - 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,114, - 162,0,0,0,70,114,161,0,0,0,41,6,114,115,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,162,0,0,0,114, - 107,0,0,0,114,121,0,0,0,218,10,77,111,100,117,108, - 101,83,112,101,99,41,5,114,106,0,0,0,114,127,0,0, - 0,114,161,0,0,0,114,162,0,0,0,90,6,115,101,97, - 114,99,104,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,131,0,0,0,8,2,0,0,115,28,0,0,0, - 0,2,15,1,12,1,16,1,18,1,15,1,7,2,12,1, - 15,1,3,1,19,1,13,1,14,3,6,2,114,131,0,0, - 0,114,127,0,0,0,114,164,0,0,0,99,2,0,0,0, - 2,0,0,0,9,0,0,0,19,0,0,0,67,0,0,0, - 115,89,1,0,0,124,1,0,100,1,0,107,8,0,114,73, - 0,100,2,0,125,1,0,116,0,0,124,2,0,100,3,0, - 131,2,0,114,73,0,121,19,0,124,2,0,106,1,0,124, - 0,0,131,1,0,125,1,0,87,110,18,0,4,116,2,0, - 107,10,0,114,72,0,1,1,1,89,110,1,0,88,116,3, - 0,106,4,0,124,0,0,124,2,0,100,4,0,124,1,0, - 131,2,1,125,4,0,100,5,0,124,4,0,95,5,0,124, - 2,0,100,1,0,107,8,0,114,194,0,120,73,0,116,6, - 0,131,0,0,68,93,58,0,92,2,0,125,5,0,125,6, - 0,124,1,0,106,7,0,116,8,0,124,6,0,131,1,0, - 131,1,0,114,128,0,124,5,0,124,0,0,124,1,0,131, - 2,0,125,2,0,124,2,0,124,4,0,95,9,0,80,113, - 128,0,87,100,1,0,83,124,3,0,116,10,0,107,8,0, - 114,23,1,116,0,0,124,2,0,100,6,0,131,2,0,114, - 32,1,121,19,0,124,2,0,106,11,0,124,0,0,131,1, - 0,125,7,0,87,110,18,0,4,116,2,0,107,10,0,114, - 4,1,1,1,1,89,113,32,1,88,124,7,0,114,32,1, - 103,0,0,124,4,0,95,12,0,110,9,0,124,3,0,124, - 4,0,95,12,0,124,4,0,106,12,0,103,0,0,107,2, - 0,114,85,1,124,1,0,114,85,1,116,13,0,124,1,0, - 131,1,0,100,7,0,25,125,8,0,124,4,0,106,12,0, - 106,14,0,124,8,0,131,1,0,1,124,4,0,83,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,114,163, - 0,0,0,114,161,0,0,0,84,114,162,0,0,0,114,59, - 0,0,0,41,15,114,115,0,0,0,114,163,0,0,0,114, - 107,0,0,0,114,121,0,0,0,114,166,0,0,0,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,92,0,0,0,114, - 93,0,0,0,114,127,0,0,0,218,9,95,80,79,80,85, - 76,65,84,69,114,162,0,0,0,114,164,0,0,0,114,38, - 0,0,0,218,6,97,112,112,101,110,100,41,9,114,106,0, - 0,0,90,8,108,111,99,97,116,105,111,110,114,127,0,0, - 0,114,164,0,0,0,114,133,0,0,0,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,162,0,0,0,90,7,100,105,114,110,97,109, - 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,165,0,0,0,33,2,0,0,115,60,0,0,0,0,12, - 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, - 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, - 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, - 9,1,15,1,6,1,16,1,16,2,114,165,0,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, - 64,0,0,0,115,121,0,0,0,101,0,0,90,1,0,100, - 0,0,90,2,0,100,1,0,90,3,0,100,2,0,90,4, - 0,100,3,0,90,5,0,100,4,0,90,6,0,101,7,0, - 100,5,0,100,6,0,132,0,0,131,1,0,90,8,0,101, - 7,0,100,7,0,100,8,0,132,0,0,131,1,0,90,9, - 0,101,7,0,100,9,0,100,9,0,100,10,0,100,11,0, - 132,2,0,131,1,0,90,10,0,101,7,0,100,9,0,100, - 12,0,100,13,0,132,1,0,131,1,0,90,11,0,100,9, - 0,83,41,14,218,21,87,105,110,100,111,119,115,82,101,103, - 105,115,116,114,121,70,105,110,100,101,114,122,62,77,101,116, - 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, - 114,32,109,111,100,117,108,101,115,32,100,101,99,108,97,114, - 101,100,32,105,110,32,116,104,101,32,87,105,110,100,111,119, - 115,32,114,101,103,105,115,116,114,121,46,122,59,83,111,102, - 116,119,97,114,101,92,80,121,116,104,111,110,92,80,121,116, - 104,111,110,67,111,114,101,92,123,115,121,115,95,118,101,114, - 115,105,111,110,125,92,77,111,100,117,108,101,115,92,123,102, - 117,108,108,110,97,109,101,125,122,65,83,111,102,116,119,97, - 114,101,92,80,121,116,104,111,110,92,80,121,116,104,111,110, - 67,111,114,101,92,123,115,121,115,95,118,101,114,115,105,111, - 110,125,92,77,111,100,117,108,101,115,92,123,102,117,108,108, - 110,97,109,101,125,92,68,101,98,117,103,70,99,2,0,0, - 0,0,0,0,0,2,0,0,0,11,0,0,0,67,0,0, - 0,115,67,0,0,0,121,23,0,116,0,0,106,1,0,116, - 0,0,106,2,0,124,1,0,131,2,0,83,87,110,37,0, - 4,116,3,0,107,10,0,114,62,0,1,1,1,116,0,0, - 106,1,0,116,0,0,106,4,0,124,1,0,131,2,0,83, - 89,110,1,0,88,100,0,0,83,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,218,3,107,101,121,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, - 101,103,105,115,116,114,121,111,2,0,0,115,8,0,0,0, - 0,2,3,1,23,1,13,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,16,0,0,0,67, - 0,0,0,115,142,0,0,0,124,0,0,106,0,0,114,21, - 0,124,0,0,106,1,0,125,2,0,110,9,0,124,0,0, - 106,2,0,125,2,0,124,2,0,106,3,0,100,1,0,124, - 1,0,100,2,0,116,4,0,106,5,0,100,0,0,100,3, - 0,133,2,0,25,131,0,2,125,3,0,121,46,0,124,0, - 0,106,6,0,124,3,0,131,1,0,143,25,0,125,4,0, - 116,7,0,106,8,0,124,4,0,100,4,0,131,2,0,125, - 5,0,87,100,0,0,81,88,87,110,22,0,4,116,9,0, - 107,10,0,114,137,0,1,1,1,100,0,0,83,89,110,1, - 0,88,124,5,0,83,41,5,78,114,126,0,0,0,90,11, - 115,121,115,95,118,101,114,115,105,111,110,114,80,0,0,0, - 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,47,0,0,0,114,7,0,0,0, - 218,7,118,101,114,115,105,111,110,114,176,0,0,0,114,173, - 0,0,0,90,10,81,117,101,114,121,86,97,108,117,101,114, - 40,0,0,0,41,6,114,174,0,0,0,114,126,0,0,0, - 90,12,114,101,103,105,115,116,114,121,95,107,101,121,114,175, - 0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,112, - 97,116,104,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,105, - 115,116,114,121,118,2,0,0,115,22,0,0,0,0,2,9, - 1,12,2,9,1,15,1,22,1,3,1,18,1,28,1,13, - 1,9,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,14,0,0,0,67,0,0, - 0,115,155,0,0,0,124,0,0,106,0,0,124,1,0,131, - 1,0,125,4,0,124,4,0,100,0,0,107,8,0,114,31, - 0,100,0,0,83,121,14,0,116,1,0,124,4,0,131,1, - 0,1,87,110,22,0,4,116,2,0,107,10,0,114,69,0, - 1,1,1,100,0,0,83,89,110,1,0,88,120,78,0,116, - 3,0,131,0,0,68,93,67,0,92,2,0,125,5,0,125, - 6,0,124,4,0,106,4,0,116,5,0,124,6,0,131,1, - 0,131,1,0,114,80,0,116,6,0,124,1,0,124,5,0, - 124,1,0,124,4,0,131,2,0,100,1,0,124,4,0,131, - 2,1,125,7,0,124,7,0,83,113,80,0,87,100,0,0, - 83,41,2,78,114,161,0,0,0,41,7,114,182,0,0,0, - 114,39,0,0,0,114,40,0,0,0,114,167,0,0,0,114, - 92,0,0,0,114,93,0,0,0,114,131,0,0,0,41,8, - 114,174,0,0,0,114,126,0,0,0,114,35,0,0,0,218, - 6,116,97,114,103,101,116,114,181,0,0,0,114,127,0,0, - 0,114,171,0,0,0,114,133,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,9,102,105,110,100, - 95,115,112,101,99,133,2,0,0,115,24,0,0,0,0,2, - 15,1,12,1,4,1,3,1,14,1,13,1,9,1,22,1, - 21,1,21,1,9,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,3,0,0,0,67,0,0,0,115,45,0,0, - 0,124,0,0,106,0,0,124,1,0,124,2,0,131,2,0, - 125,3,0,124,3,0,100,1,0,107,9,0,114,37,0,124, - 3,0,106,1,0,83,100,1,0,83,100,1,0,83,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,184,0,0,0,114,127,0,0,0,41,4,114,174,0, - 0,0,114,126,0,0,0,114,35,0,0,0,114,133,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,11,102,105,110,100,95,109,111,100,117,108,101,148,2,0, - 0,115,8,0,0,0,0,7,18,1,12,1,7,2,122,33, - 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, - 105,110,100,101,114,46,102,105,110,100,95,109,111,100,117,108, - 101,41,12,114,112,0,0,0,114,111,0,0,0,114,113,0, - 0,0,114,114,0,0,0,114,179,0,0,0,114,178,0,0, - 0,114,177,0,0,0,218,11,99,108,97,115,115,109,101,116, - 104,111,100,114,176,0,0,0,114,182,0,0,0,114,184,0, - 0,0,114,185,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,172,0,0,0, - 99,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, - 2,6,2,18,7,18,15,3,1,21,14,3,1,114,172,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,64,0,0,0,101,0,0,90, - 1,0,100,0,0,90,2,0,100,1,0,90,3,0,100,2, - 0,100,3,0,132,0,0,90,4,0,100,4,0,100,5,0, - 132,0,0,90,5,0,100,6,0,100,7,0,132,0,0,90, - 6,0,101,7,0,90,8,0,100,8,0,83,41,9,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,3, - 0,0,0,67,0,0,0,115,88,0,0,0,116,0,0,124, - 0,0,106,1,0,124,1,0,131,1,0,131,1,0,100,1, - 0,25,125,2,0,124,2,0,106,2,0,100,2,0,100,1, - 0,131,2,0,100,3,0,25,125,3,0,124,1,0,106,3, - 0,100,2,0,131,1,0,100,4,0,25,125,4,0,124,3, - 0,100,5,0,107,2,0,111,87,0,124,4,0,100,5,0, - 107,3,0,83,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,58,0,0,0,114, - 59,0,0,0,114,56,0,0,0,218,8,95,95,105,110,105, - 116,95,95,41,4,114,38,0,0,0,114,163,0,0,0,114, - 34,0,0,0,114,32,0,0,0,41,5,114,108,0,0,0, - 114,126,0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,162,0,0,0,167,2,0,0,115,8,0,0, - 0,0,3,25,1,22,1,19,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,0, - 83,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,4,0,0,0,41,2,114,108,0,0,0,114,133,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,175, - 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,4,0,0,0,67,0,0,0,115,80,0,0,0,124, - 0,0,106,0,0,124,1,0,106,1,0,131,1,0,125,2, - 0,124,2,0,100,1,0,107,8,0,114,54,0,116,2,0, - 100,2,0,106,3,0,124,1,0,106,1,0,131,1,0,131, - 1,0,130,1,0,116,4,0,106,5,0,116,6,0,124,2, - 0,124,1,0,106,7,0,131,3,0,1,100,1,0,83,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,112,0,0,0,114,107, - 0,0,0,114,47,0,0,0,114,121,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,118, - 0,0,0,41,3,114,108,0,0,0,114,134,0,0,0,114, - 151,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,101, - 178,2,0,0,115,10,0,0,0,0,2,18,1,12,1,9, - 1,15,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,78,41, - 9,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, - 114,114,0,0,0,114,162,0,0,0,114,189,0,0,0,114, - 193,0,0,0,114,135,0,0,0,218,11,108,111,97,100,95, - 109,111,100,117,108,101,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,187,0,0,0,162, - 2,0,0,115,10,0,0,0,12,3,6,2,12,8,12,3, - 12,8,114,187,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,106,0,0, - 0,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, - 100,2,0,132,0,0,90,3,0,100,3,0,100,4,0,132, - 0,0,90,4,0,100,5,0,100,6,0,132,0,0,90,5, - 0,100,7,0,100,8,0,132,0,0,90,6,0,100,9,0, - 100,10,0,132,0,0,90,7,0,100,11,0,100,18,0,100, - 13,0,100,14,0,132,0,1,90,8,0,100,15,0,100,16, - 0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0,83,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,73,79,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,218,7,73,79,69,114,114,111, - 114,41,2,114,108,0,0,0,114,35,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,10,112,97, - 116,104,95,109,116,105,109,101,191,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,3,0,0,0,67,0,0, - 0,115,19,0,0,0,124,0,0,106,0,0,124,1,0,131, - 1,0,100,1,0,105,1,0,83,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,73,79,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,138,0,0,0,41, - 1,114,197,0,0,0,41,2,114,108,0,0,0,114,35,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,10,112,97,116,104,95,115,116,97,116,115,199,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,3,0, - 0,0,67,0,0,0,115,16,0,0,0,124,0,0,106,0, - 0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99,97,99, - 104,101,95,112,97,116,104,114,53,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,15,95,99,97, - 99,104,101,95,98,121,116,101,99,111,100,101,212,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,0,83,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,4, - 0,0,0,41,3,114,108,0,0,0,114,35,0,0,0,114, - 53,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,199,0,0,0,222,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,16,0,0,0,67,0,0,0,115,105,0, - 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, - 0,121,19,0,124,0,0,106,1,0,124,2,0,131,1,0, - 125,3,0,87,110,58,0,4,116,2,0,107,10,0,114,94, - 0,1,125,4,0,1,122,26,0,116,3,0,100,1,0,100, - 2,0,124,1,0,131,1,1,124,4,0,130,2,0,87,89, - 100,3,0,100,3,0,125,4,0,126,4,0,88,110,1,0, - 88,116,4,0,124,3,0,131,1,0,83,41,4,122,52,67, - 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,73,110,115,112,101,99, - 116,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, - 99,101,46,122,39,115,111,117,114,99,101,32,110,111,116,32, - 97,118,97,105,108,97,98,108,101,32,116,104,114,111,117,103, - 104,32,103,101,116,95,100,97,116,97,40,41,114,106,0,0, - 0,78,41,5,114,163,0,0,0,218,8,103,101,116,95,100, - 97,116,97,114,40,0,0,0,114,107,0,0,0,114,160,0, - 0,0,41,5,114,108,0,0,0,114,126,0,0,0,114,35, - 0,0,0,114,158,0,0,0,218,3,101,120,99,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,10,103,101, - 116,95,115,111,117,114,99,101,229,2,0,0,115,14,0,0, - 0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105,109, - 105,122,101,114,29,0,0,0,99,3,0,0,0,1,0,0, - 0,4,0,0,0,9,0,0,0,67,0,0,0,115,34,0, - 0,0,116,0,0,106,1,0,116,2,0,124,1,0,124,2, - 0,100,1,0,100,2,0,100,3,0,100,4,0,124,3,0, - 131,4,2,83,41,5,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,192,0,0,0,218, - 12,100,111,110,116,95,105,110,104,101,114,105,116,84,114,68, - 0,0,0,41,3,114,121,0,0,0,114,191,0,0,0,218, - 7,99,111,109,112,105,108,101,41,4,114,108,0,0,0,114, - 53,0,0,0,114,35,0,0,0,114,204,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,14,115, - 111,117,114,99,101,95,116,111,95,99,111,100,101,239,2,0, - 0,115,4,0,0,0,0,5,21,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, - 10,0,0,0,43,0,0,0,67,0,0,0,115,174,1,0, - 0,124,0,0,106,0,0,124,1,0,131,1,0,125,2,0, - 100,1,0,125,3,0,121,16,0,116,1,0,124,2,0,131, - 1,0,125,4,0,87,110,24,0,4,116,2,0,107,10,0, - 114,63,0,1,1,1,100,1,0,125,4,0,89,110,202,0, - 88,121,19,0,124,0,0,106,3,0,124,2,0,131,1,0, - 125,5,0,87,110,18,0,4,116,4,0,107,10,0,114,103, - 0,1,1,1,89,110,162,0,88,116,5,0,124,5,0,100, - 2,0,25,131,1,0,125,3,0,121,19,0,124,0,0,106, - 6,0,124,4,0,131,1,0,125,6,0,87,110,18,0,4, - 116,7,0,107,10,0,114,159,0,1,1,1,89,110,106,0, - 88,121,34,0,116,8,0,124,6,0,100,3,0,124,5,0, - 100,4,0,124,1,0,100,5,0,124,4,0,131,1,3,125, - 7,0,87,110,24,0,4,116,9,0,116,10,0,102,2,0, - 107,10,0,114,220,0,1,1,1,89,110,45,0,88,116,11, - 0,100,6,0,124,4,0,124,2,0,131,3,0,1,116,12, - 0,124,7,0,100,4,0,124,1,0,100,7,0,124,4,0, - 100,8,0,124,2,0,131,1,3,83,124,0,0,106,6,0, - 124,2,0,131,1,0,125,8,0,124,0,0,106,13,0,124, - 8,0,124,2,0,131,2,0,125,9,0,116,11,0,100,9, - 0,124,2,0,131,2,0,1,116,14,0,106,15,0,12,114, - 170,1,124,4,0,100,1,0,107,9,0,114,170,1,124,3, - 0,100,1,0,107,9,0,114,170,1,116,16,0,124,9,0, - 124,3,0,116,17,0,124,8,0,131,1,0,131,3,0,125, - 6,0,121,36,0,124,0,0,106,18,0,124,2,0,124,4, - 0,124,6,0,131,3,0,1,116,11,0,100,10,0,124,4, - 0,131,2,0,1,87,110,18,0,4,116,2,0,107,10,0, - 114,169,1,1,1,1,89,110,1,0,88,124,9,0,83,41, - 11,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,114,138,0,0,0,114,143,0,0,0,114,106,0,0, - 0,114,35,0,0,0,122,13,123,125,32,109,97,116,99,104, - 101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66,0,0, - 0,114,198,0,0,0,114,196,0,0,0,114,14,0,0,0, - 114,201,0,0,0,114,40,0,0,0,114,146,0,0,0,114, - 107,0,0,0,114,141,0,0,0,114,105,0,0,0,114,152, - 0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200,0,0, - 0,41,10,114,108,0,0,0,114,126,0,0,0,114,90,0, - 0,0,114,144,0,0,0,114,89,0,0,0,218,2,115,116, - 114,53,0,0,0,218,10,98,121,116,101,115,95,100,97,116, - 97,114,158,0,0,0,90,11,99,111,100,101,95,111,98,106, - 101,99,116,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,190,0,0,0,247,2,0,0,115,78,0,0,0, - 0,7,15,1,6,1,3,1,16,1,13,1,11,2,3,1, - 19,1,13,1,5,2,16,1,3,1,19,1,13,1,5,2, - 3,1,9,1,12,1,13,1,19,1,5,2,9,1,7,1, - 15,1,6,1,7,1,15,1,18,1,13,1,22,1,12,1, - 9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112,0, - 0,0,114,111,0,0,0,114,113,0,0,0,114,197,0,0, - 0,114,198,0,0,0,114,200,0,0,0,114,199,0,0,0, - 114,203,0,0,0,114,207,0,0,0,114,190,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,195,0,0,0,189,2,0,0,115,14,0,0, - 0,12,2,12,8,12,13,12,10,12,7,12,10,18,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,112,0,0,0,101,0, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,148, + 2,0,0,115,8,0,0,0,0,7,18,1,12,1,7,2, + 122,33,87,105,110,100,111,119,115,82,101,103,105,115,116,114, + 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, + 117,108,101,41,12,114,112,0,0,0,114,111,0,0,0,114, + 113,0,0,0,114,114,0,0,0,114,179,0,0,0,114,178, + 0,0,0,114,177,0,0,0,218,11,99,108,97,115,115,109, + 101,116,104,111,100,114,176,0,0,0,114,182,0,0,0,114, + 184,0,0,0,114,185,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,172,0, + 0,0,99,2,0,0,115,20,0,0,0,12,2,6,3,6, + 3,6,2,6,2,18,7,18,15,3,1,21,14,3,1,114, + 172,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,64,0,0,0,101,0, 0,90,1,0,100,0,0,90,2,0,100,1,0,90,3,0, 100,2,0,100,3,0,132,0,0,90,4,0,100,4,0,100, 5,0,132,0,0,90,5,0,100,6,0,100,7,0,132,0, - 0,90,6,0,101,7,0,135,0,0,102,1,0,100,8,0, - 100,9,0,134,0,0,131,1,0,90,8,0,101,7,0,100, - 10,0,100,11,0,132,0,0,131,1,0,90,9,0,100,12, - 0,100,13,0,132,0,0,90,10,0,135,0,0,83,41,14, - 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,22,0,0,0,124, - 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, - 0,100,1,0,83,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,106,0,0,0,114,35,0,0, - 0,41,3,114,108,0,0,0,114,126,0,0,0,114,35,0, + 0,90,6,0,101,7,0,90,8,0,100,8,0,83,41,9, + 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,3,0,0,0,67,0,0,0,115,88,0,0,0,116,0, + 0,124,0,0,106,1,0,124,1,0,131,1,0,131,1,0, + 100,1,0,25,125,2,0,124,2,0,106,2,0,100,2,0, + 100,1,0,131,2,0,100,3,0,25,125,3,0,124,1,0, + 106,3,0,100,2,0,131,1,0,100,4,0,25,125,4,0, + 124,3,0,100,5,0,107,2,0,111,87,0,124,4,0,100, + 5,0,107,3,0,83,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,58,0,0, + 0,114,59,0,0,0,114,56,0,0,0,218,8,95,95,105, + 110,105,116,95,95,41,4,114,38,0,0,0,114,163,0,0, + 0,114,34,0,0,0,114,32,0,0,0,41,5,114,108,0, + 0,0,114,126,0,0,0,114,94,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,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,162,0,0,0,167,2,0,0,115,8, + 0,0,0,0,3,25,1,22,1,19,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0,114,133, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,13,99,114,101,97,116,101,95,109,111,100,117,108, + 101,175,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,4,0,0,0,67,0,0,0,115,80,0,0, + 0,124,0,0,106,0,0,124,1,0,106,1,0,131,1,0, + 125,2,0,124,2,0,100,1,0,107,8,0,114,54,0,116, + 2,0,100,2,0,106,3,0,124,1,0,106,1,0,131,1, + 0,131,1,0,130,1,0,116,4,0,106,5,0,116,6,0, + 124,2,0,124,1,0,106,7,0,131,3,0,1,100,1,0, + 83,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,112,0,0,0, + 114,107,0,0,0,114,47,0,0,0,114,121,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,118,0,0,0,41,3,114,108,0,0,0,114,134,0,0, + 0,114,151,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,11,101,120,101,99,95,109,111,100,117, + 108,101,178,2,0,0,115,10,0,0,0,0,2,18,1,12, + 1,9,1,15,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, + 78,41,9,114,112,0,0,0,114,111,0,0,0,114,113,0, + 0,0,114,114,0,0,0,114,162,0,0,0,114,189,0,0, + 0,114,193,0,0,0,114,135,0,0,0,218,11,108,111,97, + 100,95,109,111,100,117,108,101,114,4,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,187,0,0, + 0,162,2,0,0,115,10,0,0,0,12,3,6,2,12,8, + 12,3,12,8,114,187,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,106, + 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, + 1,0,100,2,0,132,0,0,90,3,0,100,3,0,100,4, + 0,132,0,0,90,4,0,100,5,0,100,6,0,132,0,0, + 90,5,0,100,7,0,100,8,0,132,0,0,90,6,0,100, + 9,0,100,10,0,132,0,0,90,7,0,100,11,0,100,18, + 0,100,13,0,100,14,0,132,0,1,90,8,0,100,15,0, + 100,16,0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0, + 83,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,73,79,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,218,7,73,79,69,114, + 114,111,114,41,2,114,108,0,0,0,114,35,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,10, + 112,97,116,104,95,109,116,105,109,101,191,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,3,0,0,0,67, + 0,0,0,115,19,0,0,0,124,0,0,106,0,0,124,1, + 0,131,1,0,100,1,0,105,1,0,83,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,73,79,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,138,0,0, + 0,41,1,114,197,0,0,0,41,2,114,108,0,0,0,114, + 35,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,10,112,97,116,104,95,115,116,97,116,115,199, + 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, + 3,0,0,0,67,0,0,0,115,16,0,0,0,124,0,0, + 106,0,0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99, + 97,99,104,101,95,112,97,116,104,114,53,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,15,95, + 99,97,99,104,101,95,98,121,116,101,99,111,100,101,212,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,0,83,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,4,0,0,0,41,3,114,108,0,0,0,114,35,0,0, + 0,114,53,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,199,0,0,0,222,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,16,0,0,0,67,0,0,0,115, + 105,0,0,0,124,0,0,106,0,0,124,1,0,131,1,0, + 125,2,0,121,19,0,124,0,0,106,1,0,124,2,0,131, + 1,0,125,3,0,87,110,58,0,4,116,2,0,107,10,0, + 114,94,0,1,125,4,0,1,122,26,0,116,3,0,100,1, + 0,100,2,0,124,1,0,131,1,1,124,4,0,130,2,0, + 87,89,100,3,0,100,3,0,125,4,0,126,4,0,88,110, + 1,0,88,116,4,0,124,3,0,131,1,0,83,41,4,122, + 52,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,73,110,115,112, + 101,99,116,76,111,97,100,101,114,46,103,101,116,95,115,111, + 117,114,99,101,46,122,39,115,111,117,114,99,101,32,110,111, + 116,32,97,118,97,105,108,97,98,108,101,32,116,104,114,111, + 117,103,104,32,103,101,116,95,100,97,116,97,40,41,114,106, + 0,0,0,78,41,5,114,163,0,0,0,218,8,103,101,116, + 95,100,97,116,97,114,40,0,0,0,114,107,0,0,0,114, + 160,0,0,0,41,5,114,108,0,0,0,114,126,0,0,0, + 114,35,0,0,0,114,158,0,0,0,218,3,101,120,99,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,10, + 103,101,116,95,115,111,117,114,99,101,229,2,0,0,115,14, + 0,0,0,0,2,15,1,3,1,19,1,18,1,9,1,31, + 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,218,9,95,111,112,116, + 105,109,105,122,101,114,29,0,0,0,99,3,0,0,0,1, + 0,0,0,4,0,0,0,9,0,0,0,67,0,0,0,115, + 34,0,0,0,116,0,0,106,1,0,116,2,0,124,1,0, + 124,2,0,100,1,0,100,2,0,100,3,0,100,4,0,124, + 3,0,131,4,2,83,41,5,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,192,0,0, + 0,218,12,100,111,110,116,95,105,110,104,101,114,105,116,84, + 114,68,0,0,0,41,3,114,121,0,0,0,114,191,0,0, + 0,218,7,99,111,109,112,105,108,101,41,4,114,108,0,0, + 0,114,53,0,0,0,114,35,0,0,0,114,204,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 14,115,111,117,114,99,101,95,116,111,95,99,111,100,101,239, + 2,0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174, + 1,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, + 2,0,100,1,0,125,3,0,121,16,0,116,1,0,124,2, + 0,131,1,0,125,4,0,87,110,24,0,4,116,2,0,107, + 10,0,114,63,0,1,1,1,100,1,0,125,4,0,89,110, + 202,0,88,121,19,0,124,0,0,106,3,0,124,2,0,131, + 1,0,125,5,0,87,110,18,0,4,116,4,0,107,10,0, + 114,103,0,1,1,1,89,110,162,0,88,116,5,0,124,5, + 0,100,2,0,25,131,1,0,125,3,0,121,19,0,124,0, + 0,106,6,0,124,4,0,131,1,0,125,6,0,87,110,18, + 0,4,116,7,0,107,10,0,114,159,0,1,1,1,89,110, + 106,0,88,121,34,0,116,8,0,124,6,0,100,3,0,124, + 5,0,100,4,0,124,1,0,100,5,0,124,4,0,131,1, + 3,125,7,0,87,110,24,0,4,116,9,0,116,10,0,102, + 2,0,107,10,0,114,220,0,1,1,1,89,110,45,0,88, + 116,11,0,100,6,0,124,4,0,124,2,0,131,3,0,1, + 116,12,0,124,7,0,100,4,0,124,1,0,100,7,0,124, + 4,0,100,8,0,124,2,0,131,1,3,83,124,0,0,106, + 6,0,124,2,0,131,1,0,125,8,0,124,0,0,106,13, + 0,124,8,0,124,2,0,131,2,0,125,9,0,116,11,0, + 100,9,0,124,2,0,131,2,0,1,116,14,0,106,15,0, + 12,114,170,1,124,4,0,100,1,0,107,9,0,114,170,1, + 124,3,0,100,1,0,107,9,0,114,170,1,116,16,0,124, + 9,0,124,3,0,116,17,0,124,8,0,131,1,0,131,3, + 0,125,6,0,121,36,0,124,0,0,106,18,0,124,2,0, + 124,4,0,124,6,0,131,3,0,1,116,11,0,100,10,0, + 124,4,0,131,2,0,1,87,110,18,0,4,116,2,0,107, + 10,0,114,169,1,1,1,1,89,110,1,0,88,124,9,0, + 83,41,11,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,114,138,0,0,0,114,143,0,0,0,114,106, + 0,0,0,114,35,0,0,0,122,13,123,125,32,109,97,116, + 99,104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66, + 0,0,0,114,198,0,0,0,114,196,0,0,0,114,14,0, + 0,0,114,201,0,0,0,114,40,0,0,0,114,146,0,0, + 0,114,107,0,0,0,114,141,0,0,0,114,105,0,0,0, + 114,152,0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200, + 0,0,0,41,10,114,108,0,0,0,114,126,0,0,0,114, + 90,0,0,0,114,144,0,0,0,114,89,0,0,0,218,2, + 115,116,114,53,0,0,0,218,10,98,121,116,101,115,95,100, + 97,116,97,114,158,0,0,0,90,11,99,111,100,101,95,111, + 98,106,101,99,116,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,190,0,0,0,247,2,0,0,115,78,0, + 0,0,0,7,15,1,6,1,3,1,16,1,13,1,11,2, + 3,1,19,1,13,1,5,2,16,1,3,1,19,1,13,1, + 5,2,3,1,9,1,12,1,13,1,19,1,5,2,9,1, + 7,1,15,1,6,1,7,1,15,1,18,1,13,1,22,1, + 12,1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,197, + 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, + 0,0,114,203,0,0,0,114,207,0,0,0,114,190,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,195,0,0,0,189,2,0,0,115,14, + 0,0,0,12,2,12,8,12,13,12,10,12,7,12,10,18, + 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,112,0,0,0, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, + 132,0,0,90,6,0,101,7,0,135,0,0,102,1,0,100, + 8,0,100,9,0,134,0,0,131,1,0,90,8,0,101,7, + 0,100,10,0,100,11,0,132,0,0,131,1,0,90,9,0, + 100,12,0,100,13,0,132,0,0,90,10,0,135,0,0,83, + 41,14,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,22,0,0, + 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, + 95,1,0,100,1,0,83,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,106,0,0,0,114,35, + 0,0,0,41,3,114,108,0,0,0,114,126,0,0,0,114, + 35,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,188,0,0,0,48,3,0,0,115,4,0,0, + 0,0,3,9,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, + 34,0,0,0,124,0,0,106,0,0,124,1,0,106,0,0, + 107,2,0,111,33,0,124,0,0,106,1,0,124,1,0,106, + 1,0,107,2,0,83,41,1,78,41,2,218,9,95,95,99, + 108,97,115,115,95,95,114,118,0,0,0,41,2,114,108,0, + 0,0,218,5,111,116,104,101,114,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,6,95,95,101,113,95,95, + 54,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0, + 106,1,0,131,1,0,116,0,0,124,0,0,106,2,0,131, + 1,0,65,83,41,1,78,41,3,218,4,104,97,115,104,114, + 106,0,0,0,114,35,0,0,0,41,1,114,108,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 8,95,95,104,97,115,104,95,95,58,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,22, + 0,0,0,116,0,0,116,1,0,124,0,0,131,2,0,106, + 2,0,124,1,0,131,1,0,83,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,211,0,0,0,114, + 194,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, + 41,1,114,212,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,194,0,0,0,61,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,7, + 0,0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,163,0,0,0,73, + 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,42,0,0,0,116,0,0, + 106,1,0,124,1,0,100,1,0,131,2,0,143,17,0,125, + 2,0,124,2,0,106,2,0,131,0,0,83,87,100,2,0, + 81,82,88,100,2,0,83,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,49,0,0,0,114,50,0, + 0,0,90,4,114,101,97,100,41,3,114,108,0,0,0,114, + 35,0,0,0,114,54,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,201,0,0,0,78,3,0, + 0,115,4,0,0,0,0,2,21,1,122,19,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41, + 11,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, + 114,114,0,0,0,114,188,0,0,0,114,214,0,0,0,114, + 216,0,0,0,114,123,0,0,0,114,194,0,0,0,114,163, + 0,0,0,114,201,0,0,0,114,4,0,0,0,114,4,0, + 0,0,41,1,114,212,0,0,0,114,5,0,0,0,114,211, + 0,0,0,43,3,0,0,115,14,0,0,0,12,3,6,2, + 12,6,12,4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100, + 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, + 0,132,0,0,90,4,0,100,4,0,100,5,0,132,0,0, + 90,5,0,100,6,0,100,7,0,100,8,0,100,9,0,132, + 0,1,90,6,0,100,10,0,83,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,5,0,0,0,67,0, + 0,0,115,34,0,0,0,116,0,0,124,1,0,131,1,0, + 125,2,0,124,2,0,106,1,0,100,1,0,124,2,0,106, + 2,0,100,2,0,105,2,0,83,41,3,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,114,138, + 0,0,0,114,139,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,108,0,0,0,114,35,0,0,0,114,209, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,198,0,0,0,88,3,0,0,115,4,0,0,0, + 0,2,12,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,34,0,0,0,116,0,0,124,1, + 0,131,1,0,125,4,0,124,0,0,106,1,0,124,2,0, + 124,3,0,100,1,0,124,4,0,131,2,1,83,41,2,78, + 218,5,95,109,111,100,101,41,2,114,97,0,0,0,114,199, + 0,0,0,41,5,114,108,0,0,0,114,90,0,0,0,114, + 89,0,0,0,114,53,0,0,0,114,42,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,200,0, + 0,0,93,3,0,0,115,4,0,0,0,0,2,12,1,122, + 32,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, + 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, + 101,114,221,0,0,0,105,182,1,0,0,99,3,0,0,0, + 1,0,0,0,9,0,0,0,17,0,0,0,67,0,0,0, + 115,53,1,0,0,116,0,0,124,1,0,131,1,0,92,2, + 0,125,4,0,125,5,0,103,0,0,125,6,0,120,54,0, + 124,4,0,114,80,0,116,1,0,124,4,0,131,1,0,12, + 114,80,0,116,0,0,124,4,0,131,1,0,92,2,0,125, + 4,0,125,7,0,124,6,0,106,2,0,124,7,0,131,1, + 0,1,113,27,0,87,120,132,0,116,3,0,124,6,0,131, + 1,0,68,93,118,0,125,7,0,116,4,0,124,4,0,124, + 7,0,131,2,0,125,4,0,121,17,0,116,5,0,106,6, + 0,124,4,0,131,1,0,1,87,113,94,0,4,116,7,0, + 107,10,0,114,155,0,1,1,1,119,94,0,89,113,94,0, + 4,116,8,0,107,10,0,114,211,0,1,125,8,0,1,122, + 25,0,116,9,0,100,1,0,124,4,0,124,8,0,131,3, + 0,1,100,2,0,83,87,89,100,2,0,100,2,0,125,8, + 0,126,8,0,88,113,94,0,88,113,94,0,87,121,33,0, + 116,10,0,124,1,0,124,2,0,124,3,0,131,3,0,1, + 116,9,0,100,3,0,124,1,0,131,2,0,1,87,110,53, + 0,4,116,8,0,107,10,0,114,48,1,1,125,8,0,1, + 122,21,0,116,9,0,100,1,0,124,1,0,124,8,0,131, + 3,0,1,87,89,100,2,0,100,2,0,125,8,0,126,8, + 0,88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0, + 0,114,169,0,0,0,114,33,0,0,0,114,28,0,0,0, + 114,3,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,105,0,0,0,114,55,0,0,0,41,9,114,108, + 0,0,0,114,35,0,0,0,114,53,0,0,0,114,221,0, + 0,0,218,6,112,97,114,101,110,116,114,94,0,0,0,114, + 27,0,0,0,114,23,0,0,0,114,202,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,199,0, + 0,0,98,3,0,0,115,38,0,0,0,0,2,18,1,6, + 2,22,1,18,1,17,2,19,1,15,1,3,1,17,1,13, + 2,7,1,18,3,16,1,27,1,3,1,16,1,17,1,18, + 2,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, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, + 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,219,0,0,0,84,3,0,0,115, + 8,0,0,0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1, + 0,100,0,0,90,2,0,100,1,0,90,3,0,100,2,0, + 100,3,0,132,0,0,90,4,0,100,4,0,100,5,0,132, + 0,0,90,5,0,100,6,0,83,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,6,0,0, + 0,67,0,0,0,115,76,0,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,125,2,0,124,0,0,106,1,0,124, + 2,0,131,1,0,125,3,0,116,2,0,124,3,0,100,1, + 0,124,1,0,100,2,0,124,2,0,131,1,2,125,4,0, + 116,3,0,124,4,0,100,1,0,124,1,0,100,3,0,124, + 2,0,131,1,2,83,41,4,78,114,106,0,0,0,114,35, + 0,0,0,114,89,0,0,0,41,4,114,163,0,0,0,114, + 201,0,0,0,114,146,0,0,0,114,152,0,0,0,41,5, + 114,108,0,0,0,114,126,0,0,0,114,35,0,0,0,114, + 53,0,0,0,114,210,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,190,0,0,0,131,3,0, + 0,115,8,0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108, + 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,203,0,0,0,137,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,112,0,0,0, + 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, + 190,0,0,0,114,203,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,224,0, + 0,0,127,3,0,0,115,6,0,0,0,12,2,6,2,12, + 6,114,224,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,130,0,0,0, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, + 132,0,0,90,6,0,101,7,0,100,8,0,100,9,0,132, + 0,0,131,1,0,90,8,0,100,10,0,100,11,0,132,0, + 0,90,9,0,100,12,0,100,13,0,132,0,0,90,10,0, + 100,14,0,100,15,0,132,0,0,90,11,0,101,7,0,100, + 16,0,100,17,0,132,0,0,131,1,0,90,12,0,100,18, + 0,83,41,19,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,22,0, + 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, + 0,95,1,0,100,0,0,83,41,1,78,41,2,114,106,0, + 0,0,114,35,0,0,0,41,3,114,108,0,0,0,114,106, + 0,0,0,114,35,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,188,0,0,0,154,3,0,0, + 115,4,0,0,0,0,1,9,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,34,0,0, + 0,124,0,0,106,0,0,124,1,0,106,0,0,107,2,0, + 111,33,0,124,0,0,106,1,0,124,1,0,106,1,0,107, + 2,0,83,41,1,78,41,2,114,212,0,0,0,114,118,0, + 0,0,41,2,114,108,0,0,0,114,213,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,214,0, + 0,0,158,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1,0,131,1, + 0,116,0,0,124,0,0,106,2,0,131,1,0,65,83,41, + 1,78,41,3,114,215,0,0,0,114,106,0,0,0,114,35, + 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,216,0,0,0,162,3, + 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, + 4,0,0,0,11,0,0,0,67,0,0,0,115,184,0,0, + 0,116,0,0,106,1,0,124,1,0,131,1,0,143,32,0, + 1,116,0,0,106,2,0,116,3,0,106,4,0,124,1,0, + 124,0,0,106,5,0,131,3,0,125,2,0,87,100,1,0, + 81,82,88,116,6,0,100,2,0,124,0,0,106,5,0,131, + 2,0,1,124,0,0,106,7,0,124,1,0,131,1,0,125, + 3,0,124,3,0,114,128,0,116,8,0,124,2,0,100,3, + 0,131,2,0,12,114,128,0,116,9,0,124,0,0,106,5, + 0,131,1,0,100,4,0,25,103,1,0,124,2,0,95,10, + 0,124,0,0,124,2,0,95,11,0,124,2,0,106,12,0, + 124,2,0,95,13,0,124,3,0,115,180,0,124,2,0,106, + 13,0,106,14,0,100,5,0,131,1,0,100,4,0,25,124, + 2,0,95,13,0,124,2,0,83,41,6,122,25,76,111,97, + 100,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,46,78,122,33,101,120,116,101,110,115,105, + 111,110,32,109,111,100,117,108,101,32,108,111,97,100,101,100, + 32,102,114,111,109,32,123,33,114,125,218,8,95,95,112,97, + 116,104,95,95,114,59,0,0,0,114,58,0,0,0,41,15, + 114,121,0,0,0,90,13,95,77,97,110,97,103,101,82,101, + 108,111,97,100,114,191,0,0,0,114,150,0,0,0,90,12, + 108,111,97,100,95,100,121,110,97,109,105,99,114,35,0,0, + 0,114,105,0,0,0,114,162,0,0,0,114,115,0,0,0, + 114,38,0,0,0,114,226,0,0,0,218,10,95,95,108,111, + 97,100,101,114,95,95,114,112,0,0,0,218,11,95,95,112, + 97,99,107,97,103,101,95,95,114,32,0,0,0,41,4,114, + 108,0,0,0,114,126,0,0,0,114,134,0,0,0,114,162, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,194,0,0,0,165,3,0,0,115,24,0,0,0, + 0,5,16,1,12,1,22,1,16,1,15,1,22,1,25,1, + 9,1,12,1,6,1,25,1,122,31,69,120,116,101,110,115, + 105,111,110,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,4,0,0,0,3,0,0,0,115,48, + 0,0,0,116,0,0,124,0,0,106,1,0,131,1,0,100, + 1,0,25,137,0,0,116,2,0,135,0,0,102,1,0,100, + 2,0,100,3,0,134,0,0,116,3,0,68,131,1,0,131, + 1,0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0, + 136,0,0,100,0,0,124,1,0,23,107,2,0,86,1,113, + 3,0,100,1,0,83,41,2,114,188,0,0,0,78,114,4, + 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, + 4,0,0,0,114,5,0,0,0,250,9,60,103,101,110,101, + 120,112,114,62,186,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126, + 0,0,0,114,4,0,0,0,41,1,114,230,0,0,0,114, + 5,0,0,0,114,162,0,0,0,183,3,0,0,115,6,0, + 0,0,0,2,19,1,18,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,0,83,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,4,0,0,0,41, + 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,190,0,0,0,189, + 3,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0,114,126,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,203,0,0,0,193,3,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,7,0,0,0,124,0,0,106,0,0, + 83,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,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,188,0,0,0,48,3,0,0,115,4,0,0,0,0, - 3,9,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,34,0, - 0,0,124,0,0,106,0,0,124,1,0,106,0,0,107,2, - 0,111,33,0,124,0,0,106,1,0,124,1,0,106,1,0, - 107,2,0,83,41,1,78,41,2,218,9,95,95,99,108,97, - 115,115,95,95,114,118,0,0,0,41,2,114,108,0,0,0, - 218,5,111,116,104,101,114,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,6,95,95,101,113,95,95,54,3, - 0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1, - 0,131,1,0,116,0,0,124,0,0,106,2,0,131,1,0, - 65,83,41,1,78,41,3,218,4,104,97,115,104,114,106,0, - 0,0,114,35,0,0,0,41,1,114,108,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,95, - 95,104,97,115,104,95,95,58,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,22,0,0, - 0,116,0,0,116,1,0,124,0,0,131,2,0,106,2,0, - 124,1,0,131,1,0,83,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,211,0,0,0,114,194,0, - 0,0,41,2,114,108,0,0,0,114,126,0,0,0,41,1, - 114,212,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 194,0,0,0,61,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,7,0,0, - 0,124,0,0,106,0,0,83,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, - 108,0,0,0,114,126,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,163,0,0,0,73,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,8,0, - 0,0,67,0,0,0,115,41,0,0,0,116,0,0,106,1, - 0,124,1,0,100,1,0,131,2,0,143,17,0,125,2,0, - 124,2,0,106,2,0,131,0,0,83,87,100,2,0,81,88, - 100,2,0,83,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,49,0,0,0,114,50,0,0,0,90, - 4,114,101,97,100,41,3,114,108,0,0,0,114,35,0,0, - 0,114,54,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,201,0,0,0,78,3,0,0,115,4, - 0,0,0,0,2,21,1,122,19,70,105,108,101,76,111,97, - 100,101,114,46,103,101,116,95,100,97,116,97,41,11,114,112, - 0,0,0,114,111,0,0,0,114,113,0,0,0,114,114,0, - 0,0,114,188,0,0,0,114,214,0,0,0,114,216,0,0, - 0,114,123,0,0,0,114,194,0,0,0,114,163,0,0,0, - 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,41, - 1,114,212,0,0,0,114,5,0,0,0,114,211,0,0,0, - 43,3,0,0,115,14,0,0,0,12,3,6,2,12,6,12, - 4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100,0,0,90, - 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, - 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, - 100,6,0,100,7,0,100,8,0,100,9,0,132,0,1,90, - 6,0,100,10,0,83,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,5,0,0,0,67,0,0,0,115, - 34,0,0,0,116,0,0,124,1,0,131,1,0,125,2,0, - 124,2,0,106,1,0,100,1,0,124,2,0,106,2,0,100, - 2,0,105,2,0,83,41,3,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,114,138,0,0,0, - 114,139,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,108,0,0,0,114,35,0,0,0,114,209,0,0,0, + 0,114,163,0,0,0,197,3,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,13,114,112,0,0,0,114,111,0,0,0, + 114,113,0,0,0,114,114,0,0,0,114,188,0,0,0,114, + 214,0,0,0,114,216,0,0,0,114,123,0,0,0,114,194, + 0,0,0,114,162,0,0,0,114,190,0,0,0,114,203,0, + 0,0,114,163,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,225,0,0,0, + 146,3,0,0,115,18,0,0,0,12,6,6,2,12,4,12, + 4,12,3,18,18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,100, + 3,0,132,0,0,90,4,0,100,4,0,100,5,0,132,0, + 0,90,5,0,100,6,0,100,7,0,132,0,0,90,6,0, + 100,8,0,100,9,0,132,0,0,90,7,0,100,10,0,100, + 11,0,132,0,0,90,8,0,100,12,0,100,13,0,132,0, + 0,90,9,0,100,14,0,100,15,0,132,0,0,90,10,0, + 100,16,0,100,17,0,132,0,0,90,11,0,100,18,0,100, + 19,0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52, + 0,0,0,124,1,0,124,0,0,95,0,0,124,2,0,124, + 0,0,95,1,0,116,2,0,124,0,0,106,3,0,131,0, + 0,131,1,0,124,0,0,95,4,0,124,3,0,124,0,0, + 95,5,0,100,0,0,83,41,1,78,41,6,218,5,95,110, + 97,109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35, + 0,0,0,218,11,112,97,116,104,95,102,105,110,100,101,114, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 198,0,0,0,88,3,0,0,115,4,0,0,0,0,2,12, - 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,34,0,0,0,116,0,0,124,1,0,131,1, - 0,125,4,0,124,0,0,106,1,0,124,2,0,124,3,0, - 100,1,0,124,4,0,131,2,1,83,41,2,78,218,5,95, - 109,111,100,101,41,2,114,97,0,0,0,114,199,0,0,0, - 41,5,114,108,0,0,0,114,90,0,0,0,114,89,0,0, - 0,114,53,0,0,0,114,42,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,200,0,0,0,93, - 3,0,0,115,4,0,0,0,0,2,12,1,122,32,83,111, - 117,114,99,101,70,105,108,101,76,111,97,100,101,114,46,95, - 99,97,99,104,101,95,98,121,116,101,99,111,100,101,114,221, - 0,0,0,105,182,1,0,0,99,3,0,0,0,1,0,0, - 0,9,0,0,0,17,0,0,0,67,0,0,0,115,53,1, - 0,0,116,0,0,124,1,0,131,1,0,92,2,0,125,4, - 0,125,5,0,103,0,0,125,6,0,120,54,0,124,4,0, - 114,80,0,116,1,0,124,4,0,131,1,0,12,114,80,0, - 116,0,0,124,4,0,131,1,0,92,2,0,125,4,0,125, - 7,0,124,6,0,106,2,0,124,7,0,131,1,0,1,113, - 27,0,87,120,132,0,116,3,0,124,6,0,131,1,0,68, - 93,118,0,125,7,0,116,4,0,124,4,0,124,7,0,131, - 2,0,125,4,0,121,17,0,116,5,0,106,6,0,124,4, - 0,131,1,0,1,87,113,94,0,4,116,7,0,107,10,0, - 114,155,0,1,1,1,119,94,0,89,113,94,0,4,116,8, - 0,107,10,0,114,211,0,1,125,8,0,1,122,25,0,116, - 9,0,100,1,0,124,4,0,124,8,0,131,3,0,1,100, - 2,0,83,87,89,100,2,0,100,2,0,125,8,0,126,8, - 0,88,113,94,0,88,113,94,0,87,121,33,0,116,10,0, - 124,1,0,124,2,0,124,3,0,131,3,0,1,116,9,0, - 100,3,0,124,1,0,131,2,0,1,87,110,53,0,4,116, - 8,0,107,10,0,114,48,1,1,125,8,0,1,122,21,0, - 116,9,0,100,1,0,124,1,0,124,8,0,131,3,0,1, - 87,89,100,2,0,100,2,0,125,8,0,126,8,0,88,110, - 1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0,0,114,169, - 0,0,0,114,33,0,0,0,114,28,0,0,0,114,3,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, - 105,0,0,0,114,55,0,0,0,41,9,114,108,0,0,0, - 114,35,0,0,0,114,53,0,0,0,114,221,0,0,0,218, - 6,112,97,114,101,110,116,114,94,0,0,0,114,27,0,0, - 0,114,23,0,0,0,114,202,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,199,0,0,0,98, - 3,0,0,115,38,0,0,0,0,2,18,1,6,2,22,1, - 18,1,17,2,19,1,15,1,3,1,17,1,13,2,7,1, - 18,3,16,1,27,1,3,1,16,1,17,1,18,2,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,112,0,0, - 0,114,111,0,0,0,114,113,0,0,0,114,114,0,0,0, - 114,198,0,0,0,114,200,0,0,0,114,199,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,219,0,0,0,84,3,0,0,115,8,0,0, - 0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1,0,100,0, - 0,90,2,0,100,1,0,90,3,0,100,2,0,100,3,0, - 132,0,0,90,4,0,100,4,0,100,5,0,132,0,0,90, - 5,0,100,6,0,83,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,6,0,0,0,67,0, - 0,0,115,76,0,0,0,124,0,0,106,0,0,124,1,0, - 131,1,0,125,2,0,124,0,0,106,1,0,124,2,0,131, - 1,0,125,3,0,116,2,0,124,3,0,100,1,0,124,1, - 0,100,2,0,124,2,0,131,1,2,125,4,0,116,3,0, - 124,4,0,100,1,0,124,1,0,100,3,0,124,2,0,131, - 1,2,83,41,4,78,114,106,0,0,0,114,35,0,0,0, - 114,89,0,0,0,41,4,114,163,0,0,0,114,201,0,0, - 0,114,146,0,0,0,114,152,0,0,0,41,5,114,108,0, - 0,0,114,126,0,0,0,114,35,0,0,0,114,53,0,0, - 0,114,210,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,190,0,0,0,131,3,0,0,115,8, - 0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0, - 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,203,0,0,0,137,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,112,0,0,0,114,111,0, - 0,0,114,113,0,0,0,114,114,0,0,0,114,190,0,0, - 0,114,203,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,224,0,0,0,127, - 3,0,0,115,6,0,0,0,12,2,6,2,12,6,114,224, - 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,130,0,0,0,101,0,0, - 90,1,0,100,0,0,90,2,0,100,1,0,90,3,0,100, - 2,0,100,3,0,132,0,0,90,4,0,100,4,0,100,5, - 0,132,0,0,90,5,0,100,6,0,100,7,0,132,0,0, - 90,6,0,101,7,0,100,8,0,100,9,0,132,0,0,131, - 1,0,90,8,0,100,10,0,100,11,0,132,0,0,90,9, - 0,100,12,0,100,13,0,132,0,0,90,10,0,100,14,0, - 100,15,0,132,0,0,90,11,0,101,7,0,100,16,0,100, - 17,0,132,0,0,131,1,0,90,12,0,100,18,0,83,41, - 19,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,22,0,0,0,124, - 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, - 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, - 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, - 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,188,0,0,0,154,3,0,0,115,4,0, - 0,0,0,1,9,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,34,0,0,0,124,0, - 0,106,0,0,124,1,0,106,0,0,107,2,0,111,33,0, - 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, - 41,1,78,41,2,114,212,0,0,0,114,118,0,0,0,41, - 2,114,108,0,0,0,114,213,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,214,0,0,0,158, - 3,0,0,115,4,0,0,0,0,1,18,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,26,0, - 0,0,116,0,0,124,0,0,106,1,0,131,1,0,116,0, - 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, - 3,114,215,0,0,0,114,106,0,0,0,114,35,0,0,0, + 188,0,0,0,210,3,0,0,115,8,0,0,0,0,1,9, + 1,9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1, + 0,100,1,0,131,1,0,92,3,0,125,1,0,125,2,0, + 125,3,0,124,2,0,100,2,0,107,2,0,114,43,0,100, + 6,0,83,124,1,0,100,5,0,102,2,0,83,41,7,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, + 58,0,0,0,114,30,0,0,0,114,7,0,0,0,114,35, + 0,0,0,114,226,0,0,0,41,2,122,3,115,121,115,122, + 4,112,97,116,104,41,2,114,235,0,0,0,114,32,0,0, + 0,41,4,114,108,0,0,0,114,223,0,0,0,218,3,100, + 111,116,90,2,109,101,114,4,0,0,0,114,4,0,0,0, + 114,5,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,216,3, + 0,0,115,8,0,0,0,0,2,27,1,12,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,38,0,0, + 0,124,0,0,106,0,0,131,0,0,92,2,0,125,1,0, + 125,2,0,116,1,0,116,2,0,106,3,0,124,1,0,25, + 124,2,0,131,2,0,83,41,1,78,41,4,114,242,0,0, + 0,114,117,0,0,0,114,7,0,0,0,114,132,0,0,0, + 41,3,114,108,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,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,237,0,0,0,226, + 3,0,0,115,4,0,0,0,0,1,18,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,3,0,0,0,67,0, + 0,0,115,118,0,0,0,116,0,0,124,0,0,106,1,0, + 131,0,0,131,1,0,125,1,0,124,1,0,124,0,0,106, + 2,0,107,3,0,114,111,0,124,0,0,106,3,0,124,0, + 0,106,4,0,124,1,0,131,2,0,125,2,0,124,2,0, + 100,0,0,107,9,0,114,102,0,124,2,0,106,5,0,100, + 0,0,107,8,0,114,102,0,124,2,0,106,6,0,114,102, + 0,124,2,0,106,6,0,124,0,0,95,7,0,124,1,0, + 124,0,0,95,2,0,124,0,0,106,7,0,83,41,1,78, + 41,8,114,93,0,0,0,114,237,0,0,0,114,238,0,0, + 0,114,239,0,0,0,114,235,0,0,0,114,127,0,0,0, + 114,164,0,0,0,114,236,0,0,0,41,3,114,108,0,0, + 0,90,11,112,97,114,101,110,116,95,112,97,116,104,114,133, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,12,95,114,101,99,97,108,99,117,108,97,116,101, + 230,3,0,0,115,16,0,0,0,0,2,18,1,15,1,21, + 3,27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16,0,0,0, + 116,0,0,124,0,0,106,1,0,131,0,0,131,1,0,83, + 41,1,78,41,2,218,4,105,116,101,114,114,243,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,216,0,0,0,162,3,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,4,0,0, - 0,11,0,0,0,67,0,0,0,115,183,0,0,0,116,0, - 0,106,1,0,124,1,0,131,1,0,143,32,0,1,116,0, - 0,106,2,0,116,3,0,106,4,0,124,1,0,124,0,0, - 106,5,0,131,3,0,125,2,0,87,100,1,0,81,88,116, - 6,0,100,2,0,124,0,0,106,5,0,131,2,0,1,124, - 0,0,106,7,0,124,1,0,131,1,0,125,3,0,124,3, - 0,114,127,0,116,8,0,124,2,0,100,3,0,131,2,0, - 12,114,127,0,116,9,0,124,0,0,106,5,0,131,1,0, - 100,4,0,25,103,1,0,124,2,0,95,10,0,124,0,0, - 124,2,0,95,11,0,124,2,0,106,12,0,124,2,0,95, - 13,0,124,3,0,115,179,0,124,2,0,106,13,0,106,14, - 0,100,5,0,131,1,0,100,4,0,25,124,2,0,95,13, - 0,124,2,0,83,41,6,122,25,76,111,97,100,32,97,110, - 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,46,78,122,33,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,32,108,111,97,100,101,100,32,102,114,111, - 109,32,123,33,114,125,218,8,95,95,112,97,116,104,95,95, - 114,59,0,0,0,114,58,0,0,0,41,15,114,121,0,0, - 0,90,13,95,77,97,110,97,103,101,82,101,108,111,97,100, - 114,191,0,0,0,114,150,0,0,0,90,12,108,111,97,100, - 95,100,121,110,97,109,105,99,114,35,0,0,0,114,105,0, - 0,0,114,162,0,0,0,114,115,0,0,0,114,38,0,0, - 0,114,226,0,0,0,218,10,95,95,108,111,97,100,101,114, - 95,95,114,112,0,0,0,218,11,95,95,112,97,99,107,97, - 103,101,95,95,114,32,0,0,0,41,4,114,108,0,0,0, - 114,126,0,0,0,114,134,0,0,0,114,162,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,194, - 0,0,0,165,3,0,0,115,24,0,0,0,0,5,16,1, - 12,1,21,1,16,1,15,1,22,1,25,1,9,1,12,1, - 6,1,25,1,122,31,69,120,116,101,110,115,105,111,110,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,4,0,0,0,3,0,0,0,115,48,0,0,0,116, - 0,0,124,0,0,106,1,0,131,1,0,100,1,0,25,137, - 0,0,116,2,0,135,0,0,102,1,0,100,2,0,100,3, - 0,134,0,0,116,3,0,68,131,1,0,131,1,0,83,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,31, - 0,0,0,124,0,0,93,21,0,125,1,0,136,0,0,100, - 0,0,124,1,0,23,107,2,0,86,1,113,3,0,100,1, - 0,83,41,2,114,188,0,0,0,78,114,4,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,4,0,0,0, - 114,5,0,0,0,250,9,60,103,101,110,101,120,112,114,62, - 186,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0,0,0,114, - 4,0,0,0,41,1,114,230,0,0,0,114,5,0,0,0, - 114,162,0,0,0,183,3,0,0,115,6,0,0,0,0,2, - 19,1,18,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, + 0,114,5,0,0,0,218,8,95,95,105,116,101,114,95,95, + 243,3,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,1,0,0,0,0,0,0,0,1,0,0, + 0,2,0,0,0,67,0,0,0,115,16,0,0,0,116,0, + 0,124,0,0,106,1,0,131,0,0,131,1,0,83,41,1, + 78,41,2,114,31,0,0,0,114,243,0,0,0,41,1,114, + 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,7,95,95,108,101,110,95,95,246,3,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,2,0,0,0, + 67,0,0,0,115,16,0,0,0,100,1,0,106,0,0,124, + 0,0,106,1,0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1, + 114,108,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,8,95,95,114,101,112,114,95,95,249,3, + 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,2, + 0,0,0,67,0,0,0,115,16,0,0,0,124,1,0,124, + 0,0,106,0,0,131,0,0,107,6,0,83,41,1,78,41, + 1,114,243,0,0,0,41,2,114,108,0,0,0,218,4,105, + 116,101,109,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,12,95,95,99,111,110,116,97,105,110,115,95,95, + 252,3,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,2,0,0,0,67,0,0,0,115,20,0, + 0,0,124,0,0,106,0,0,106,1,0,124,1,0,131,1, + 0,1,100,0,0,83,41,1,78,41,2,114,236,0,0,0, + 114,169,0,0,0,41,2,114,108,0,0,0,114,248,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,169,0,0,0,255,3,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,13,114,112,0,0,0,114, + 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,188, + 0,0,0,114,242,0,0,0,114,237,0,0,0,114,243,0, + 0,0,114,245,0,0,0,114,246,0,0,0,114,247,0,0, + 0,114,249,0,0,0,114,169,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 234,0,0,0,203,3,0,0,115,20,0,0,0,12,5,6, + 2,12,6,12,10,12,4,12,13,12,3,12,3,12,3,12, + 3,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,118,0,0,0, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,100, + 2,0,132,0,0,90,3,0,101,4,0,100,3,0,100,4, + 0,132,0,0,131,1,0,90,5,0,100,5,0,100,6,0, + 132,0,0,90,6,0,100,7,0,100,8,0,132,0,0,90, + 7,0,100,9,0,100,10,0,132,0,0,90,8,0,100,11, + 0,100,12,0,132,0,0,90,9,0,100,13,0,100,14,0, + 132,0,0,90,10,0,100,15,0,100,16,0,132,0,0,90, + 11,0,100,17,0,83,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, + 25,0,0,0,116,0,0,124,1,0,124,2,0,124,3,0, + 131,3,0,124,0,0,95,1,0,100,0,0,83,41,1,78, + 41,2,114,234,0,0,0,114,236,0,0,0,41,4,114,108, + 0,0,0,114,106,0,0,0,114,35,0,0,0,114,240,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,188,0,0,0,5,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,2,0,0,0,67,0,0, + 0,115,16,0,0,0,100,1,0,106,0,0,124,1,0,106, + 1,0,131,1,0,83,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,47,0,0,0,114, + 112,0,0,0,41,2,114,174,0,0,0,114,134,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 11,109,111,100,117,108,101,95,114,101,112,114,8,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,0,83,41,2,78,84,114,4,0,0,0,41,2,114,108, + 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,162,0,0,0,17,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, - 0,83,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,4,0,0,0,41,2,114,108,0, + 0,83,41,2,78,114,30,0,0,0,114,4,0,0,0,41, + 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,203,0,0,0,20, + 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,22,0,0, + 0,116,0,0,100,1,0,100,2,0,100,3,0,100,4,0, + 100,5,0,131,3,1,83,41,6,78,114,30,0,0,0,122, + 8,60,115,116,114,105,110,103,62,114,192,0,0,0,114,205, + 0,0,0,84,41,1,114,206,0,0,0,41,2,114,108,0, 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,190,0,0,0,189,3,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, - 0,83,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,4,0,0, + 0,114,5,0,0,0,114,190,0,0,0,23,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,0,83,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,4, + 0,0,0,41,2,114,108,0,0,0,114,133,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,189, + 0,0,0,26,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,0,83,41,1,78,114,4,0, + 0,0,41,2,114,108,0,0,0,114,134,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,193,0, + 0,0,29,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,3,0,0,0,67,0,0,0, + 115,29,0,0,0,116,0,0,100,1,0,124,0,0,106,1, + 0,131,2,0,1,116,2,0,124,0,0,124,1,0,131,2, + 0,83,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,3,114,105,0,0,0,114,236,0,0,0,114,135,0,0, 0,41,2,114,108,0,0,0,114,126,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,203,0,0, - 0,193,3,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,7,0,0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,163,0, - 0,0,197,3,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,13,114,112,0,0,0,114,111,0,0,0,114,113,0,0, - 0,114,114,0,0,0,114,188,0,0,0,114,214,0,0,0, - 114,216,0,0,0,114,123,0,0,0,114,194,0,0,0,114, - 162,0,0,0,114,190,0,0,0,114,203,0,0,0,114,163, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,225,0,0,0,146,3,0,0, - 115,18,0,0,0,12,6,6,2,12,4,12,4,12,3,18, - 18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0,100,0,0,90, - 2,0,100,1,0,90,3,0,100,2,0,100,3,0,132,0, - 0,90,4,0,100,4,0,100,5,0,132,0,0,90,5,0, - 100,6,0,100,7,0,132,0,0,90,6,0,100,8,0,100, - 9,0,132,0,0,90,7,0,100,10,0,100,11,0,132,0, - 0,90,8,0,100,12,0,100,13,0,132,0,0,90,9,0, - 100,14,0,100,15,0,132,0,0,90,10,0,100,16,0,100, - 17,0,132,0,0,90,11,0,100,18,0,100,19,0,132,0, - 0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0,0,0,124, - 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, - 0,116,2,0,124,0,0,106,3,0,131,0,0,131,1,0, - 124,0,0,95,4,0,124,3,0,124,0,0,95,5,0,100, - 0,0,83,41,1,78,41,6,218,5,95,110,97,109,101,218, - 5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0,0,0,218, - 11,112,97,116,104,95,102,105,110,100,101,114,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,188,0,0,0, - 210,3,0,0,115,8,0,0,0,0,1,9,1,9,1,21, - 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, - 53,0,0,0,124,0,0,106,0,0,106,1,0,100,1,0, - 131,1,0,92,3,0,125,1,0,125,2,0,125,3,0,124, - 2,0,100,2,0,107,2,0,114,43,0,100,6,0,83,124, - 1,0,100,5,0,102,2,0,83,41,7,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,58,0,0,0, - 114,30,0,0,0,114,7,0,0,0,114,35,0,0,0,114, - 226,0,0,0,41,2,122,3,115,121,115,122,4,112,97,116, - 104,41,2,114,235,0,0,0,114,32,0,0,0,41,4,114, - 108,0,0,0,114,223,0,0,0,218,3,100,111,116,90,2, - 109,101,114,4,0,0,0,114,4,0,0,0,114,5,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,216,3,0,0,115,8, - 0,0,0,0,2,27,1,12,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,38,0,0,0,124,0,0, - 106,0,0,131,0,0,92,2,0,125,1,0,125,2,0,116, - 1,0,116,2,0,106,3,0,124,1,0,25,124,2,0,131, - 2,0,83,41,1,78,41,4,114,242,0,0,0,114,117,0, - 0,0,114,7,0,0,0,114,132,0,0,0,41,3,114,108, - 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,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,237,0,0,0,226,3,0,0,115, - 4,0,0,0,0,1,18,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,3,0,0,0,67,0,0,0,115,118, - 0,0,0,116,0,0,124,0,0,106,1,0,131,0,0,131, - 1,0,125,1,0,124,1,0,124,0,0,106,2,0,107,3, - 0,114,111,0,124,0,0,106,3,0,124,0,0,106,4,0, - 124,1,0,131,2,0,125,2,0,124,2,0,100,0,0,107, - 9,0,114,102,0,124,2,0,106,5,0,100,0,0,107,8, - 0,114,102,0,124,2,0,106,6,0,114,102,0,124,2,0, - 106,6,0,124,0,0,95,7,0,124,1,0,124,0,0,95, - 2,0,124,0,0,106,7,0,83,41,1,78,41,8,114,93, - 0,0,0,114,237,0,0,0,114,238,0,0,0,114,239,0, - 0,0,114,235,0,0,0,114,127,0,0,0,114,164,0,0, - 0,114,236,0,0,0,41,3,114,108,0,0,0,90,11,112, - 97,114,101,110,116,95,112,97,116,104,114,133,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, - 95,114,101,99,97,108,99,117,108,97,116,101,230,3,0,0, - 115,16,0,0,0,0,2,18,1,15,1,21,3,27,1,9, - 1,12,1,9,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,2, - 0,0,0,67,0,0,0,115,16,0,0,0,116,0,0,124, - 0,0,106,1,0,131,0,0,131,1,0,83,41,1,78,41, - 2,218,4,105,116,101,114,114,243,0,0,0,41,1,114,108, + 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, + 0,32,4,0,0,115,4,0,0,0,0,7,16,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, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,188, + 0,0,0,114,186,0,0,0,114,251,0,0,0,114,162,0, + 0,0,114,203,0,0,0,114,190,0,0,0,114,189,0,0, + 0,114,193,0,0,0,114,194,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 250,0,0,0,4,4,0,0,115,16,0,0,0,12,1,12, + 3,18,9,12,3,12,3,12,3,12,3,12,3,114,250,0, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,64,0,0,0,115,160,0,0,0,101,0,0,90, + 1,0,100,0,0,90,2,0,100,1,0,90,3,0,101,4, + 0,100,2,0,100,3,0,132,0,0,131,1,0,90,5,0, + 101,4,0,100,4,0,100,5,0,132,0,0,131,1,0,90, + 6,0,101,4,0,100,6,0,100,7,0,132,0,0,131,1, + 0,90,7,0,101,4,0,100,8,0,100,9,0,132,0,0, + 131,1,0,90,8,0,101,4,0,100,10,0,100,11,0,100, + 12,0,132,1,0,131,1,0,90,9,0,101,4,0,100,10, + 0,100,10,0,100,13,0,100,14,0,132,2,0,131,1,0, + 90,10,0,101,4,0,100,10,0,100,15,0,100,16,0,132, + 1,0,131,1,0,90,11,0,100,10,0,83,41,17,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, + 55,0,0,0,120,48,0,116,0,0,106,1,0,106,2,0, + 131,0,0,68,93,31,0,125,1,0,116,3,0,124,1,0, + 100,1,0,131,2,0,114,16,0,124,1,0,106,4,0,131, + 0,0,1,113,16,0,87,100,2,0,83,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,7,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,115,0,0,0,114,253,0,0,0,41,2, + 114,174,0,0,0,218,6,102,105,110,100,101,114,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,253,0,0, + 0,49,4,0,0,115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67, + 0,0,0,115,107,0,0,0,116,0,0,106,1,0,100,1, + 0,107,9,0,114,41,0,116,0,0,106,1,0,12,114,41, + 0,116,2,0,106,3,0,100,2,0,116,4,0,131,2,0, + 1,120,59,0,116,0,0,106,1,0,68,93,44,0,125,2, + 0,121,14,0,124,2,0,124,1,0,131,1,0,83,87,113, + 51,0,4,116,5,0,107,10,0,114,94,0,1,1,1,119, + 51,0,89,113,51,0,88,113,51,0,87,100,1,0,83,100, + 1,0,83,41,3,122,113,83,101,97,114,99,104,32,115,101, + 113,117,101,110,99,101,32,111,102,32,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,10,10,32,32,32,32,32,32, + 32,32,73,102,32,39,104,111,111,107,115,39,32,105,115,32, + 102,97,108,115,101,32,116,104,101,110,32,117,115,101,32,115, + 121,115,46,112,97,116,104,95,104,111,111,107,115,46,10,10, + 32,32,32,32,32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95, + 104,111,111,107,115,114,60,0,0,0,114,61,0,0,0,114, + 125,0,0,0,114,107,0,0,0,41,3,114,174,0,0,0, + 114,35,0,0,0,90,4,104,111,111,107,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,11,95,112,97,116, + 104,95,104,111,111,107,115,57,4,0,0,115,16,0,0,0, + 0,7,25,1,16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0, + 0,0,124,1,0,100,1,0,107,2,0,114,53,0,121,16, + 0,116,0,0,106,1,0,131,0,0,125,1,0,87,110,22, + 0,4,116,2,0,107,10,0,114,52,0,1,1,1,100,2, + 0,83,89,110,1,0,88,121,17,0,116,3,0,106,4,0, + 124,1,0,25,125,2,0,87,110,46,0,4,116,5,0,107, + 10,0,114,118,0,1,1,1,124,0,0,106,6,0,124,1, + 0,131,1,0,125,2,0,124,2,0,116,3,0,106,4,0, + 124,1,0,60,89,110,1,0,88,124,2,0,83,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,3,0,0,0, + 114,45,0,0,0,218,17,70,105,108,101,78,111,116,70,111, + 117,110,100,69,114,114,111,114,114,7,0,0,0,114,254,0, + 0,0,114,142,0,0,0,114,2,1,0,0,41,3,114,174, + 0,0,0,114,35,0,0,0,114,0,1,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,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,74,4,0,0,115,22,0,0,0,0,8,12,1,3, + 1,16,1,13,3,9,1,3,1,17,1,13,1,15,1,18, + 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,3, + 0,0,0,67,0,0,0,115,116,0,0,0,116,0,0,124, + 2,0,100,1,0,131,2,0,114,39,0,124,2,0,106,1, + 0,124,1,0,131,1,0,92,2,0,125,3,0,125,4,0, + 110,21,0,124,2,0,106,2,0,124,1,0,131,1,0,125, + 3,0,103,0,0,125,4,0,124,3,0,100,0,0,107,9, + 0,114,85,0,116,3,0,124,1,0,124,3,0,131,2,0, + 83,116,4,0,106,5,0,124,1,0,100,0,0,131,2,0, + 125,5,0,124,4,0,124,5,0,95,6,0,124,5,0,83, + 41,2,78,114,124,0,0,0,41,7,114,115,0,0,0,114, + 124,0,0,0,114,185,0,0,0,114,131,0,0,0,114,121, + 0,0,0,114,166,0,0,0,114,164,0,0,0,41,6,114, + 174,0,0,0,114,126,0,0,0,114,0,1,0,0,114,127, + 0,0,0,114,128,0,0,0,114,133,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,16,95,108, + 101,103,97,99,121,95,103,101,116,95,115,112,101,99,96,4, + 0,0,115,18,0,0,0,0,4,15,1,24,2,15,1,6, + 1,12,1,13,1,18,1,9,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,243,0,0, + 0,103,0,0,125,4,0,120,230,0,124,2,0,68,93,191, + 0,125,5,0,116,0,0,124,5,0,116,1,0,116,2,0, + 102,2,0,131,2,0,115,43,0,113,13,0,124,0,0,106, + 3,0,124,5,0,131,1,0,125,6,0,124,6,0,100,1, + 0,107,9,0,114,13,0,116,4,0,124,6,0,100,2,0, + 131,2,0,114,106,0,124,6,0,106,5,0,124,1,0,124, + 3,0,131,2,0,125,7,0,110,18,0,124,0,0,106,6, + 0,124,1,0,124,6,0,131,2,0,125,7,0,124,7,0, + 100,1,0,107,8,0,114,139,0,113,13,0,124,7,0,106, + 7,0,100,1,0,107,9,0,114,158,0,124,7,0,83,124, + 7,0,106,8,0,125,8,0,124,8,0,100,1,0,107,8, + 0,114,191,0,116,9,0,100,3,0,131,1,0,130,1,0, + 124,4,0,106,10,0,124,8,0,131,1,0,1,113,13,0, + 87,116,11,0,106,12,0,124,1,0,100,1,0,131,2,0, + 125,7,0,124,4,0,124,7,0,95,8,0,124,7,0,83, + 100,1,0,83,41,4,122,63,70,105,110,100,32,116,104,101, + 32,108,111,97,100,101,114,32,111,114,32,110,97,109,101,115, + 112,97,99,101,95,112,97,116,104,32,102,111,114,32,116,104, + 105,115,32,109,111,100,117,108,101,47,112,97,99,107,97,103, + 101,32,110,97,109,101,46,78,114,184,0,0,0,122,19,115, + 112,101,99,32,109,105,115,115,105,110,103,32,108,111,97,100, + 101,114,41,13,114,148,0,0,0,114,69,0,0,0,218,5, + 98,121,116,101,115,114,4,1,0,0,114,115,0,0,0,114, + 184,0,0,0,114,5,1,0,0,114,127,0,0,0,114,164, + 0,0,0,114,107,0,0,0,114,154,0,0,0,114,121,0, + 0,0,114,166,0,0,0,41,9,114,174,0,0,0,114,126, + 0,0,0,114,35,0,0,0,114,183,0,0,0,218,14,110, + 97,109,101,115,112,97,99,101,95,112,97,116,104,90,5,101, + 110,116,114,121,114,0,1,0,0,114,133,0,0,0,114,128, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,8,95,95,105,116,101,114,95,95,243,3,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,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0, - 0,67,0,0,0,115,16,0,0,0,116,0,0,124,0,0, - 106,1,0,131,0,0,131,1,0,83,41,1,78,41,2,114, - 31,0,0,0,114,243,0,0,0,41,1,114,108,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 7,95,95,108,101,110,95,95,246,3,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,2,0,0,0,67,0,0,0, - 115,16,0,0,0,100,1,0,106,0,0,124,0,0,106,1, - 0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1,114,108,0,0, + 0,0,218,9,95,103,101,116,95,115,112,101,99,111,4,0, + 0,115,40,0,0,0,0,5,6,1,13,1,21,1,3,1, + 15,1,12,1,15,1,21,2,18,1,12,1,3,1,15,1, + 4,1,9,1,12,1,12,5,17,2,18,1,9,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,4,0,0,0,67,0,0,0,115,140,0,0,0,124,2, + 0,100,1,0,107,8,0,114,21,0,116,0,0,106,1,0, + 125,2,0,124,0,0,106,2,0,124,1,0,124,2,0,124, + 3,0,131,3,0,125,4,0,124,4,0,100,1,0,107,8, + 0,114,58,0,100,1,0,83,124,4,0,106,3,0,100,1, + 0,107,8,0,114,132,0,124,4,0,106,4,0,125,5,0, + 124,5,0,114,125,0,100,2,0,124,4,0,95,5,0,116, + 6,0,124,1,0,124,5,0,124,0,0,106,2,0,131,3, + 0,124,4,0,95,4,0,124,4,0,83,100,1,0,83,110, + 4,0,124,4,0,83,100,1,0,83,41,3,122,98,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, + 78,90,9,110,97,109,101,115,112,97,99,101,41,7,114,7, + 0,0,0,114,35,0,0,0,114,8,1,0,0,114,127,0, + 0,0,114,164,0,0,0,114,161,0,0,0,114,234,0,0, + 0,41,6,114,174,0,0,0,114,126,0,0,0,114,35,0, + 0,0,114,183,0,0,0,114,133,0,0,0,114,7,1,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,8,95,95,114,101,112,114,95,95,249,3,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,2,0,0,0,67, - 0,0,0,115,16,0,0,0,124,1,0,124,0,0,106,0, - 0,131,0,0,107,6,0,83,41,1,78,41,1,114,243,0, - 0,0,41,2,114,108,0,0,0,218,4,105,116,101,109,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, - 95,95,99,111,110,116,97,105,110,115,95,95,252,3,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,2,0,0,0,67,0,0,0,115,20,0,0,0,124,0, - 0,106,0,0,106,1,0,124,1,0,131,1,0,1,100,0, - 0,83,41,1,78,41,2,114,236,0,0,0,114,169,0,0, - 0,41,2,114,108,0,0,0,114,248,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,169,0,0, - 0,255,3,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,13,114,112,0,0,0,114,111,0,0,0, - 114,113,0,0,0,114,114,0,0,0,114,188,0,0,0,114, - 242,0,0,0,114,237,0,0,0,114,243,0,0,0,114,245, - 0,0,0,114,246,0,0,0,114,247,0,0,0,114,249,0, - 0,0,114,169,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,234,0,0,0, - 203,3,0,0,115,20,0,0,0,12,5,6,2,12,6,12, - 10,12,4,12,13,12,3,12,3,12,3,12,3,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,118,0,0,0,101,0,0,90, - 1,0,100,0,0,90,2,0,100,1,0,100,2,0,132,0, - 0,90,3,0,101,4,0,100,3,0,100,4,0,132,0,0, - 131,1,0,90,5,0,100,5,0,100,6,0,132,0,0,90, - 6,0,100,7,0,100,8,0,132,0,0,90,7,0,100,9, - 0,100,10,0,132,0,0,90,8,0,100,11,0,100,12,0, - 132,0,0,90,9,0,100,13,0,100,14,0,132,0,0,90, - 10,0,100,15,0,100,16,0,132,0,0,90,11,0,100,17, - 0,83,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,25,0,0,0, - 116,0,0,124,1,0,124,2,0,124,3,0,131,3,0,124, - 0,0,95,1,0,100,0,0,83,41,1,78,41,2,114,234, - 0,0,0,114,236,0,0,0,41,4,114,108,0,0,0,114, - 106,0,0,0,114,35,0,0,0,114,240,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,188,0, - 0,0,5,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,2,0,0,0,67,0,0,0,115,16,0, - 0,0,100,1,0,106,0,0,124,1,0,106,1,0,131,1, - 0,83,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,47,0,0,0,114,112,0,0,0, - 41,2,114,174,0,0,0,114,134,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,11,109,111,100, - 117,108,101,95,114,101,112,114,8,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,0,83,41, - 2,78,84,114,4,0,0,0,41,2,114,108,0,0,0,114, - 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,162,0,0,0,17,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,0,83,41,2, - 78,114,30,0,0,0,114,4,0,0,0,41,2,114,108,0, - 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,203,0,0,0,20,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,22,0,0,0,116,0,0, - 100,1,0,100,2,0,100,3,0,100,4,0,100,5,0,131, - 3,1,83,41,6,78,114,30,0,0,0,122,8,60,115,116, - 114,105,110,103,62,114,192,0,0,0,114,205,0,0,0,84, - 41,1,114,206,0,0,0,41,2,114,108,0,0,0,114,126, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,190,0,0,0,23,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,0,83,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,4,0,0,0,41, - 2,114,108,0,0,0,114,133,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,189,0,0,0,26, - 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,0,83,41,1,78,114,4,0,0,0,41,2, - 114,108,0,0,0,114,134,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,193,0,0,0,29,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,3,0,0,0,67,0,0,0,115,29,0,0, - 0,116,0,0,100,1,0,124,0,0,106,1,0,131,2,0, - 1,116,2,0,124,0,0,124,1,0,131,2,0,83,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,3,114,105, - 0,0,0,114,236,0,0,0,114,135,0,0,0,41,2,114, - 108,0,0,0,114,126,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,194,0,0,0,32,4,0, - 0,115,4,0,0,0,0,7,16,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,112,0,0,0, - 114,111,0,0,0,114,113,0,0,0,114,188,0,0,0,114, - 186,0,0,0,114,251,0,0,0,114,162,0,0,0,114,203, - 0,0,0,114,190,0,0,0,114,189,0,0,0,114,193,0, - 0,0,114,194,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,250,0,0,0, - 4,4,0,0,115,16,0,0,0,12,1,12,3,18,9,12, - 3,12,3,12,3,12,3,12,3,114,250,0,0,0,99,0, - 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,64, - 0,0,0,115,160,0,0,0,101,0,0,90,1,0,100,0, - 0,90,2,0,100,1,0,90,3,0,101,4,0,100,2,0, - 100,3,0,132,0,0,131,1,0,90,5,0,101,4,0,100, - 4,0,100,5,0,132,0,0,131,1,0,90,6,0,101,4, - 0,100,6,0,100,7,0,132,0,0,131,1,0,90,7,0, - 101,4,0,100,8,0,100,9,0,132,0,0,131,1,0,90, - 8,0,101,4,0,100,10,0,100,11,0,100,12,0,132,1, - 0,131,1,0,90,9,0,101,4,0,100,10,0,100,10,0, - 100,13,0,100,14,0,132,2,0,131,1,0,90,10,0,101, - 4,0,100,10,0,100,15,0,100,16,0,132,1,0,131,1, - 0,90,11,0,100,10,0,83,41,17,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,55,0,0,0, - 120,48,0,116,0,0,106,1,0,106,2,0,131,0,0,68, - 93,31,0,125,1,0,116,3,0,124,1,0,100,1,0,131, - 2,0,114,16,0,124,1,0,106,4,0,131,0,0,1,113, - 16,0,87,100,2,0,83,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,7, - 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,115,0,0,0,114,253,0,0,0,41,2,114,174,0,0, - 0,218,6,102,105,110,100,101,114,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,253,0,0,0,49,4,0, - 0,115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67,0,0,0,115, - 107,0,0,0,116,0,0,106,1,0,100,1,0,107,9,0, - 114,41,0,116,0,0,106,1,0,12,114,41,0,116,2,0, - 106,3,0,100,2,0,116,4,0,131,2,0,1,120,59,0, - 116,0,0,106,1,0,68,93,44,0,125,2,0,121,14,0, - 124,2,0,124,1,0,131,1,0,83,87,113,51,0,4,116, - 5,0,107,10,0,114,94,0,1,1,1,119,51,0,89,113, - 51,0,88,113,51,0,87,100,1,0,83,100,1,0,83,41, - 3,122,113,83,101,97,114,99,104,32,115,101,113,117,101,110, - 99,101,32,111,102,32,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,10,10,32,32,32,32,32,32,32,32,73,102, - 32,39,104,111,111,107,115,39,32,105,115,32,102,97,108,115, - 101,32,116,104,101,110,32,117,115,101,32,115,121,115,46,112, - 97,116,104,95,104,111,111,107,115,46,10,10,32,32,32,32, - 32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95,104,111,111,107, - 115,114,60,0,0,0,114,61,0,0,0,114,125,0,0,0, - 114,107,0,0,0,41,3,114,174,0,0,0,114,35,0,0, - 0,90,4,104,111,111,107,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,11,95,112,97,116,104,95,104,111, - 111,107,115,57,4,0,0,115,16,0,0,0,0,7,25,1, - 16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0,0,0,124,1, - 0,100,1,0,107,2,0,114,53,0,121,16,0,116,0,0, - 106,1,0,131,0,0,125,1,0,87,110,22,0,4,116,2, - 0,107,10,0,114,52,0,1,1,1,100,2,0,83,89,110, - 1,0,88,121,17,0,116,3,0,106,4,0,124,1,0,25, - 125,2,0,87,110,46,0,4,116,5,0,107,10,0,114,118, - 0,1,1,1,124,0,0,106,6,0,124,1,0,131,1,0, - 125,2,0,124,2,0,116,3,0,106,4,0,124,1,0,60, - 89,110,1,0,88,124,2,0,83,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,3,0,0,0,114,45,0,0, - 0,218,17,70,105,108,101,78,111,116,70,111,117,110,100,69, - 114,114,111,114,114,7,0,0,0,114,254,0,0,0,114,142, - 0,0,0,114,2,1,0,0,41,3,114,174,0,0,0,114, - 35,0,0,0,114,0,1,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,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,74,4, - 0,0,115,22,0,0,0,0,8,12,1,3,1,16,1,13, - 3,9,1,3,1,17,1,13,1,15,1,18,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,3,0,0,0,67, - 0,0,0,115,116,0,0,0,116,0,0,124,2,0,100,1, - 0,131,2,0,114,39,0,124,2,0,106,1,0,124,1,0, - 131,1,0,92,2,0,125,3,0,125,4,0,110,21,0,124, - 2,0,106,2,0,124,1,0,131,1,0,125,3,0,103,0, - 0,125,4,0,124,3,0,100,0,0,107,9,0,114,85,0, - 116,3,0,124,1,0,124,3,0,131,2,0,83,116,4,0, - 106,5,0,124,1,0,100,0,0,131,2,0,125,5,0,124, - 4,0,124,5,0,95,6,0,124,5,0,83,41,2,78,114, - 124,0,0,0,41,7,114,115,0,0,0,114,124,0,0,0, - 114,185,0,0,0,114,131,0,0,0,114,121,0,0,0,114, - 166,0,0,0,114,164,0,0,0,41,6,114,174,0,0,0, - 114,126,0,0,0,114,0,1,0,0,114,127,0,0,0,114, - 128,0,0,0,114,133,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,16,95,108,101,103,97,99, - 121,95,103,101,116,95,115,112,101,99,96,4,0,0,115,18, - 0,0,0,0,4,15,1,24,2,15,1,6,1,12,1,13, - 1,18,1,9,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,243,0,0,0,103,0,0, - 125,4,0,120,230,0,124,2,0,68,93,191,0,125,5,0, - 116,0,0,124,5,0,116,1,0,116,2,0,102,2,0,131, - 2,0,115,43,0,113,13,0,124,0,0,106,3,0,124,5, - 0,131,1,0,125,6,0,124,6,0,100,1,0,107,9,0, - 114,13,0,116,4,0,124,6,0,100,2,0,131,2,0,114, - 106,0,124,6,0,106,5,0,124,1,0,124,3,0,131,2, - 0,125,7,0,110,18,0,124,0,0,106,6,0,124,1,0, - 124,6,0,131,2,0,125,7,0,124,7,0,100,1,0,107, - 8,0,114,139,0,113,13,0,124,7,0,106,7,0,100,1, - 0,107,9,0,114,158,0,124,7,0,83,124,7,0,106,8, - 0,125,8,0,124,8,0,100,1,0,107,8,0,114,191,0, - 116,9,0,100,3,0,131,1,0,130,1,0,124,4,0,106, - 10,0,124,8,0,131,1,0,1,113,13,0,87,116,11,0, - 106,12,0,124,1,0,100,1,0,131,2,0,125,7,0,124, - 4,0,124,7,0,95,8,0,124,7,0,83,100,1,0,83, - 41,4,122,63,70,105,110,100,32,116,104,101,32,108,111,97, - 100,101,114,32,111,114,32,110,97,109,101,115,112,97,99,101, - 95,112,97,116,104,32,102,111,114,32,116,104,105,115,32,109, - 111,100,117,108,101,47,112,97,99,107,97,103,101,32,110,97, - 109,101,46,78,114,184,0,0,0,122,19,115,112,101,99,32, - 109,105,115,115,105,110,103,32,108,111,97,100,101,114,41,13, - 114,148,0,0,0,114,69,0,0,0,218,5,98,121,116,101, - 115,114,4,1,0,0,114,115,0,0,0,114,184,0,0,0, - 114,5,1,0,0,114,127,0,0,0,114,164,0,0,0,114, - 107,0,0,0,114,154,0,0,0,114,121,0,0,0,114,166, - 0,0,0,41,9,114,174,0,0,0,114,126,0,0,0,114, - 35,0,0,0,114,183,0,0,0,218,14,110,97,109,101,115, - 112,97,99,101,95,112,97,116,104,90,5,101,110,116,114,121, - 114,0,1,0,0,114,133,0,0,0,114,128,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,9, - 95,103,101,116,95,115,112,101,99,111,4,0,0,115,40,0, - 0,0,0,5,6,1,13,1,21,1,3,1,15,1,12,1, - 15,1,21,2,18,1,12,1,3,1,15,1,4,1,9,1, - 12,1,12,5,17,2,18,1,9,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,4,0,0, - 0,67,0,0,0,115,140,0,0,0,124,2,0,100,1,0, - 107,8,0,114,21,0,116,0,0,106,1,0,125,2,0,124, - 0,0,106,2,0,124,1,0,124,2,0,124,3,0,131,3, - 0,125,4,0,124,4,0,100,1,0,107,8,0,114,58,0, - 100,1,0,83,124,4,0,106,3,0,100,1,0,107,8,0, - 114,132,0,124,4,0,106,4,0,125,5,0,124,5,0,114, - 125,0,100,2,0,124,4,0,95,5,0,116,6,0,124,1, - 0,124,5,0,124,0,0,106,2,0,131,3,0,124,4,0, - 95,4,0,124,4,0,83,100,1,0,83,110,4,0,124,4, - 0,83,100,1,0,83,41,3,122,98,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,78,90,9,110, - 97,109,101,115,112,97,99,101,41,7,114,7,0,0,0,114, - 35,0,0,0,114,8,1,0,0,114,127,0,0,0,114,164, - 0,0,0,114,161,0,0,0,114,234,0,0,0,41,6,114, - 174,0,0,0,114,126,0,0,0,114,35,0,0,0,114,183, - 0,0,0,114,133,0,0,0,114,7,1,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,184,0,0, - 0,143,4,0,0,115,26,0,0,0,0,4,12,1,9,1, - 21,1,12,1,4,1,15,1,9,1,6,3,9,1,24,1, - 4,2,7,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, - 41,0,0,0,124,0,0,106,0,0,124,1,0,124,2,0, - 131,2,0,125,3,0,124,3,0,100,1,0,107,8,0,114, - 34,0,100,1,0,83,124,3,0,106,1,0,83,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,184, - 0,0,0,114,127,0,0,0,41,4,114,174,0,0,0,114, - 126,0,0,0,114,35,0,0,0,114,133,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,185,0, - 0,0,165,4,0,0,115,8,0,0,0,0,8,18,1,12, - 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,12,114,112,0, - 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, - 0,114,186,0,0,0,114,253,0,0,0,114,2,1,0,0, - 114,4,1,0,0,114,5,1,0,0,114,8,1,0,0,114, - 184,0,0,0,114,185,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,252,0, - 0,0,45,4,0,0,115,22,0,0,0,12,2,6,2,18, - 8,18,17,18,22,18,15,3,1,18,31,3,1,21,21,3, - 1,114,252,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,133,0,0,0, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,101,6,0,90,7,0, - 100,6,0,100,7,0,132,0,0,90,8,0,100,8,0,100, - 9,0,132,0,0,90,9,0,100,10,0,100,11,0,100,12, - 0,132,1,0,90,10,0,100,13,0,100,14,0,132,0,0, - 90,11,0,101,12,0,100,15,0,100,16,0,132,0,0,131, - 1,0,90,13,0,100,17,0,100,18,0,132,0,0,90,14, - 0,100,10,0,83,41,19,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,122,0,0,0,103,0,0,125,3, - 0,120,52,0,124,2,0,68,93,44,0,92,2,0,137,0, - 0,125,4,0,124,3,0,106,0,0,135,0,0,102,1,0, - 100,1,0,100,2,0,134,0,0,124,4,0,68,131,1,0, - 131,1,0,1,113,13,0,87,124,3,0,124,0,0,95,1, - 0,124,1,0,112,79,0,100,3,0,124,0,0,95,2,0, - 100,6,0,124,0,0,95,3,0,116,4,0,131,0,0,124, - 0,0,95,5,0,116,4,0,131,0,0,124,0,0,95,6, - 0,100,5,0,83,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,27,0,0,0,124,0,0, - 93,17,0,125,1,0,124,1,0,136,0,0,102,2,0,86, - 1,113,3,0,100,0,0,83,41,1,78,114,4,0,0,0, - 41,2,114,22,0,0,0,114,229,0,0,0,41,1,114,127, + 114,184,0,0,0,143,4,0,0,115,26,0,0,0,0,4, + 12,1,9,1,21,1,12,1,4,1,15,1,9,1,6,3, + 9,1,24,1,4,2,7,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,41,0,0,0,124,0,0,106,0,0,124,1, + 0,124,2,0,131,2,0,125,3,0,124,3,0,100,1,0, + 107,8,0,114,34,0,100,1,0,83,124,3,0,106,1,0, + 83,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,184,0,0,0,114,127,0,0,0,41,4,114,174, + 0,0,0,114,126,0,0,0,114,35,0,0,0,114,133,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,185,0,0,0,165,4,0,0,115,8,0,0,0,0, + 8,18,1,12,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, + 12,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, + 114,114,0,0,0,114,186,0,0,0,114,253,0,0,0,114, + 2,1,0,0,114,4,1,0,0,114,5,1,0,0,114,8, + 1,0,0,114,184,0,0,0,114,185,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,252,0,0,0,45,4,0,0,115,22,0,0,0,12, + 2,6,2,18,8,18,17,18,22,18,15,3,1,18,31,3, + 1,21,21,3,1,114,252,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, + 133,0,0,0,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,100,2,0,100,3,0,132,0,0,90, + 4,0,100,4,0,100,5,0,132,0,0,90,5,0,101,6, + 0,90,7,0,100,6,0,100,7,0,132,0,0,90,8,0, + 100,8,0,100,9,0,132,0,0,90,9,0,100,10,0,100, + 11,0,100,12,0,132,1,0,90,10,0,100,13,0,100,14, + 0,132,0,0,90,11,0,101,12,0,100,15,0,100,16,0, + 132,0,0,131,1,0,90,13,0,100,17,0,100,18,0,132, + 0,0,90,14,0,100,10,0,83,41,19,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,122,0,0,0,103, + 0,0,125,3,0,120,52,0,124,2,0,68,93,44,0,92, + 2,0,137,0,0,125,4,0,124,3,0,106,0,0,135,0, + 0,102,1,0,100,1,0,100,2,0,134,0,0,124,4,0, + 68,131,1,0,131,1,0,1,113,13,0,87,124,3,0,124, + 0,0,95,1,0,124,1,0,112,79,0,100,3,0,124,0, + 0,95,2,0,100,6,0,124,0,0,95,3,0,116,4,0, + 131,0,0,124,0,0,95,5,0,116,4,0,131,0,0,124, + 0,0,95,6,0,100,5,0,83,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,27,0,0, + 0,124,0,0,93,17,0,125,1,0,124,1,0,136,0,0, + 102,2,0,86,1,113,3,0,100,0,0,83,41,1,78,114, + 4,0,0,0,41,2,114,22,0,0,0,114,229,0,0,0, + 41,1,114,127,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,231,0,0,0,194,4,0,0,115,2,0,0,0,6, + 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,58,0,0,0,114,29, + 0,0,0,78,114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0, + 0,0,41,1,114,127,0,0,0,114,5,0,0,0,114,188, + 0,0,0,188,4,0,0,115,16,0,0,0,0,4,6,1, + 19,1,36,1,9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0, + 0,95,0,0,100,2,0,83,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,29,0,0,0, + 78,114,87,0,0,0,41,1,114,11,1,0,0,41,1,114, + 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,253,0,0,0,202,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,59,0,0,0,124,0,0,106,0, + 0,124,1,0,131,1,0,125,2,0,124,2,0,100,1,0, + 107,8,0,114,37,0,100,1,0,103,0,0,102,2,0,83, + 124,2,0,106,1,0,124,2,0,106,2,0,112,55,0,103, + 0,0,102,2,0,83,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,184,0,0,0,114,127,0,0,0,114,164,0,0, + 0,41,3,114,108,0,0,0,114,126,0,0,0,114,133,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,124,0,0,0,208,4,0,0,115,8,0,0,0,0, + 7,15,1,12,1,10,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,7,0,0,0, + 67,0,0,0,115,40,0,0,0,124,1,0,124,2,0,124, + 3,0,131,2,0,125,6,0,116,0,0,124,2,0,124,3, + 0,100,1,0,124,6,0,100,2,0,124,4,0,131,2,2, + 83,41,3,78,114,127,0,0,0,114,164,0,0,0,41,1, + 114,165,0,0,0,41,7,114,108,0,0,0,114,170,0,0, + 0,114,126,0,0,0,114,35,0,0,0,90,4,115,109,115, + 108,114,183,0,0,0,114,127,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,8,1,0,0,220, + 4,0,0,115,6,0,0,0,0,1,15,1,18,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,234,1,0,0,100, + 1,0,125,3,0,124,1,0,106,0,0,100,2,0,131,1, + 0,100,3,0,25,125,4,0,121,34,0,116,1,0,124,0, + 0,106,2,0,112,49,0,116,3,0,106,4,0,131,0,0, + 131,1,0,106,5,0,125,5,0,87,110,24,0,4,116,6, + 0,107,10,0,114,85,0,1,1,1,100,10,0,125,5,0, + 89,110,1,0,88,124,5,0,124,0,0,106,7,0,107,3, + 0,114,120,0,124,0,0,106,8,0,131,0,0,1,124,5, + 0,124,0,0,95,7,0,116,9,0,131,0,0,114,153,0, + 124,0,0,106,10,0,125,6,0,124,4,0,106,11,0,131, + 0,0,125,7,0,110,15,0,124,0,0,106,12,0,125,6, + 0,124,4,0,125,7,0,124,7,0,124,6,0,107,6,0, + 114,45,1,116,13,0,124,0,0,106,2,0,124,4,0,131, + 2,0,125,8,0,120,100,0,124,0,0,106,14,0,68,93, + 77,0,92,2,0,125,9,0,125,10,0,100,5,0,124,9, + 0,23,125,11,0,116,13,0,124,8,0,124,11,0,131,2, + 0,125,12,0,116,15,0,124,12,0,131,1,0,114,208,0, + 124,0,0,106,16,0,124,10,0,124,1,0,124,12,0,124, + 8,0,103,1,0,124,2,0,131,5,0,83,113,208,0,87, + 116,17,0,124,8,0,131,1,0,125,3,0,120,123,0,124, + 0,0,106,14,0,68,93,112,0,92,2,0,125,9,0,125, + 10,0,116,13,0,124,0,0,106,2,0,124,4,0,124,9, + 0,23,131,2,0,125,12,0,116,18,0,100,6,0,106,19, + 0,124,12,0,131,1,0,100,7,0,100,3,0,131,1,1, + 1,124,7,0,124,9,0,23,124,6,0,107,6,0,114,55, + 1,116,15,0,124,12,0,131,1,0,114,55,1,124,0,0, + 106,16,0,124,10,0,124,1,0,124,12,0,100,8,0,124, + 2,0,131,5,0,83,113,55,1,87,124,3,0,114,230,1, + 116,18,0,100,9,0,106,19,0,124,8,0,131,1,0,131, + 1,0,1,116,20,0,106,21,0,124,1,0,100,8,0,131, + 2,0,125,13,0,124,8,0,103,1,0,124,13,0,95,22, + 0,124,13,0,83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0, + 114,56,0,0,0,114,29,0,0,0,114,188,0,0,0,122, + 9,116,114,121,105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0, + 41,23,114,32,0,0,0,114,39,0,0,0,114,35,0,0, + 0,114,3,0,0,0,114,45,0,0,0,114,220,0,0,0, + 114,40,0,0,0,114,11,1,0,0,218,11,95,102,105,108, + 108,95,99,97,99,104,101,114,6,0,0,0,114,14,1,0, + 0,114,88,0,0,0,114,13,1,0,0,114,28,0,0,0, + 114,10,1,0,0,114,44,0,0,0,114,8,1,0,0,114, + 46,0,0,0,114,105,0,0,0,114,47,0,0,0,114,121, + 0,0,0,114,166,0,0,0,114,164,0,0,0,41,14,114, + 108,0,0,0,114,126,0,0,0,114,183,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,138,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,229, + 0,0,0,114,170,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,133,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,184,0,0,0,225,4,0,0,115, + 68,0,0,0,0,3,6,1,19,1,3,1,34,1,13,1, + 11,1,15,1,10,1,9,2,9,1,9,1,15,2,9,1, + 6,2,12,1,18,1,22,1,10,1,15,1,12,1,32,4, + 12,2,22,1,22,1,25,1,16,1,12,1,29,1,6,1, + 19,1,18,1,12,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,11,1,0,0,124,0,0,106,0,0,125,1, + 0,121,31,0,116,1,0,106,2,0,124,1,0,112,33,0, + 116,1,0,106,3,0,131,0,0,131,1,0,125,2,0,87, + 110,33,0,4,116,4,0,116,5,0,116,6,0,102,3,0, + 107,10,0,114,75,0,1,1,1,103,0,0,125,2,0,89, + 110,1,0,88,116,7,0,106,8,0,106,9,0,100,1,0, + 131,1,0,115,112,0,116,10,0,124,2,0,131,1,0,124, + 0,0,95,11,0,110,111,0,116,10,0,131,0,0,125,3, + 0,120,90,0,124,2,0,68,93,82,0,125,4,0,124,4, + 0,106,12,0,100,2,0,131,1,0,92,3,0,125,5,0, + 125,6,0,125,7,0,124,6,0,114,191,0,100,3,0,106, + 13,0,124,5,0,124,7,0,106,14,0,131,0,0,131,2, + 0,125,8,0,110,6,0,124,5,0,125,8,0,124,3,0, + 106,15,0,124,8,0,131,1,0,1,113,128,0,87,124,3, + 0,124,0,0,95,11,0,116,7,0,106,8,0,106,9,0, + 116,16,0,131,1,0,114,7,1,100,4,0,100,5,0,132, + 0,0,124,2,0,68,131,1,0,124,0,0,95,17,0,100, + 6,0,83,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,58,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,28,0,0,0,104,0,0,124,0,0,93,18,0,125, + 1,0,124,1,0,106,0,0,131,0,0,146,2,0,113,6, + 0,83,114,4,0,0,0,41,1,114,88,0,0,0,41,2, + 114,22,0,0,0,90,2,102,110,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,250,9,60,115,101,116,99,111, + 109,112,62,43,5,0,0,115,2,0,0,0,9,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,3,0,0,0,90,7,108,105,115,116,100,105,114,114, + 45,0,0,0,114,3,1,0,0,218,15,80,101,114,109,105, + 115,115,105,111,110,69,114,114,111,114,218,18,78,111,116,65, + 68,105,114,101,99,116,111,114,121,69,114,114,111,114,114,7, + 0,0,0,114,8,0,0,0,114,9,0,0,0,114,12,1, + 0,0,114,13,1,0,0,114,83,0,0,0,114,47,0,0, + 0,114,88,0,0,0,218,3,97,100,100,114,10,0,0,0, + 114,14,1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,241,0,0, + 0,114,229,0,0,0,90,8,110,101,119,95,110,97,109,101, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 16,1,0,0,14,5,0,0,115,34,0,0,0,0,2,9, + 1,3,1,31,1,22,3,11,3,18,1,18,7,9,1,13, + 1,24,1,6,1,27,2,6,1,17,1,9,1,18,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,25,0,0, + 0,135,0,0,135,1,0,102,2,0,100,1,0,100,2,0, + 134,0,0,125,2,0,124,2,0,83,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,43,0,0,0,116, + 0,0,124,0,0,131,1,0,115,30,0,116,1,0,100,1, + 0,100,2,0,124,0,0,131,1,1,130,1,0,136,0,0, + 124,0,0,136,1,0,140,1,0,83,41,3,122,45,80,97, + 116,104,32,104,111,111,107,32,102,111,114,32,105,109,112,111, + 114,116,108,105,98,46,109,97,99,104,105,110,101,114,121,46, + 70,105,108,101,70,105,110,100,101,114,46,122,30,111,110,108, + 121,32,100,105,114,101,99,116,111,114,105,101,115,32,97,114, + 101,32,115,117,112,112,111,114,116,101,100,114,35,0,0,0, + 41,2,114,46,0,0,0,114,107,0,0,0,41,1,114,35, + 0,0,0,41,2,114,174,0,0,0,114,15,1,0,0,114, + 4,0,0,0,114,5,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,55,5,0,0,115,6,0,0,0,0,2,12,1, + 18,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,174,0,0,0,114,15,1,0,0,114,21,1,0,0, + 114,4,0,0,0,41,2,114,174,0,0,0,114,15,1,0, + 0,114,5,0,0,0,218,9,112,97,116,104,95,104,111,111, + 107,45,5,0,0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1, + 0,106,0,0,124,0,0,106,1,0,131,1,0,83,41,2, + 78,122,16,70,105,108,101,70,105,110,100,101,114,40,123,33, + 114,125,41,41,2,114,47,0,0,0,114,35,0,0,0,41, + 1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,247,0,0,0,63,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,15,114,112,0,0, + 0,114,111,0,0,0,114,113,0,0,0,114,114,0,0,0, + 114,188,0,0,0,114,253,0,0,0,114,130,0,0,0,114, + 185,0,0,0,114,124,0,0,0,114,8,1,0,0,114,184, + 0,0,0,114,16,1,0,0,114,186,0,0,0,114,22,1, + 0,0,114,247,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,9,1,0,0, + 179,4,0,0,115,20,0,0,0,12,7,6,2,12,14,12, + 4,6,2,12,12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106, + 0,0,100,1,0,131,1,0,125,4,0,124,0,0,106,0, + 0,100,2,0,131,1,0,125,5,0,124,4,0,115,99,0, + 124,5,0,114,54,0,124,5,0,106,1,0,125,4,0,110, + 45,0,124,2,0,124,3,0,107,2,0,114,84,0,116,2, + 0,124,1,0,124,2,0,131,2,0,125,4,0,110,15,0, + 116,3,0,124,1,0,124,2,0,131,2,0,125,4,0,124, + 5,0,115,126,0,116,4,0,124,1,0,124,2,0,100,3, + 0,124,4,0,131,2,1,125,5,0,121,44,0,124,5,0, + 124,0,0,100,2,0,60,124,4,0,124,0,0,100,1,0, + 60,124,2,0,124,0,0,100,4,0,60,124,3,0,124,0, + 0,100,5,0,60,87,110,18,0,4,116,5,0,107,10,0, + 114,190,0,1,1,1,89,110,1,0,88,100,0,0,83,41, + 6,78,114,227,0,0,0,218,8,95,95,115,112,101,99,95, + 95,114,127,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,127,0,0,0,114,224,0,0,0,114,219,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,106,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,127,0,0,0,114,133,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,14,95,102,105, + 120,95,117,112,95,109,111,100,117,108,101,69,5,0,0,115, + 34,0,0,0,0,2,15,1,15,1,6,1,6,1,12,1, + 12,1,18,2,15,1,6,1,21,1,3,1,10,1,10,1, + 10,1,14,1,13,2,114,26,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,55,0,0,0,116,0,0,116,1,0,106,2,0,131,0, + 0,102,2,0,125,0,0,116,3,0,116,4,0,102,2,0, + 125,1,0,116,5,0,116,6,0,102,2,0,125,2,0,124, + 0,0,124,1,0,124,2,0,103,3,0,83,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,225,0,0,0,114,150,0,0,0,218,18,101,120,116, + 101,110,115,105,111,110,95,115,117,102,102,105,120,101,115,114, + 219,0,0,0,114,84,0,0,0,114,224,0,0,0,114,74, + 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,5,0, + 0,0,114,167,0,0,0,92,5,0,0,115,8,0,0,0, + 0,5,18,1,12,1,12,1,114,167,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,70,2,0,0,124,0,0,97,0,0,116,0,0, + 106,1,0,97,1,0,116,0,0,106,2,0,97,2,0,116, + 1,0,106,3,0,116,4,0,25,125,1,0,120,76,0,100, + 26,0,68,93,68,0,125,2,0,124,2,0,116,1,0,106, + 3,0,107,7,0,114,83,0,116,0,0,106,5,0,124,2, + 0,131,1,0,125,3,0,110,13,0,116,1,0,106,3,0, + 124,2,0,25,125,3,0,116,6,0,124,1,0,124,2,0, + 124,3,0,131,3,0,1,113,44,0,87,100,5,0,100,6, + 0,103,1,0,102,2,0,100,7,0,100,8,0,100,6,0, + 103,2,0,102,2,0,102,2,0,125,4,0,120,149,0,124, + 4,0,68,93,129,0,92,2,0,125,5,0,125,6,0,116, + 7,0,100,9,0,100,10,0,132,0,0,124,6,0,68,131, + 1,0,131,1,0,115,199,0,116,8,0,130,1,0,124,6, + 0,100,11,0,25,125,7,0,124,5,0,116,1,0,106,3, + 0,107,6,0,114,241,0,116,1,0,106,3,0,124,5,0, + 25,125,8,0,80,113,156,0,121,20,0,116,0,0,106,5, + 0,124,5,0,131,1,0,125,8,0,80,87,113,156,0,4, + 116,9,0,107,10,0,114,28,1,1,1,1,119,156,0,89, + 113,156,0,88,113,156,0,87,116,9,0,100,12,0,131,1, + 0,130,1,0,116,6,0,124,1,0,100,13,0,124,8,0, + 131,3,0,1,116,6,0,124,1,0,100,14,0,124,7,0, + 131,3,0,1,116,6,0,124,1,0,100,15,0,100,16,0, + 106,10,0,124,6,0,131,1,0,131,3,0,1,121,19,0, + 116,0,0,106,5,0,100,17,0,131,1,0,125,9,0,87, + 110,24,0,4,116,9,0,107,10,0,114,147,1,1,1,1, + 100,18,0,125,9,0,89,110,1,0,88,116,6,0,124,1, + 0,100,17,0,124,9,0,131,3,0,1,116,0,0,106,5, + 0,100,19,0,131,1,0,125,10,0,116,6,0,124,1,0, + 100,19,0,124,10,0,131,3,0,1,124,5,0,100,7,0, + 107,2,0,114,238,1,116,0,0,106,5,0,100,20,0,131, + 1,0,125,11,0,116,6,0,124,1,0,100,21,0,124,11, + 0,131,3,0,1,116,6,0,124,1,0,100,22,0,116,11, + 0,131,0,0,131,3,0,1,116,12,0,106,13,0,116,2, + 0,106,14,0,131,0,0,131,1,0,1,124,5,0,100,7, + 0,107,2,0,114,66,2,116,15,0,106,16,0,100,23,0, + 131,1,0,1,100,24,0,116,12,0,107,6,0,114,66,2, + 100,25,0,116,17,0,95,18,0,100,18,0,83,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,49, + 0,0,0,114,60,0,0,0,218,8,98,117,105,108,116,105, + 110,115,114,147,0,0,0,90,5,112,111,115,105,120,250,1, + 47,218,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,33,0, + 0,0,124,0,0,93,23,0,125,1,0,116,0,0,124,1, + 0,131,1,0,100,0,0,107,2,0,86,1,113,3,0,100, + 1,0,83,41,2,114,29,0,0,0,78,41,1,114,31,0, + 0,0,41,2,114,22,0,0,0,114,77,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,231,0, - 0,0,194,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0,0,78, - 114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0,0,0,41,1, - 114,127,0,0,0,114,5,0,0,0,114,188,0,0,0,188, - 4,0,0,115,16,0,0,0,0,4,6,1,19,1,36,1, - 9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0,0,95,0,0, - 100,2,0,83,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,29,0,0,0,78,114,87,0, - 0,0,41,1,114,11,1,0,0,41,1,114,108,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 253,0,0,0,202,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,59,0,0,0,124,0,0,106,0,0,124,1,0, - 131,1,0,125,2,0,124,2,0,100,1,0,107,8,0,114, - 37,0,100,1,0,103,0,0,102,2,0,83,124,2,0,106, - 1,0,124,2,0,106,2,0,112,55,0,103,0,0,102,2, - 0,83,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,184, - 0,0,0,114,127,0,0,0,114,164,0,0,0,41,3,114, - 108,0,0,0,114,126,0,0,0,114,133,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,124,0, - 0,0,208,4,0,0,115,8,0,0,0,0,7,15,1,12, - 1,10,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,7,0,0,0,67,0,0,0, - 115,40,0,0,0,124,1,0,124,2,0,124,3,0,131,2, - 0,125,6,0,116,0,0,124,2,0,124,3,0,100,1,0, - 124,6,0,100,2,0,124,4,0,131,2,2,83,41,3,78, - 114,127,0,0,0,114,164,0,0,0,41,1,114,165,0,0, - 0,41,7,114,108,0,0,0,114,170,0,0,0,114,126,0, - 0,0,114,35,0,0,0,90,4,115,109,115,108,114,183,0, - 0,0,114,127,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,8,1,0,0,220,4,0,0,115, - 6,0,0,0,0,1,15,1,18,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,234,1,0,0,100,1,0,125,3, - 0,124,1,0,106,0,0,100,2,0,131,1,0,100,3,0, - 25,125,4,0,121,34,0,116,1,0,124,0,0,106,2,0, - 112,49,0,116,3,0,106,4,0,131,0,0,131,1,0,106, - 5,0,125,5,0,87,110,24,0,4,116,6,0,107,10,0, - 114,85,0,1,1,1,100,10,0,125,5,0,89,110,1,0, - 88,124,5,0,124,0,0,106,7,0,107,3,0,114,120,0, - 124,0,0,106,8,0,131,0,0,1,124,5,0,124,0,0, - 95,7,0,116,9,0,131,0,0,114,153,0,124,0,0,106, - 10,0,125,6,0,124,4,0,106,11,0,131,0,0,125,7, - 0,110,15,0,124,0,0,106,12,0,125,6,0,124,4,0, - 125,7,0,124,7,0,124,6,0,107,6,0,114,45,1,116, - 13,0,124,0,0,106,2,0,124,4,0,131,2,0,125,8, - 0,120,100,0,124,0,0,106,14,0,68,93,77,0,92,2, - 0,125,9,0,125,10,0,100,5,0,124,9,0,23,125,11, - 0,116,13,0,124,8,0,124,11,0,131,2,0,125,12,0, - 116,15,0,124,12,0,131,1,0,114,208,0,124,0,0,106, - 16,0,124,10,0,124,1,0,124,12,0,124,8,0,103,1, - 0,124,2,0,131,5,0,83,113,208,0,87,116,17,0,124, - 8,0,131,1,0,125,3,0,120,123,0,124,0,0,106,14, - 0,68,93,112,0,92,2,0,125,9,0,125,10,0,116,13, - 0,124,0,0,106,2,0,124,4,0,124,9,0,23,131,2, - 0,125,12,0,116,18,0,100,6,0,106,19,0,124,12,0, - 131,1,0,100,7,0,100,3,0,131,1,1,1,124,7,0, - 124,9,0,23,124,6,0,107,6,0,114,55,1,116,15,0, - 124,12,0,131,1,0,114,55,1,124,0,0,106,16,0,124, - 10,0,124,1,0,124,12,0,100,8,0,124,2,0,131,5, - 0,83,113,55,1,87,124,3,0,114,230,1,116,18,0,100, - 9,0,106,19,0,124,8,0,131,1,0,131,1,0,1,116, - 20,0,106,21,0,124,1,0,100,8,0,131,2,0,125,13, - 0,124,8,0,103,1,0,124,13,0,95,22,0,124,13,0, - 83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0,114,56,0,0, - 0,114,29,0,0,0,114,188,0,0,0,122,9,116,114,121, - 105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0,41,23,114,32, - 0,0,0,114,39,0,0,0,114,35,0,0,0,114,3,0, - 0,0,114,45,0,0,0,114,220,0,0,0,114,40,0,0, - 0,114,11,1,0,0,218,11,95,102,105,108,108,95,99,97, - 99,104,101,114,6,0,0,0,114,14,1,0,0,114,88,0, - 0,0,114,13,1,0,0,114,28,0,0,0,114,10,1,0, - 0,114,44,0,0,0,114,8,1,0,0,114,46,0,0,0, - 114,105,0,0,0,114,47,0,0,0,114,121,0,0,0,114, - 166,0,0,0,114,164,0,0,0,41,14,114,108,0,0,0, - 114,126,0,0,0,114,183,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,138,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,229,0,0,0,114, - 170,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,133, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,184,0,0,0,225,4,0,0,115,68,0,0,0, - 0,3,6,1,19,1,3,1,34,1,13,1,11,1,15,1, - 10,1,9,2,9,1,9,1,15,2,9,1,6,2,12,1, - 18,1,22,1,10,1,15,1,12,1,32,4,12,2,22,1, - 22,1,25,1,16,1,12,1,29,1,6,1,19,1,18,1, - 12,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, - 11,1,0,0,124,0,0,106,0,0,125,1,0,121,31,0, - 116,1,0,106,2,0,124,1,0,112,33,0,116,1,0,106, - 3,0,131,0,0,131,1,0,125,2,0,87,110,33,0,4, - 116,4,0,116,5,0,116,6,0,102,3,0,107,10,0,114, - 75,0,1,1,1,103,0,0,125,2,0,89,110,1,0,88, - 116,7,0,106,8,0,106,9,0,100,1,0,131,1,0,115, - 112,0,116,10,0,124,2,0,131,1,0,124,0,0,95,11, - 0,110,111,0,116,10,0,131,0,0,125,3,0,120,90,0, - 124,2,0,68,93,82,0,125,4,0,124,4,0,106,12,0, - 100,2,0,131,1,0,92,3,0,125,5,0,125,6,0,125, - 7,0,124,6,0,114,191,0,100,3,0,106,13,0,124,5, - 0,124,7,0,106,14,0,131,0,0,131,2,0,125,8,0, - 110,6,0,124,5,0,125,8,0,124,3,0,106,15,0,124, - 8,0,131,1,0,1,113,128,0,87,124,3,0,124,0,0, - 95,11,0,116,7,0,106,8,0,106,9,0,116,16,0,131, - 1,0,114,7,1,100,4,0,100,5,0,132,0,0,124,2, - 0,68,131,1,0,124,0,0,95,17,0,100,6,0,83,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,58,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,28,0, - 0,0,104,0,0,124,0,0,93,18,0,125,1,0,124,1, - 0,106,0,0,131,0,0,146,2,0,113,6,0,83,114,4, - 0,0,0,41,1,114,88,0,0,0,41,2,114,22,0,0, - 0,90,2,102,110,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,250,9,60,115,101,116,99,111,109,112,62,43, - 5,0,0,115,2,0,0,0,9,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,3,0, - 0,0,90,7,108,105,115,116,100,105,114,114,45,0,0,0, - 114,3,1,0,0,218,15,80,101,114,109,105,115,115,105,111, - 110,69,114,114,111,114,218,18,78,111,116,65,68,105,114,101, - 99,116,111,114,121,69,114,114,111,114,114,7,0,0,0,114, - 8,0,0,0,114,9,0,0,0,114,12,1,0,0,114,13, - 1,0,0,114,83,0,0,0,114,47,0,0,0,114,88,0, - 0,0,218,3,97,100,100,114,10,0,0,0,114,14,1,0, - 0,41,9,114,108,0,0,0,114,35,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,248, - 0,0,0,114,106,0,0,0,114,241,0,0,0,114,229,0, - 0,0,90,8,110,101,119,95,110,97,109,101,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,16,1,0,0, - 14,5,0,0,115,34,0,0,0,0,2,9,1,3,1,31, - 1,22,3,11,3,18,1,18,7,9,1,13,1,24,1,6, - 1,27,2,6,1,17,1,9,1,18,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,25,0,0,0,135,0,0, - 135,1,0,102,2,0,100,1,0,100,2,0,134,0,0,125, - 2,0,124,2,0,83,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,43,0,0,0,116,0,0,124,0, - 0,131,1,0,115,30,0,116,1,0,100,1,0,100,2,0, - 124,0,0,131,1,1,130,1,0,136,0,0,124,0,0,136, - 1,0,140,1,0,83,41,3,122,45,80,97,116,104,32,104, - 111,111,107,32,102,111,114,32,105,109,112,111,114,116,108,105, - 98,46,109,97,99,104,105,110,101,114,121,46,70,105,108,101, - 70,105,110,100,101,114,46,122,30,111,110,108,121,32,100,105, - 114,101,99,116,111,114,105,101,115,32,97,114,101,32,115,117, - 112,112,111,114,116,101,100,114,35,0,0,0,41,2,114,46, - 0,0,0,114,107,0,0,0,41,1,114,35,0,0,0,41, - 2,114,174,0,0,0,114,15,1,0,0,114,4,0,0,0, - 114,5,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,55, - 5,0,0,115,6,0,0,0,0,2,12,1,18,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,174,0, - 0,0,114,15,1,0,0,114,21,1,0,0,114,4,0,0, - 0,41,2,114,174,0,0,0,114,15,1,0,0,114,5,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,45,5,0, - 0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1,0,106,0,0, - 124,0,0,106,1,0,131,1,0,83,41,2,78,122,16,70, - 105,108,101,70,105,110,100,101,114,40,123,33,114,125,41,41, - 2,114,47,0,0,0,114,35,0,0,0,41,1,114,108,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,247,0,0,0,63,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,15,114,112,0,0,0,114,111,0, - 0,0,114,113,0,0,0,114,114,0,0,0,114,188,0,0, - 0,114,253,0,0,0,114,130,0,0,0,114,185,0,0,0, - 114,124,0,0,0,114,8,1,0,0,114,184,0,0,0,114, - 16,1,0,0,114,186,0,0,0,114,22,1,0,0,114,247, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,9,1,0,0,179,4,0,0, - 115,20,0,0,0,12,7,6,2,12,14,12,4,6,2,12, - 12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106,0,0,100,1, - 0,131,1,0,125,4,0,124,0,0,106,0,0,100,2,0, - 131,1,0,125,5,0,124,4,0,115,99,0,124,5,0,114, - 54,0,124,5,0,106,1,0,125,4,0,110,45,0,124,2, - 0,124,3,0,107,2,0,114,84,0,116,2,0,124,1,0, - 124,2,0,131,2,0,125,4,0,110,15,0,116,3,0,124, - 1,0,124,2,0,131,2,0,125,4,0,124,5,0,115,126, - 0,116,4,0,124,1,0,124,2,0,100,3,0,124,4,0, - 131,2,1,125,5,0,121,44,0,124,5,0,124,0,0,100, - 2,0,60,124,4,0,124,0,0,100,1,0,60,124,2,0, - 124,0,0,100,4,0,60,124,3,0,124,0,0,100,5,0, - 60,87,110,18,0,4,116,5,0,107,10,0,114,190,0,1, - 1,1,89,110,1,0,88,100,0,0,83,41,6,78,114,227, - 0,0,0,218,8,95,95,115,112,101,99,95,95,114,127,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, - 127,0,0,0,114,224,0,0,0,114,219,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,106,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,127, - 0,0,0,114,133,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,14,95,102,105,120,95,117,112, - 95,109,111,100,117,108,101,69,5,0,0,115,34,0,0,0, - 0,2,15,1,15,1,6,1,6,1,12,1,12,1,18,2, - 15,1,6,1,21,1,3,1,10,1,10,1,10,1,14,1, - 13,2,114,26,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,55,0,0, - 0,116,0,0,116,1,0,106,2,0,131,0,0,102,2,0, - 125,0,0,116,3,0,116,4,0,102,2,0,125,1,0,116, - 5,0,116,6,0,102,2,0,125,2,0,124,0,0,124,1, - 0,124,2,0,103,3,0,83,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,225,0, - 0,0,114,150,0,0,0,218,18,101,120,116,101,110,115,105, - 111,110,95,115,117,102,102,105,120,101,115,114,219,0,0,0, - 114,84,0,0,0,114,224,0,0,0,114,74,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,5,0,0,0,114,167, - 0,0,0,92,5,0,0,115,8,0,0,0,0,5,18,1, - 12,1,12,1,114,167,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,70, - 2,0,0,124,0,0,97,0,0,116,0,0,106,1,0,97, - 1,0,116,0,0,106,2,0,97,2,0,116,1,0,106,3, - 0,116,4,0,25,125,1,0,120,76,0,100,26,0,68,93, - 68,0,125,2,0,124,2,0,116,1,0,106,3,0,107,7, - 0,114,83,0,116,0,0,106,5,0,124,2,0,131,1,0, - 125,3,0,110,13,0,116,1,0,106,3,0,124,2,0,25, - 125,3,0,116,6,0,124,1,0,124,2,0,124,3,0,131, - 3,0,1,113,44,0,87,100,5,0,100,6,0,103,1,0, - 102,2,0,100,7,0,100,8,0,100,6,0,103,2,0,102, - 2,0,102,2,0,125,4,0,120,149,0,124,4,0,68,93, - 129,0,92,2,0,125,5,0,125,6,0,116,7,0,100,9, - 0,100,10,0,132,0,0,124,6,0,68,131,1,0,131,1, - 0,115,199,0,116,8,0,130,1,0,124,6,0,100,11,0, - 25,125,7,0,124,5,0,116,1,0,106,3,0,107,6,0, - 114,241,0,116,1,0,106,3,0,124,5,0,25,125,8,0, - 80,113,156,0,121,20,0,116,0,0,106,5,0,124,5,0, - 131,1,0,125,8,0,80,87,113,156,0,4,116,9,0,107, - 10,0,114,28,1,1,1,1,119,156,0,89,113,156,0,88, - 113,156,0,87,116,9,0,100,12,0,131,1,0,130,1,0, - 116,6,0,124,1,0,100,13,0,124,8,0,131,3,0,1, - 116,6,0,124,1,0,100,14,0,124,7,0,131,3,0,1, - 116,6,0,124,1,0,100,15,0,100,16,0,106,10,0,124, - 6,0,131,1,0,131,3,0,1,121,19,0,116,0,0,106, - 5,0,100,17,0,131,1,0,125,9,0,87,110,24,0,4, - 116,9,0,107,10,0,114,147,1,1,1,1,100,18,0,125, - 9,0,89,110,1,0,88,116,6,0,124,1,0,100,17,0, - 124,9,0,131,3,0,1,116,0,0,106,5,0,100,19,0, - 131,1,0,125,10,0,116,6,0,124,1,0,100,19,0,124, - 10,0,131,3,0,1,124,5,0,100,7,0,107,2,0,114, - 238,1,116,0,0,106,5,0,100,20,0,131,1,0,125,11, - 0,116,6,0,124,1,0,100,21,0,124,11,0,131,3,0, - 1,116,6,0,124,1,0,100,22,0,116,11,0,131,0,0, - 131,3,0,1,116,12,0,106,13,0,116,2,0,106,14,0, - 131,0,0,131,1,0,1,124,5,0,100,7,0,107,2,0, - 114,66,2,116,15,0,106,16,0,100,23,0,131,1,0,1, - 100,24,0,116,12,0,107,6,0,114,66,2,100,25,0,116, - 17,0,95,18,0,100,18,0,83,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,49,0,0,0,114, - 60,0,0,0,218,8,98,117,105,108,116,105,110,115,114,147, - 0,0,0,90,5,112,111,115,105,120,250,1,47,218,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,33,0,0,0,124,0, - 0,93,23,0,125,1,0,116,0,0,124,1,0,131,1,0, - 100,0,0,107,2,0,86,1,113,3,0,100,1,0,83,41, - 2,114,29,0,0,0,78,41,1,114,31,0,0,0,41,2, - 114,22,0,0,0,114,77,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,231,0,0,0,128,5, - 0,0,115,2,0,0,0,6,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,59,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,25, - 0,0,0,114,21,0,0,0,114,30,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,173,0,0,0,114,6, - 0,0,0,122,4,46,112,121,119,122,6,95,100,46,112,121, - 100,84,41,4,122,3,95,105,111,122,9,95,119,97,114,110, - 105,110,103,115,122,8,98,117,105,108,116,105,110,115,122,7, - 109,97,114,115,104,97,108,41,19,114,121,0,0,0,114,7, - 0,0,0,114,150,0,0,0,114,132,0,0,0,114,112,0, - 0,0,90,18,95,98,117,105,108,116,105,110,95,102,114,111, - 109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0,0,0,114, - 233,0,0,0,114,154,0,0,0,114,27,1,0,0,114,84, - 0,0,0,114,169,0,0,0,114,172,0,0,0,114,177,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,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,6,95,115, - 101,116,117,112,103,5,0,0,115,82,0,0,0,0,8,6, - 1,9,1,9,3,13,1,13,1,15,1,18,2,13,1,20, - 3,33,1,19,2,31,1,10,1,15,1,13,1,4,2,3, - 1,15,1,5,1,13,1,12,2,12,1,16,1,16,1,25, - 3,3,1,19,1,13,2,11,1,16,3,15,1,16,3,12, - 1,15,1,16,3,19,1,19,1,12,1,13,1,12,1,114, - 35,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,116,0,0,0,116,0, - 0,124,0,0,131,1,0,1,116,1,0,131,0,0,125,1, - 0,116,2,0,106,3,0,106,4,0,116,5,0,106,6,0, - 124,1,0,140,0,0,103,1,0,131,1,0,1,116,7,0, - 106,8,0,100,1,0,107,2,0,114,78,0,116,2,0,106, - 9,0,106,10,0,116,11,0,131,1,0,1,116,2,0,106, - 9,0,106,10,0,116,12,0,131,1,0,1,116,5,0,124, - 0,0,95,5,0,116,13,0,124,0,0,95,13,0,100,2, - 0,83,41,3,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,114, - 30,1,0,0,78,41,14,114,35,1,0,0,114,167,0,0, - 0,114,7,0,0,0,114,1,1,0,0,114,154,0,0,0, - 114,9,1,0,0,114,22,1,0,0,114,3,0,0,0,114, - 112,0,0,0,218,9,109,101,116,97,95,112,97,116,104,114, - 169,0,0,0,114,172,0,0,0,114,252,0,0,0,114,219, - 0,0,0,41,2,114,34,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,5,0,0,0,218,8,95,105, - 110,115,116,97,108,108,171,5,0,0,115,16,0,0,0,0, - 2,10,1,9,1,28,1,15,1,16,1,16,4,9,1,114, - 37,1,0,0,41,3,122,3,119,105,110,114,1,0,0,0, - 114,2,0,0,0,41,59,114,114,0,0,0,114,10,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,55, - 0,0,0,218,4,116,121,112,101,218,8,95,95,99,111,100, - 101,95,95,114,149,0,0,0,114,15,0,0,0,114,140,0, - 0,0,114,14,0,0,0,114,18,0,0,0,90,17,95,82, - 65,87,95,77,65,71,73,67,95,78,85,77,66,69,82,114, - 73,0,0,0,114,72,0,0,0,114,84,0,0,0,114,74, - 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,79,0,0,0,114,85, - 0,0,0,114,91,0,0,0,114,95,0,0,0,114,97,0, - 0,0,114,105,0,0,0,114,123,0,0,0,114,130,0,0, - 0,114,135,0,0,0,114,146,0,0,0,114,152,0,0,0, - 114,155,0,0,0,114,160,0,0,0,114,131,0,0,0,218, - 6,111,98,106,101,99,116,114,168,0,0,0,114,165,0,0, - 0,114,172,0,0,0,114,187,0,0,0,114,195,0,0,0, - 114,211,0,0,0,114,219,0,0,0,114,224,0,0,0,114, - 233,0,0,0,114,225,0,0,0,114,234,0,0,0,114,250, - 0,0,0,114,252,0,0,0,114,9,1,0,0,114,26,1, - 0,0,114,167,0,0,0,114,35,1,0,0,114,37,1,0, - 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,8,60,109,111,100,117,108,101,62,8, - 0,0,0,115,104,0,0,0,6,17,6,3,12,12,12,5, - 12,5,12,6,12,12,12,10,12,9,12,5,12,7,15,22, - 15,108,22,1,18,2,6,1,6,2,9,2,9,2,10,2, - 21,44,12,33,12,19,12,12,12,12,18,8,12,27,12,18, - 12,15,21,55,21,12,18,10,12,14,24,22,9,3,12,1, - 15,65,19,63,19,27,22,110,19,41,25,43,25,16,6,3, - 19,57,19,57,19,41,19,134,19,146,15,23,12,11,12,68, + 0,0,128,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,173,0, + 0,0,114,6,0,0,0,122,4,46,112,121,119,122,6,95, + 100,46,112,121,100,84,41,4,122,3,95,105,111,122,9,95, + 119,97,114,110,105,110,103,115,122,8,98,117,105,108,116,105, + 110,115,122,7,109,97,114,115,104,97,108,41,19,114,121,0, + 0,0,114,7,0,0,0,114,150,0,0,0,114,132,0,0, + 0,114,112,0,0,0,90,18,95,98,117,105,108,116,105,110, + 95,102,114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11, + 0,0,0,114,233,0,0,0,114,154,0,0,0,114,27,1, + 0,0,114,84,0,0,0,114,169,0,0,0,114,172,0,0, + 0,114,177,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,6,95,115,101,116,117,112,103,5,0,0,115,82,0,0, + 0,0,8,6,1,9,1,9,3,13,1,13,1,15,1,18, + 2,13,1,20,3,33,1,19,2,31,1,10,1,15,1,13, + 1,4,2,3,1,15,1,5,1,13,1,12,2,12,1,16, + 1,16,1,25,3,3,1,19,1,13,2,11,1,16,3,15, + 1,16,3,12,1,15,1,16,3,19,1,19,1,12,1,13, + 1,12,1,114,35,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,116,0, + 0,0,116,0,0,124,0,0,131,1,0,1,116,1,0,131, + 0,0,125,1,0,116,2,0,106,3,0,106,4,0,116,5, + 0,106,6,0,124,1,0,140,0,0,103,1,0,131,1,0, + 1,116,7,0,106,8,0,100,1,0,107,2,0,114,78,0, + 116,2,0,106,9,0,106,10,0,116,11,0,131,1,0,1, + 116,2,0,106,9,0,106,10,0,116,12,0,131,1,0,1, + 116,5,0,124,0,0,95,5,0,116,13,0,124,0,0,95, + 13,0,100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0, + 114,167,0,0,0,114,7,0,0,0,114,1,1,0,0,114, + 154,0,0,0,114,9,1,0,0,114,22,1,0,0,114,3, + 0,0,0,114,112,0,0,0,218,9,109,101,116,97,95,112, + 97,116,104,114,169,0,0,0,114,172,0,0,0,114,252,0, + 0,0,114,219,0,0,0,41,2,114,34,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,5,0,0,0, + 218,8,95,105,110,115,116,97,108,108,171,5,0,0,115,16, + 0,0,0,0,2,10,1,9,1,28,1,15,1,16,1,16, + 4,9,1,114,37,1,0,0,41,3,122,3,119,105,110,114, + 1,0,0,0,114,2,0,0,0,41,59,114,114,0,0,0, + 114,10,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,55,0,0,0,218,4,116,121,112,101,218,8,95, + 95,99,111,100,101,95,95,114,149,0,0,0,114,15,0,0, + 0,114,140,0,0,0,114,14,0,0,0,114,18,0,0,0, + 90,17,95,82,65,87,95,77,65,71,73,67,95,78,85,77, + 66,69,82,114,73,0,0,0,114,72,0,0,0,114,84,0, + 0,0,114,74,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,79,0, + 0,0,114,85,0,0,0,114,91,0,0,0,114,95,0,0, + 0,114,97,0,0,0,114,105,0,0,0,114,123,0,0,0, + 114,130,0,0,0,114,135,0,0,0,114,146,0,0,0,114, + 152,0,0,0,114,155,0,0,0,114,160,0,0,0,114,131, + 0,0,0,218,6,111,98,106,101,99,116,114,168,0,0,0, + 114,165,0,0,0,114,172,0,0,0,114,187,0,0,0,114, + 195,0,0,0,114,211,0,0,0,114,219,0,0,0,114,224, + 0,0,0,114,233,0,0,0,114,225,0,0,0,114,234,0, + 0,0,114,250,0,0,0,114,252,0,0,0,114,9,1,0, + 0,114,26,1,0,0,114,167,0,0,0,114,35,1,0,0, + 114,37,1,0,0,114,4,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,8,60,109,111,100,117, + 108,101,62,8,0,0,0,115,104,0,0,0,6,17,6,3, + 12,12,12,5,12,5,12,6,12,12,12,10,12,9,12,5, + 12,7,15,22,15,108,22,1,18,2,6,1,6,2,9,2, + 9,2,10,2,21,44,12,33,12,19,12,12,12,12,18,8, + 12,27,12,18,12,15,21,55,21,12,18,10,12,14,24,22, + 9,3,12,1,15,65,19,63,19,27,22,110,19,41,25,43, + 25,16,6,3,19,57,19,57,19,41,19,134,19,146,15,23, + 12,11,12,68, }; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -49,9 +49,9 @@ &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_GET_AITER, + &&TARGET_GET_ANEXT, + &&TARGET_BEFORE_ASYNC_WITH, &&_unknown_opcode, &&TARGET_STORE_MAP, &&TARGET_INPLACE_ADD, @@ -72,7 +72,7 @@ &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_YIELD_FROM, - &&_unknown_opcode, + &&TARGET_GET_AWAITABLE, &&_unknown_opcode, &&TARGET_INPLACE_LSHIFT, &&TARGET_INPLACE_RSHIFT, @@ -80,8 +80,8 @@ &&TARGET_INPLACE_XOR, &&TARGET_INPLACE_OR, &&TARGET_BREAK_LOOP, - &&TARGET_WITH_CLEANUP, - &&_unknown_opcode, + &&TARGET_WITH_CLEANUP_START, + &&TARGET_WITH_CLEANUP_FINISH, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&_unknown_opcode, @@ -153,7 +153,7 @@ &&TARGET_BUILD_MAP_UNPACK_WITH_CALL, &&TARGET_BUILD_TUPLE_UNPACK, &&TARGET_BUILD_SET_UNPACK, - &&_unknown_opcode, + &&TARGET_SETUP_ASYNC_WITH, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/peephole.c b/Python/peephole.c --- a/Python/peephole.c +++ b/Python/peephole.c @@ -319,6 +319,7 @@ case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: + case SETUP_ASYNC_WITH: j = GETJUMPTGT(code, i); blocks[j] = 1; break; @@ -620,6 +621,7 @@ case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: + case SETUP_ASYNC_WITH: tgt = GETJUMPTGT(codestr, i); /* Replace JUMP_* to a RETURN into just a RETURN */ if (UNCONDITIONAL_JUMP(opcode) && @@ -704,6 +706,7 @@ case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: + case SETUP_ASYNC_WITH: j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3; SETARG(codestr, i, j); break; diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -212,6 +212,8 @@ tstate->on_delete = NULL; tstate->on_delete_data = NULL; + tstate->coroutine_wrapper = NULL; + if (init) _PyThreadState_Init(tstate); @@ -372,6 +374,8 @@ tstate->c_tracefunc = NULL; Py_CLEAR(tstate->c_profileobj); Py_CLEAR(tstate->c_traceobj); + + Py_CLEAR(tstate->coroutine_wrapper); } diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -180,7 +180,7 @@ static int symtable_visit_params(struct symtable *st, asdl_seq *args); static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args); static int symtable_implicit_arg(struct symtable *st, int pos); -static int symtable_visit_annotations(struct symtable *st, stmt_ty s); +static int symtable_visit_annotations(struct symtable *st, stmt_ty s, arguments_ty, expr_ty); static int symtable_visit_withitem(struct symtable *st, withitem_ty item); @@ -1147,7 +1147,8 @@ VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s)) + if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args, + s->v.FunctionDef.returns)) VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); @@ -1315,6 +1316,39 @@ VISIT_SEQ(st, withitem, s->v.With.items); VISIT_SEQ(st, stmt, s->v.With.body); break; + case AsyncFunctionDef_kind: + if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL)) + VISIT_QUIT(st, 0); + if (s->v.AsyncFunctionDef.args->defaults) + VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults); + if (s->v.AsyncFunctionDef.args->kw_defaults) + VISIT_SEQ_WITH_NULL(st, expr, + s->v.AsyncFunctionDef.args->kw_defaults); + if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args, + s->v.AsyncFunctionDef.returns)) + VISIT_QUIT(st, 0); + if (s->v.AsyncFunctionDef.decorator_list) + VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list); + if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name, + FunctionBlock, (void *)s, s->lineno, + s->col_offset)) + VISIT_QUIT(st, 0); + VISIT(st, arguments, s->v.AsyncFunctionDef.args); + VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body); + if (!symtable_exit_block(st, s)) + VISIT_QUIT(st, 0); + break; + case AsyncWith_kind: + VISIT_SEQ(st, withitem, s->v.AsyncWith.items); + VISIT_SEQ(st, stmt, s->v.AsyncWith.body); + break; + case AsyncFor_kind: + VISIT(st, expr, s->v.AsyncFor.target); + VISIT(st, expr, s->v.AsyncFor.iter); + VISIT_SEQ(st, stmt, s->v.AsyncFor.body); + if (s->v.AsyncFor.orelse) + VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse); + break; } VISIT_QUIT(st, 1); } @@ -1392,6 +1426,10 @@ VISIT(st, expr, e->v.YieldFrom.value); st->st_cur->ste_generator = 1; break; + case Await_kind: + VISIT(st, expr, e->v.Await.value); + st->st_cur->ste_generator = 1; + break; case Compare_kind: VISIT(st, expr, e->v.Compare.left); VISIT_SEQ(st, expr, e->v.Compare.comparators); @@ -1492,10 +1530,9 @@ } static int -symtable_visit_annotations(struct symtable *st, stmt_ty s) +symtable_visit_annotations(struct symtable *st, stmt_ty s, + arguments_ty a, expr_ty returns) { - arguments_ty a = s->v.FunctionDef.args; - if (a->args && !symtable_visit_argannotations(st, a->args)) return 0; if (a->vararg && a->vararg->annotation) @@ -1504,7 +1541,7 @@ VISIT(st, expr, a->kwarg->annotation); if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) return 0; - if (s->v.FunctionDef.returns) + if (returns) VISIT(st, expr, s->v.FunctionDef.returns); return 1; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -645,6 +645,49 @@ return Py_None; } +static PyObject * +sys_set_coroutine_wrapper(PyObject *self, PyObject *wrapper) +{ + if (wrapper != Py_None) { + if (!PyCallable_Check(wrapper)) { + PyErr_Format(PyExc_TypeError, + "callable expected, got %.50s", + Py_TYPE(wrapper)->tp_name); + return NULL; + } + + PyEval_SetCoroutineWrapper(wrapper); + } + else + PyEval_SetCoroutineWrapper(NULL); + Py_INCREF(Py_None); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(set_coroutine_wrapper_doc, +"set_coroutine_wrapper(wrapper)\n\ +\n\ +Set a wrapper for coroutine objects." +); + +static PyObject * +sys_get_coroutine_wrapper(PyObject *self, PyObject *args) +{ + PyObject *wrapper = PyEval_GetCoroutineWrapper(); + if (wrapper == NULL) { + wrapper = Py_None; + } + Py_INCREF(wrapper); + return wrapper; +} + +PyDoc_STRVAR(get_coroutine_wrapper_doc, +"get_coroutine_wrapper()\n\ +\n\ +Return the wrapper for coroutine objects set by sys.set_coroutine_wrapper." +); + + static PyTypeObject Hash_InfoType; PyDoc_STRVAR(hash_info_doc, @@ -1215,6 +1258,10 @@ {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, {"_debugmallocstats", sys_debugmallocstats, METH_NOARGS, debugmallocstats_doc}, + {"set_coroutine_wrapper", sys_set_coroutine_wrapper, METH_O, + set_coroutine_wrapper_doc}, + {"get_coroutine_wrapper", sys_get_coroutine_wrapper, METH_NOARGS, + get_coroutine_wrapper_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -138,6 +138,14 @@ self.fill("nonlocal ") interleave(lambda: self.write(", "), self.write, t.names) + def _Await(self, t): + self.write("(") + self.write("await") + if t.value: + self.write(" ") + self.dispatch(t.value) + self.write(")") + def _Yield(self, t): self.write("(") self.write("yield") @@ -218,11 +226,18 @@ self.leave() def _FunctionDef(self, t): + self.__FunctionDef_helper(t, "def") + + def _AsyncFunctionDef(self, t): + self.__FunctionDef_helper(t, "async def") + + def __FunctionDef_helper(self, t, fill_suffix): self.write("\n") for deco in t.decorator_list: self.fill("@") self.dispatch(deco) - self.fill("def "+t.name + "(") + def_str = fill_suffix+" "+t.name + "(" + self.fill(def_str) self.dispatch(t.args) self.write(")") if t.returns: @@ -233,7 +248,13 @@ self.leave() def _For(self, t): - self.fill("for ") + self.__For_helper("for ", t) + + def _AsyncFor(self, t): + self.__For_helper("async for ", t) + + def __For_helper(self, fill, t): + self.fill(fill) self.dispatch(t.target) self.write(" in ") self.dispatch(t.iter) @@ -287,6 +308,13 @@ self.dispatch(t.body) self.leave() + def _AsyncWith(self, t): + self.fill("async with ") + interleave(lambda: self.write(", "), self.dispatch, t.items) + self.enter() + self.dispatch(t.body) + self.leave() + # expr def _Bytes(self, t): self.write(repr(t.s)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 05:20:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:20:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_warnings_for_PyEval=5F?= =?utf-8?q?GetCoroutineWrapper?= Message-ID: <20150512032004.102421.75588@psf.io> https://hg.python.org/cpython/rev/49270fa4c6ad changeset: 95970:49270fa4c6ad user: Yury Selivanov date: Mon May 11 23:19:34 2015 -0400 summary: Fix warnings for PyEval_GetCoroutineWrapper files: Include/ceval.h | 2 +- Python/ceval.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/ceval.h b/Include/ceval.h --- a/Include/ceval.h +++ b/Include/ceval.h @@ -24,7 +24,7 @@ PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); PyAPI_FUNC(void) PyEval_SetCoroutineWrapper(PyObject *wrapper); -PyAPI_FUNC(PyObject *) PyEval_GetCoroutineWrapper(); +PyAPI_FUNC(PyObject *) PyEval_GetCoroutineWrapper(void); #endif struct _frame; /* Avoid including frameobject.h */ diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4414,7 +4414,7 @@ } PyObject * -PyEval_GetCoroutineWrapper() +PyEval_GetCoroutineWrapper(void) { PyThreadState *tstate = PyThreadState_GET(); return tstate->coroutine_wrapper; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 05:23:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:23:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_warnings_for_gen=5Fget?= =?utf-8?b?X2l0ZXIoKQ==?= Message-ID: <20150512032309.11421.24398@psf.io> https://hg.python.org/cpython/rev/0a9a5acecdd3 changeset: 95971:0a9a5acecdd3 user: Yury Selivanov date: Mon May 11 23:23:05 2015 -0400 summary: Fix warnings for gen_get_iter() files: Objects/genobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -531,7 +531,7 @@ } Py_INCREF(gen); - return gen; + return (PyObject *)gen; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 05:34:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:34:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_pep-0492_=28status=3A_?= =?utf-8?q?final=29_=26_pep-0478=2E?= Message-ID: <20150512033427.25433.93267@psf.io> https://hg.python.org/peps/rev/6139e20c6a8b changeset: 5840:6139e20c6a8b user: Yury Selivanov date: Mon May 11 23:34:24 2015 -0400 summary: Update pep-0492 (status: final) & pep-0478. files: pep-0478.txt | 2 +- pep-0492.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -65,11 +65,11 @@ * PEP 448, additional unpacking generalizations * PEP 486, make the Python Launcher aware of virtual environments * PEP 475, retrying system calls that fail with EINTR +* PEP 492, coroutines with async and await syntax Accepted PEPs: * PEP 485, math.isclose(), a function for testing approximate equality -* PEP 492, coroutines with async and await syntax Proposed changes for 3.5: diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Yury Selivanov Discussions-To: -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 09-Apr-2015 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 05:36:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:36:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_=22Implementa?= =?utf-8?q?tion=22_section=2E?= Message-ID: <20150512033627.66031.13199@psf.io> https://hg.python.org/peps/rev/120697290e95 changeset: 5841:120697290e95 user: Yury Selivanov date: Mon May 11 23:36:23 2015 -0400 summary: pep-0492: Add "Implementation" section. files: pep-0492.txt | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1361,7 +1361,12 @@ PEP 492 was accepted by Guido, Tuesday, May 5, 2015 [14]_. -The reference implementation is tracked in issue 24017 [15]_. + +Implementation +============== + +The implementation is tracked in issue 24017 [15]_. It was +committed on May 11, 2015. References -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 05:47:15 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 03:47:15 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_differences_f?= =?utf-8?q?rom_what_was_committed=2E?= Message-ID: <20150512034715.112006.63186@psf.io> https://hg.python.org/peps/rev/35254e20f2f8 changeset: 5842:35254e20f2f8 user: Yury Selivanov date: Mon May 11 23:47:11 2015 -0400 summary: pep-0492: Fix differences from what was committed. files: pep-0492.txt | 48 ++++++++++++++++++++-------------------- 1 files changed, 24 insertions(+), 24 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -110,14 +110,14 @@ * Internally, two new code object flags were introduced: - - ``CO_COROUTINE`` is used to enable runtime detection of - *coroutines* (and migrating existing code). - - - ``CO_NATIVE_COROUTINE`` is used to mark *native coroutines* + - ``CO_COROUTINE`` is used to mark *native coroutines* (defined with new syntax.) - All coroutines have ``CO_COROUTINE``, ``CO_NATIVE_COROUTINE``, and - ``CO_GENERATOR`` flags set. + - ``CO_ITERABLE_COROUTINE`` is used to make *generator-based + coroutines* compatible with *native coroutines* (set by + `types.coroutine()`_ function). + + All coroutines have ``CO_GENERATOR`` flag set. * Regular generators, when called, return a *generator object*; similarly, coroutines return a *coroutine* object. @@ -139,13 +139,13 @@ allows interoperability between existing *generator-based coroutines* in asyncio and *native coroutines* introduced by this PEP. -The function applies ``CO_COROUTINE`` flag to generator-function's code -object, making it return a *coroutine* object. +The function applies ``CO_ITERABLE_COROUTINE`` flag to generator- +function's code object, making it return a *coroutine* object. The function can be used as a decorator, since it modifies generator- functions in-place and returns them. -Note, that the ``CO_NATIVE_COROUTINE`` flag is not applied by +Note, that the ``CO_COROUTINE`` flag is not applied by ``types.coroutine()`` to make it possible to separate *native coroutines* defined with new syntax, from *generator-based coroutines*. @@ -199,8 +199,8 @@ It is a ``TypeError`` if ``__await__`` returns anything but an iterator. -* Objects defined with CPython C API with a ``tp_await`` function, - returning an iterator (similar to ``__await__`` method). +* Objects defined with CPython C API with a ``tp_as_async->am_await`` + function, returning an *iterator* (similar to ``__await__`` method). It is a ``SyntaxError`` to use ``await`` outside of an ``async def`` function (like it is a ``SyntaxError`` to use ``yield`` outside of @@ -589,9 +589,8 @@ Differences from generators ''''''''''''''''''''''''''' -This section applies only to *native coroutines* with -``CO_NATIVE_COROUTINE`` flag, i.e. defined with the new ``async def`` -syntax. +This section applies only to *native coroutines* with ``CO_COROUTINE`` +flag, i.e. defined with the new ``async def`` syntax. **The behavior of existing *generator-based coroutines* in asyncio remains unchanged.** @@ -725,11 +724,11 @@ :Future-like object: An object with an ``__await__`` method, or a C object with - ``tp_await`` function, returning an iterator. Can be consumed by - an ``await`` expression in a coroutine. A coroutine waiting for a - Future-like object is suspended until the Future-like object's - ``__await__`` completes, and returns the result. See `Await - Expression`_ for details. + ``tp_as_async->am_await`` function, returning an *iterator*. Can be + consumed by an ``await`` expression in a coroutine. A coroutine + waiting for a Future-like object is suspended until the Future-like + object's ``__await__`` completes, and returns the result. See + `Await Expression`_ for details. :Awaitable: A *Future-like* object or a *coroutine* object. See `Await @@ -1294,14 +1293,15 @@ keyword. 2. New ``__await__`` method for Future-like objects, and new - ``tp_await`` slot in ``PyTypeObject``. + ``tp_as_async->am_await`` slot in ``PyTypeObject``. 3. New syntax for asynchronous context managers: ``async with``. And associated protocol with ``__aenter__`` and ``__aexit__`` methods. 4. New syntax for asynchronous iteration: ``async for``. And associated protocol with ``__aiter__``, ``__aexit__`` and new built- - in exception ``StopAsyncIteration``. + in exception ``StopAsyncIteration``. New ``tp_as_async->am_aiter`` + and ``tp_as_async->am_anext`` slots in ``PyTypeObject``. 5. New AST nodes: ``AsyncFunctionDef``, ``AsyncFor``, ``AsyncWith``, ``Await``. @@ -1311,7 +1311,7 @@ ``inspect.iscoroutinefunction()``, ``inspect.iscoroutine()``, and ``inspect.isawaitable()``. -7. New ``CO_COROUTINE`` and ``CO_NATIVE_COROUTINE`` bit flags for code +7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. While the list of changes and new things is not short, it is important @@ -1408,8 +1408,8 @@ Svetlov, ?ukasz Langa, Greg Ewing, Stephen J. Turnbull, Jim J. Jewett, Brett Cannon, Nick Coghlan, Steven D'Aprano, Paul Moore, Nathaniel Smith, Ethan Furman, Stefan Behnel, Paul Sokolovsky, Victor Petrovykh, -and many others for their feedback, ideas, edits, criticism, and -discussions around this PEP. +and many others for their feedback, ideas, edits, criticism, code +reviews, and discussions around this PEP. Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 06:06:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 04:06:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24017=3A_Update_NEWS?= =?utf-8?q?_file=2E?= Message-ID: <20150512040636.1947.40143@psf.io> https://hg.python.org/cpython/rev/3a3cc2b9a1b2 changeset: 95972:3a3cc2b9a1b2 user: Yury Selivanov date: Tue May 12 00:06:31 2015 -0400 summary: Issue 24017: Update NEWS file. files: Misc/NEWS | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,6 +35,8 @@ - Issue #22906: PEP 479: Change StopIteration handling inside generators. +- Issue #24017: PEP 492: Coroutines with async and await syntax. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 06:09:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 04:09:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Mention_PEP_492_in_whatsne?= =?utf-8?q?w=2E?= Message-ID: <20150512040909.8141.8865@psf.io> https://hg.python.org/cpython/rev/3b39d7a369b5 changeset: 95973:3b39d7a369b5 user: Yury Selivanov date: Tue May 12 00:09:05 2015 -0400 summary: Mention PEP 492 in whatsnew. files: Doc/whatsnew/3.5.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -70,6 +70,7 @@ New syntax features: * :pep:`465`, a new matrix multiplication operator: ``a @ b``. +* :pep:`492`, coroutines with async and await syntax. New library modules: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 06:15:10 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 04:15:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_doc=3A_Briefly_mention_C_A?= =?utf-8?q?PI_changes_in_whatsnew=2E?= Message-ID: <20150512041510.1941.95941@psf.io> https://hg.python.org/cpython/rev/42f3be6cf29e changeset: 95974:42f3be6cf29e user: Yury Selivanov date: Tue May 12 00:15:05 2015 -0400 summary: doc: Briefly mention C API changes in whatsnew. files: Doc/whatsnew/3.5.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -879,3 +879,6 @@ introspection, a deprecation warning now is raised for builtin type without the :attr:`__module__` attribute. Would be an AttributeError in future. (:issue:`20204`) + +* As part of PEP 492 implementation, ``tp_reserved`` slot of + ``PyTypeObject`` was replaced with ``tp_as_async`` slot. -- Repository URL: https://hg.python.org/cpython From p.f.moore at gmail.com Mon May 11 21:42:26 2015 From: p.f.moore at gmail.com (Paul Moore) Date: Mon, 11 May 2015 20:42:26 +0100 Subject: [Python-checkins] cpython (3.4): asyncio: async() function is deprecated in favour of ensure_future(). In-Reply-To: <20150511185047.84480.21325@psf.io> References: <20150511185047.84480.21325@psf.io> Message-ID: On 11 May 2015 at 19:50, yury.selivanov wrote: > https://hg.python.org/cpython/rev/b78127eafad7 > changeset: 95956:b78127eafad7 > branch: 3.4 > parent: 95953:a983d63e3321 > user: Yury Selivanov > date: Mon May 11 14:48:38 2015 -0400 > summary: > asyncio: async() function is deprecated in favour of ensure_future(). > > files: > Lib/asyncio/base_events.py | 2 +- > Lib/asyncio/tasks.py | 27 ++++- > Lib/asyncio/windows_events.py | 2 +- > Lib/test/test_asyncio/test_base_events.py | 6 +- > Lib/test/test_asyncio/test_tasks.py | 48 +++++---- > Lib/test/test_asyncio/test_windows_events.py | 2 +- > Misc/NEWS | 4 +- > 7 files changed, 57 insertions(+), 34 deletions(-) Surely this should include a doc change? Paul From solipsis at pitrou.net Tue May 12 10:40:18 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 12 May 2015 08:40:18 +0000 Subject: [Python-checkins] Daily reference leaks (42f3be6cf29e): sum=5652 Message-ID: <20150512084018.25431.65726@psf.io> results for 42f3be6cf29e on branch "default" -------------------------------------------- test_asyncio leaked [1883, 1883, 1883] references, sum=5649 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog67NH4E', '--timeout', '7200'] From python-checkins at python.org Tue May 12 12:18:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 10:18:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320173=3A_Converte?= =?utf-8?q?d_the_=5Fcodecs_module_to_Argument_Clinic=2E?= Message-ID: <20150512101805.11417.4586@psf.io> https://hg.python.org/cpython/rev/031df83dffb4 changeset: 95975:031df83dffb4 user: Serhiy Storchaka date: Tue May 12 13:15:57 2015 +0300 summary: Issue #20173: Converted the _codecs module to Argument Clinic. files: Modules/_codecsmodule.c | 1244 ++++++++-------- Modules/clinic/_codecsmodule.c.h | 1370 +++++++++++++++++- 2 files changed, 1998 insertions(+), 616 deletions(-) diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -51,16 +51,21 @@ /* --- Registry ----------------------------------------------------------- */ -PyDoc_STRVAR(register__doc__, -"register(search_function)\n\ -\n\ -Register a codec search function. Search functions are expected to take\n\ -one argument, the encoding name in all lower case letters, and either\n\ -return None, or a tuple of functions (encoder, decoder, stream_reader,\n\ -stream_writer) (or a CodecInfo object)."); +/*[clinic input] +_codecs.register + search_function: object + / -static -PyObject *codec_register(PyObject *self, PyObject *search_function) +Register a codec search function. + +Search functions are expected to take one argument, the encoding name in +all lower case letters, and either return None, or a tuple of functions +(encoder, decoder, stream_reader, stream_writer) (or a CodecInfo object). +[clinic start generated code]*/ + +static PyObject * +_codecs_register(PyModuleDef *module, PyObject *search_function) +/*[clinic end generated code: output=d17608b6ad380eb8 input=369578467955cae4]*/ { if (PyCodec_Register(search_function)) return NULL; @@ -68,79 +73,73 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(lookup__doc__, -"lookup(encoding) -> CodecInfo\n\ -\n\ -Looks up a codec tuple in the Python codec registry and returns\n\ -a CodecInfo object."); +/*[clinic input] +_codecs.lookup + encoding: str + / -static -PyObject *codec_lookup(PyObject *self, PyObject *args) +Looks up a codec tuple in the Python codec registry and returns a CodecInfo object. +[clinic start generated code]*/ + +static PyObject * +_codecs_lookup_impl(PyModuleDef *module, const char *encoding) +/*[clinic end generated code: output=798e41aff0c04ef6 input=3c572c0db3febe9c]*/ { - char *encoding; - - if (!PyArg_ParseTuple(args, "s:lookup", &encoding)) - return NULL; - return _PyCodec_Lookup(encoding); } -PyDoc_STRVAR(encode__doc__, -"encode(obj, [encoding[,errors]]) -> object\n\ -\n\ -Encodes obj using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ -handling scheme. Default is 'strict' meaning that encoding errors raise\n\ -a ValueError. Other possible values are 'ignore', 'replace' and\n\ -'xmlcharrefreplace' as well as any other name registered with\n\ -codecs.register_error that can handle ValueErrors."); +/*[clinic input] +_codecs.encode + obj: object + encoding: str(c_default="NULL") = sys.getdefaultencoding() + errors: str(c_default="NULL") = "strict" + +Encodes obj using the codec registered for encoding. + +encoding defaults to the default encoding. errors may be given to set a +different error handling scheme. Default is 'strict' meaning that encoding +errors raise a ValueError. Other possible values are 'ignore', 'replace' +and 'backslashreplace' as well as any other name registered with +codecs.register_error that can handle ValueErrors. +[clinic start generated code]*/ static PyObject * -codec_encode(PyObject *self, PyObject *args, PyObject *kwargs) +_codecs_encode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, + const char *errors) +/*[clinic end generated code: output=5c073f62249c8d7c input=2440d769df020a0e]*/ { - static char *kwlist[] = {"obj", "encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - PyObject *v; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:encode", kwlist, - &v, &encoding, &errors)) - return NULL; - if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Encode via the codec registry */ - return PyCodec_Encode(v, encoding, errors); + return PyCodec_Encode(obj, encoding, errors); } -PyDoc_STRVAR(decode__doc__, -"decode(obj, [encoding[,errors]]) -> object\n\ -\n\ -Decodes obj using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ -handling scheme. Default is 'strict' meaning that encoding errors raise\n\ -a ValueError. Other possible values are 'ignore' and 'replace'\n\ -as well as any other name registered with codecs.register_error that is\n\ -able to handle ValueErrors."); +/*[clinic input] +_codecs.decode + obj: object + encoding: str(c_default="NULL") = sys.getdefaultencoding() + errors: str(c_default="NULL") = "strict" + +Decodes obj using the codec registered for encoding. + +encoding defaults to the default encoding. errors may be given to set a +different error handling scheme. Default is 'strict' meaning that encoding +errors raise a ValueError. Other possible values are 'ignore', 'replace' +and 'backslashreplace' as well as any other name registered with +codecs.register_error that can handle ValueErrors. +[clinic start generated code]*/ static PyObject * -codec_decode(PyObject *self, PyObject *args, PyObject *kwargs) +_codecs_decode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, + const char *errors) +/*[clinic end generated code: output=c81cbf6189a7f878 input=a351e5f5baad1544]*/ { - static char *kwlist[] = {"obj", "encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - PyObject *v; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:decode", kwlist, - &v, &encoding, &errors)) - return NULL; - if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Decode via the codec registry */ - return PyCodec_Decode(v, encoding, errors); + return PyCodec_Decode(obj, encoding, errors); } /* --- Helpers ------------------------------------------------------------ */ @@ -165,51 +164,49 @@ } static -PyObject *codec_tuple(PyObject *unicode, +PyObject *codec_tuple(PyObject *decoded, Py_ssize_t len) { - PyObject *v; - if (unicode == NULL) + if (decoded == NULL) return NULL; - v = Py_BuildValue("On", unicode, len); - Py_DECREF(unicode); - return v; + return Py_BuildValue("Nn", decoded, len); } /* --- String codecs ------------------------------------------------------ */ +/*[clinic input] +_codecs.escape_decode + data: Py_buffer(accept={str, buffer}) + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -escape_decode(PyObject *self, - PyObject *args) +_codecs_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=648fa3e78d03e658 input=0018edfd99db714d]*/ { - Py_buffer pbuf; - const char *errors = NULL; - PyObject *result; - - if (!PyArg_ParseTuple(args, "s*|z:escape_decode", - &pbuf, &errors)) - return NULL; - result = codec_tuple( - PyBytes_DecodeEscape(pbuf.buf, pbuf.len, errors, 0, NULL), - pbuf.len); - PyBuffer_Release(&pbuf); - return result; + PyObject *decoded = PyBytes_DecodeEscape(data->buf, data->len, + errors, 0, NULL); + return codec_tuple(decoded, data->len); } +/*[clinic input] +_codecs.escape_encode + data: object(subclass_of='&PyBytes_Type') + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -escape_encode(PyObject *self, - PyObject *args) +_codecs_escape_encode_impl(PyModuleDef *module, PyObject *data, + const char *errors) +/*[clinic end generated code: output=fcd6f34fe4111c50 input=da9ded00992f32f2]*/ { - PyObject *str; Py_ssize_t size; Py_ssize_t newsize; - const char *errors = NULL; PyObject *v; - if (!PyArg_ParseTuple(args, "O!|z:escape_encode", - &PyBytes_Type, &str, &errors)) - return NULL; - - size = PyBytes_GET_SIZE(str); + size = PyBytes_GET_SIZE(data); if (size > PY_SSIZE_T_MAX / 4) { PyErr_SetString(PyExc_OverflowError, "string is too large to encode"); @@ -229,7 +226,7 @@ for (i = 0; i < size; i++) { /* There's at least enough room for a hex escape */ assert(newsize - (p - PyBytes_AS_STRING(v)) >= 4); - c = PyBytes_AS_STRING(str)[i]; + c = PyBytes_AS_STRING(data)[i]; if (c == '\'' || c == '\\') *p++ = '\\', *p++ = c; else if (c == '\t') @@ -257,18 +254,18 @@ } /* --- Decoder ------------------------------------------------------------ */ +/*[clinic input] +_codecs.unicode_internal_decode + obj: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ static PyObject * -unicode_internal_decode(PyObject *self, - PyObject *args) +_codecs_unicode_internal_decode_impl(PyModuleDef *module, PyObject *obj, + const char *errors) +/*[clinic end generated code: output=9fe47c2cd8807d92 input=8d57930aeda170c6]*/ { - PyObject *obj; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", - &obj, &errors)) - return NULL; - if (PyUnicode_Check(obj)) { if (PyUnicode_READY(obj) < 0) return NULL; @@ -289,120 +286,109 @@ } } +/*[clinic input] +_codecs.utf_7_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_7_decode(PyObject *self, - PyObject *args) +_codecs_utf_7_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=ca945e907e72e827 input=bc4d6247ecdb01e6]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_7_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF7Stateful(data->buf, data->len, + errors, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_8_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_8_decode(PyObject *self, - PyObject *args) +_codecs_utf_8_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=7309f9ff4ef5c9b6 input=39161d71e7422ee2]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_8_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF8Stateful(data->buf, data->len, + errors, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_16_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_16_decode(PyObject *self, - PyObject *args) +_codecs_utf_16_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=8d2fa0507d9bef2c input=f3cf01d1461007ce]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = 0; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF16Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_16_le_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_16_le_decode(PyObject *self, - PyObject *args) +_codecs_utf_16_le_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=4fd621515ef4ce18 input=a77e3bf97335d94e]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = -1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_le_decode", - &pbuf, &errors, &final)) - return NULL; - - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF16Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_16_be_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_16_be_decode(PyObject *self, - PyObject *args) +_codecs_utf_16_be_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=792f4eacb3e1fa05 input=606f69fae91b5563]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = 1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_be_decode", - &pbuf, &errors, &final)) - return NULL; - - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF16Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } @@ -413,98 +399,94 @@ being the value in effect at the end of data. */ +/*[clinic input] +_codecs.utf_16_ex_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + byteorder: int = 0 + final: int(c_default="0") = False + / +[clinic start generated code]*/ static PyObject * -utf_16_ex_decode(PyObject *self, - PyObject *args) +_codecs_utf_16_ex_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int byteorder, int final) +/*[clinic end generated code: output=f136a186dc2defa0 input=f6e7f697658c013e]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - PyObject *unicode, *tuple; - int final = 0; - Py_ssize_t consumed; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; - if (!PyArg_ParseTuple(args, "y*|zii:utf_16_ex_decode", - &pbuf, &errors, &byteorder, &final)) + PyObject *decoded = PyUnicode_DecodeUTF16Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); + if (decoded == NULL) return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (unicode == NULL) - return NULL; - tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); - Py_DECREF(unicode); - return tuple; + return Py_BuildValue("Nni", decoded, consumed, byteorder); } +/*[clinic input] +_codecs.utf_32_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_32_decode(PyObject *self, - PyObject *args) +_codecs_utf_32_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=b7635e55857e8efb input=86d4f41c6c2e763d]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = 0; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF32Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_32_le_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_32_le_decode(PyObject *self, - PyObject *args) +_codecs_utf_32_le_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=a79d1787d8ddf988 input=d18b650772d188ba]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = -1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_le_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF32Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.utf_32_be_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -utf_32_be_decode(PyObject *self, - PyObject *args) +_codecs_utf_32_be_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=a8356b0f36779981 input=19c271b5d34926d8]*/ { - Py_buffer pbuf; - const char *errors = NULL; int byteorder = 1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_be_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + /* This is overwritten unless final is true. */ + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF32Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } @@ -515,167 +497,157 @@ being the value in effect at the end of data. */ +/*[clinic input] +_codecs.utf_32_ex_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + byteorder: int = 0 + final: int(c_default="0") = False + / +[clinic start generated code]*/ static PyObject * -utf_32_ex_decode(PyObject *self, - PyObject *args) +_codecs_utf_32_ex_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int byteorder, int final) +/*[clinic end generated code: output=ab8c70977c1992f5 input=4af3e6ccfe34a076]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - PyObject *unicode, *tuple; - int final = 0; - Py_ssize_t consumed; - - if (!PyArg_ParseTuple(args, "y*|zii:utf_32_ex_decode", - &pbuf, &errors, &byteorder, &final)) + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeUTF32Stateful(data->buf, data->len, + errors, &byteorder, + final ? NULL : &consumed); + if (decoded == NULL) return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (unicode == NULL) - return NULL; - tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); - Py_DECREF(unicode); - return tuple; + return Py_BuildValue("Nni", decoded, consumed, byteorder); } +/*[clinic input] +_codecs.unicode_escape_decode + data: Py_buffer(accept={str, buffer}) + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -unicode_escape_decode(PyObject *self, - PyObject *args) +_codecs_unicode_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=d1aa63f2620c4999 input=49fd27d06813a7f5]*/ { - Py_buffer pbuf; - const char *errors = NULL; - PyObject *unicode; - - if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); + PyObject *decoded = PyUnicode_DecodeUnicodeEscape(data->buf, data->len, + errors); + return codec_tuple(decoded, data->len); } +/*[clinic input] +_codecs.raw_unicode_escape_decode + data: Py_buffer(accept={str, buffer}) + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -raw_unicode_escape_decode(PyObject *self, - PyObject *args) +_codecs_raw_unicode_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=0bf96cc182d81379 input=770903a211434ebc]*/ { - Py_buffer pbuf; - const char *errors = NULL; - PyObject *unicode; - - if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); + PyObject *decoded = PyUnicode_DecodeRawUnicodeEscape(data->buf, data->len, + errors); + return codec_tuple(decoded, data->len); } +/*[clinic input] +_codecs.latin_1_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -latin_1_decode(PyObject *self, - PyObject *args) +_codecs_latin_1_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=66b916f5055aaf13 input=5cad0f1759c618ec]*/ { - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "y*|z:latin_1_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); + PyObject *decoded = PyUnicode_DecodeLatin1(data->buf, data->len, errors); + return codec_tuple(decoded, data->len); } +/*[clinic input] +_codecs.ascii_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -ascii_decode(PyObject *self, - PyObject *args) +_codecs_ascii_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=7f213a1b5cdafc65 input=ad1106f64037bd16]*/ { - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "y*|z:ascii_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); + PyObject *decoded = PyUnicode_DecodeASCII(data->buf, data->len, errors); + return codec_tuple(decoded, data->len); } +/*[clinic input] +_codecs.charmap_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + mapping: object = NULL + / +[clinic start generated code]*/ + static PyObject * -charmap_decode(PyObject *self, - PyObject *args) +_codecs_charmap_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, PyObject *mapping) +/*[clinic end generated code: output=87d27f365098bbae input=19712ca35c5a80e2]*/ { - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - PyObject *mapping = NULL; + PyObject *decoded; - if (!PyArg_ParseTuple(args, "y*|zO:charmap_decode", - &pbuf, &errors, &mapping)) - return NULL; if (mapping == Py_None) mapping = NULL; - unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); + decoded = PyUnicode_DecodeCharmap(data->buf, data->len, mapping, errors); + return codec_tuple(decoded, data->len); } #ifdef HAVE_MBCS +/*[clinic input] +_codecs.mbcs_decode + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -mbcs_decode(PyObject *self, - PyObject *args) +_codecs_mbcs_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final) +/*[clinic end generated code: output=0ebaf3a5b20e53fa input=d492c1ca64f4fa8a]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:mbcs_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeMBCSStateful(data->buf, data->len, + errors, final ? NULL : &consumed); return codec_tuple(decoded, consumed); } +/*[clinic input] +_codecs.code_page_decode + codepage: int + data: Py_buffer + errors: str(accept={str, NoneType}) = NULL + final: int(c_default="0") = False + / +[clinic start generated code]*/ + static PyObject * -code_page_decode(PyObject *self, - PyObject *args) +_codecs_code_page_decode_impl(PyModuleDef *module, int codepage, + Py_buffer *data, const char *errors, int final) +/*[clinic end generated code: output=4318e3d9971e31ba input=4f3152a304e21d51]*/ { - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - int code_page; - - if (!PyArg_ParseTuple(args, "iy*|zi:code_page_decode", - &code_page, &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeCodePageStateful(code_page, - pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; + Py_ssize_t consumed = data->len; + PyObject *decoded = PyUnicode_DecodeCodePageStateful(code_page, + data->buf, data->len, + errors, + final ? NULL : &consumed); return codec_tuple(decoded, consumed); } @@ -683,43 +655,39 @@ /* --- Encoder ------------------------------------------------------------ */ +/*[clinic input] +_codecs.readbuffer_encode + data: Py_buffer(accept={str, buffer}) + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -readbuffer_encode(PyObject *self, - PyObject *args) +_codecs_readbuffer_encode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors) +/*[clinic end generated code: output=319cc24083299859 input=b7c322b89d4ab923]*/ { - Py_buffer pdata; - const char *data; - Py_ssize_t size; - const char *errors = NULL; - PyObject *result; - - if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode", - &pdata, &errors)) - return NULL; - data = pdata.buf; - size = pdata.len; - - result = PyBytes_FromStringAndSize(data, size); - PyBuffer_Release(&pdata); - return codec_tuple(result, size); + PyObject *result = PyBytes_FromStringAndSize(data->buf, data->len); + return codec_tuple(result, data->len); } +/*[clinic input] +_codecs.unicode_internal_encode + obj: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -unicode_internal_encode(PyObject *self, - PyObject *args) +_codecs_unicode_internal_encode_impl(PyModuleDef *module, PyObject *obj, + const char *errors) +/*[clinic end generated code: output=be08457068ad503b input=8628f0280cf5ba61]*/ { - PyObject *obj; - const char *errors = NULL; - if (PyErr_WarnEx(PyExc_DeprecationWarning, "unicode_internal codec has been deprecated", 1)) return NULL; - if (!PyArg_ParseTuple(args, "O|z:unicode_internal_encode", - &obj, &errors)) - return NULL; - if (PyUnicode_Check(obj)) { Py_UNICODE *u; Py_ssize_t len, size; @@ -741,22 +709,26 @@ PyObject *result; if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) return NULL; - result = codec_tuple(PyBytes_FromStringAndSize(view.buf, view.len), view.len); + result = codec_tuple(PyBytes_FromStringAndSize(view.buf, view.len), + view.len); PyBuffer_Release(&view); return result; } } +/*[clinic input] +_codecs.utf_7_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_7_encode(PyObject *self, - PyObject *args) +_codecs_utf_7_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=a7accc496a32b759 input=fd91a78f103b0421]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_7_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -769,16 +741,19 @@ return v; } +/*[clinic input] +_codecs.utf_8_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_8_encode(PyObject *self, - PyObject *args) +_codecs_utf_8_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=ec831d80e7aedede input=2c22d40532f071f3]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_8_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -798,17 +773,20 @@ */ +/*[clinic input] +_codecs.utf_16_encode + str: object + errors: str(accept={str, NoneType}) = NULL + byteorder: int = 0 + / +[clinic start generated code]*/ + static PyObject * -utf_16_encode(PyObject *self, - PyObject *args) +_codecs_utf_16_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, int byteorder) +/*[clinic end generated code: output=93ac58e960a9ee4d input=3935a489b2d5385e]*/ { - PyObject *str, *v; - const char *errors = NULL; - int byteorder = 0; - - if (!PyArg_ParseTuple(args, "O|zi:utf_16_encode", - &str, &errors, &byteorder)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -821,16 +799,19 @@ return v; } +/*[clinic input] +_codecs.utf_16_le_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_16_le_encode(PyObject *self, - PyObject *args) +_codecs_utf_16_le_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=422bedb8da34fb66 input=bc27df05d1d20dfe]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_16_le_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -843,16 +824,19 @@ return v; } +/*[clinic input] +_codecs.utf_16_be_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_16_be_encode(PyObject *self, - PyObject *args) +_codecs_utf_16_be_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=3aa7ee9502acdd77 input=5a69d4112763462b]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_16_be_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -872,17 +856,20 @@ */ +/*[clinic input] +_codecs.utf_32_encode + str: object + errors: str(accept={str, NoneType}) = NULL + byteorder: int = 0 + / +[clinic start generated code]*/ + static PyObject * -utf_32_encode(PyObject *self, - PyObject *args) +_codecs_utf_32_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, int byteorder) +/*[clinic end generated code: output=3e7d5a003b02baed input=434a1efa492b8d58]*/ { - PyObject *str, *v; - const char *errors = NULL; - int byteorder = 0; - - if (!PyArg_ParseTuple(args, "O|zi:utf_32_encode", - &str, &errors, &byteorder)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -895,16 +882,19 @@ return v; } +/*[clinic input] +_codecs.utf_32_le_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_32_le_encode(PyObject *self, - PyObject *args) +_codecs_utf_32_le_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=5dda641cd33dbfc2 input=dfa2d7dc78b99422]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_32_le_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -917,16 +907,19 @@ return v; } +/*[clinic input] +_codecs.utf_32_be_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -utf_32_be_encode(PyObject *self, - PyObject *args) +_codecs_utf_32_be_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=ccca8b44d91a7c7a input=4595617b18169002]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_32_be_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -939,16 +932,19 @@ return v; } +/*[clinic input] +_codecs.unicode_escape_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -unicode_escape_encode(PyObject *self, - PyObject *args) +_codecs_unicode_escape_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=389f23d2b8f8d80b input=8273506f14076912]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:unicode_escape_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -961,16 +957,19 @@ return v; } +/*[clinic input] +_codecs.raw_unicode_escape_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -raw_unicode_escape_encode(PyObject *self, - PyObject *args) +_codecs_raw_unicode_escape_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=fec4e39d6ec37a62 input=181755d5dfacef3c]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:raw_unicode_escape_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -983,16 +982,19 @@ return v; } +/*[clinic input] +_codecs.latin_1_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -latin_1_encode(PyObject *self, - PyObject *args) +_codecs_latin_1_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=ecf00eb8e48c889c input=f03f6dcf1d84bee4]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:latin_1_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -1005,16 +1007,19 @@ return v; } +/*[clinic input] +_codecs.ascii_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -ascii_encode(PyObject *self, - PyObject *args) +_codecs_ascii_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=a9d18fc6b6b91cfb input=d87e25a10a593fee]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:ascii_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -1027,17 +1032,21 @@ return v; } +/*[clinic input] +_codecs.charmap_encode + str: object + errors: str(accept={str, NoneType}) = NULL + mapping: object = NULL + / +[clinic start generated code]*/ + static PyObject * -charmap_encode(PyObject *self, - PyObject *args) +_codecs_charmap_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, PyObject *mapping) +/*[clinic end generated code: output=14ca42b83853c643 input=85f4172661e8dad9]*/ { - PyObject *str, *v; - const char *errors = NULL; - PyObject *mapping = NULL; + PyObject *v; - if (!PyArg_ParseTuple(args, "O|zO:charmap_encode", - &str, &errors, &mapping)) - return NULL; if (mapping == Py_None) mapping = NULL; @@ -1052,27 +1061,34 @@ return v; } -static PyObject* -charmap_build(PyObject *self, PyObject *args) +/*[clinic input] +_codecs.charmap_build + map: unicode + / +[clinic start generated code]*/ + +static PyObject * +_codecs_charmap_build_impl(PyModuleDef *module, PyObject *map) +/*[clinic end generated code: output=9485b58fa44afa6a input=d91a91d1717dbc6d]*/ { - PyObject *map; - if (!PyArg_ParseTuple(args, "U:charmap_build", &map)) - return NULL; return PyUnicode_BuildEncodingMap(map); } #ifdef HAVE_MBCS +/*[clinic input] +_codecs.mbcs_encode + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -mbcs_encode(PyObject *self, - PyObject *args) +_codecs_mbcs_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors) +/*[clinic end generated code: output=d1a013bc68798bd7 input=65c09ee1e4203263]*/ { - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:mbcs_encode", - &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -1085,17 +1101,20 @@ return v; } +/*[clinic input] +_codecs.code_page_encode + code_page: int + str: object + errors: str(accept={str, NoneType}) = NULL + / +[clinic start generated code]*/ + static PyObject * -code_page_encode(PyObject *self, - PyObject *args) +_codecs_code_page_encode_impl(PyModuleDef *module, int code_page, + PyObject *str, const char *errors) +/*[clinic end generated code: output=3b406618dbfbce25 input=c8562ec460c2e309]*/ { - PyObject *str, *v; - const char *errors = NULL; - int code_page; - - if (!PyArg_ParseTuple(args, "iO|z:code_page_encode", - &code_page, &str, &errors)) - return NULL; + PyObject *v; str = PyUnicode_FromObject(str); if (str == NULL || PyUnicode_READY(str) < 0) { @@ -1114,99 +1133,94 @@ /* --- Error handler registry --------------------------------------------- */ -PyDoc_STRVAR(register_error__doc__, -"register_error(errors, handler)\n\ -\n\ -Register the specified error handler under the name\n\ -errors. handler must be a callable object, that\n\ -will be called with an exception instance containing\n\ -information about the location of the encoding/decoding\n\ -error and must return a (replacement, new position) tuple."); +/*[clinic input] +_codecs.register_error + errors: str + handler: object + / -static PyObject *register_error(PyObject *self, PyObject *args) +Register the specified error handler under the name errors. + +handler must be a callable object, that will be called with an exception +instance containing information about the location of the encoding/decoding +error and must return a (replacement, new position) tuple. +[clinic start generated code]*/ + +static PyObject * +_codecs_register_error_impl(PyModuleDef *module, const char *errors, + PyObject *handler) +/*[clinic end generated code: output=be00d3b1849ce68a input=5e6709203c2e33fe]*/ { - const char *name; - PyObject *handler; - - if (!PyArg_ParseTuple(args, "sO:register_error", - &name, &handler)) - return NULL; - if (PyCodec_RegisterError(name, handler)) + if (PyCodec_RegisterError(errors, handler)) return NULL; Py_RETURN_NONE; } -PyDoc_STRVAR(lookup_error__doc__, -"lookup_error(errors) -> handler\n\ -\n\ -Return the error handler for the specified error handling name\n\ -or raise a LookupError, if no handler exists under this name."); +/*[clinic input] +_codecs.lookup_error + name: str + / -static PyObject *lookup_error(PyObject *self, PyObject *args) +lookup_error(errors) -> handler + +Return the error handler for the specified error handling name or raise a +LookupError, if no handler exists under this name. +[clinic start generated code]*/ + +static PyObject * +_codecs_lookup_error_impl(PyModuleDef *module, const char *name) +/*[clinic end generated code: output=731e6df8c83c6158 input=4775dd65e6235aba]*/ { - const char *name; - - if (!PyArg_ParseTuple(args, "s:lookup_error", - &name)) - return NULL; return PyCodec_LookupError(name); } /* --- Module API --------------------------------------------------------- */ static PyMethodDef _codecs_functions[] = { - {"register", codec_register, METH_O, - register__doc__}, - {"lookup", codec_lookup, METH_VARARGS, - lookup__doc__}, - {"encode", (PyCFunction)codec_encode, METH_VARARGS|METH_KEYWORDS, - encode__doc__}, - {"decode", (PyCFunction)codec_decode, METH_VARARGS|METH_KEYWORDS, - decode__doc__}, - {"escape_encode", escape_encode, METH_VARARGS}, - {"escape_decode", escape_decode, METH_VARARGS}, - {"utf_8_encode", utf_8_encode, METH_VARARGS}, - {"utf_8_decode", utf_8_decode, METH_VARARGS}, - {"utf_7_encode", utf_7_encode, METH_VARARGS}, - {"utf_7_decode", utf_7_decode, METH_VARARGS}, - {"utf_16_encode", utf_16_encode, METH_VARARGS}, - {"utf_16_le_encode", utf_16_le_encode, METH_VARARGS}, - {"utf_16_be_encode", utf_16_be_encode, METH_VARARGS}, - {"utf_16_decode", utf_16_decode, METH_VARARGS}, - {"utf_16_le_decode", utf_16_le_decode, METH_VARARGS}, - {"utf_16_be_decode", utf_16_be_decode, METH_VARARGS}, - {"utf_16_ex_decode", utf_16_ex_decode, METH_VARARGS}, - {"utf_32_encode", utf_32_encode, METH_VARARGS}, - {"utf_32_le_encode", utf_32_le_encode, METH_VARARGS}, - {"utf_32_be_encode", utf_32_be_encode, METH_VARARGS}, - {"utf_32_decode", utf_32_decode, METH_VARARGS}, - {"utf_32_le_decode", utf_32_le_decode, METH_VARARGS}, - {"utf_32_be_decode", utf_32_be_decode, METH_VARARGS}, - {"utf_32_ex_decode", utf_32_ex_decode, METH_VARARGS}, - {"unicode_escape_encode", unicode_escape_encode, METH_VARARGS}, - {"unicode_escape_decode", unicode_escape_decode, METH_VARARGS}, - {"unicode_internal_encode", unicode_internal_encode, METH_VARARGS}, - {"unicode_internal_decode", unicode_internal_decode, METH_VARARGS}, - {"raw_unicode_escape_encode", raw_unicode_escape_encode, METH_VARARGS}, - {"raw_unicode_escape_decode", raw_unicode_escape_decode, METH_VARARGS}, - {"latin_1_encode", latin_1_encode, METH_VARARGS}, - {"latin_1_decode", latin_1_decode, METH_VARARGS}, - {"ascii_encode", ascii_encode, METH_VARARGS}, - {"ascii_decode", ascii_decode, METH_VARARGS}, - {"charmap_encode", charmap_encode, METH_VARARGS}, - {"charmap_decode", charmap_decode, METH_VARARGS}, - {"charmap_build", charmap_build, METH_VARARGS}, - {"readbuffer_encode", readbuffer_encode, METH_VARARGS}, -#ifdef HAVE_MBCS - {"mbcs_encode", mbcs_encode, METH_VARARGS}, - {"mbcs_decode", mbcs_decode, METH_VARARGS}, - {"code_page_encode", code_page_encode, METH_VARARGS}, - {"code_page_decode", code_page_decode, METH_VARARGS}, -#endif - {"register_error", register_error, METH_VARARGS, - register_error__doc__}, - {"lookup_error", lookup_error, METH_VARARGS, - lookup_error__doc__}, + _CODECS_REGISTER_METHODDEF + _CODECS_LOOKUP_METHODDEF + _CODECS_ENCODE_METHODDEF + _CODECS_DECODE_METHODDEF + _CODECS_ESCAPE_ENCODE_METHODDEF + _CODECS_ESCAPE_DECODE_METHODDEF + _CODECS_UTF_8_ENCODE_METHODDEF + _CODECS_UTF_8_DECODE_METHODDEF + _CODECS_UTF_7_ENCODE_METHODDEF + _CODECS_UTF_7_DECODE_METHODDEF + _CODECS_UTF_16_ENCODE_METHODDEF + _CODECS_UTF_16_LE_ENCODE_METHODDEF + _CODECS_UTF_16_BE_ENCODE_METHODDEF + _CODECS_UTF_16_DECODE_METHODDEF + _CODECS_UTF_16_LE_DECODE_METHODDEF + _CODECS_UTF_16_BE_DECODE_METHODDEF + _CODECS_UTF_16_EX_DECODE_METHODDEF + _CODECS_UTF_32_ENCODE_METHODDEF + _CODECS_UTF_32_LE_ENCODE_METHODDEF + _CODECS_UTF_32_BE_ENCODE_METHODDEF + _CODECS_UTF_32_DECODE_METHODDEF + _CODECS_UTF_32_LE_DECODE_METHODDEF + _CODECS_UTF_32_BE_DECODE_METHODDEF + _CODECS_UTF_32_EX_DECODE_METHODDEF + _CODECS_UNICODE_ESCAPE_ENCODE_METHODDEF + _CODECS_UNICODE_ESCAPE_DECODE_METHODDEF + _CODECS_UNICODE_INTERNAL_ENCODE_METHODDEF + _CODECS_UNICODE_INTERNAL_DECODE_METHODDEF + _CODECS_RAW_UNICODE_ESCAPE_ENCODE_METHODDEF + _CODECS_RAW_UNICODE_ESCAPE_DECODE_METHODDEF + _CODECS_LATIN_1_ENCODE_METHODDEF + _CODECS_LATIN_1_DECODE_METHODDEF + _CODECS_ASCII_ENCODE_METHODDEF + _CODECS_ASCII_DECODE_METHODDEF + _CODECS_CHARMAP_ENCODE_METHODDEF + _CODECS_CHARMAP_DECODE_METHODDEF + _CODECS_CHARMAP_BUILD_METHODDEF + _CODECS_READBUFFER_ENCODE_METHODDEF + _CODECS_MBCS_ENCODE_METHODDEF + _CODECS_MBCS_DECODE_METHODDEF + _CODECS_CODE_PAGE_ENCODE_METHODDEF + _CODECS_CODE_PAGE_DECODE_METHODDEF + _CODECS_REGISTER_ERROR_METHODDEF + _CODECS_LOOKUP_ERROR_METHODDEF _CODECS__FORGET_CODEC_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -2,6 +2,121 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(_codecs_register__doc__, +"register($module, search_function, /)\n" +"--\n" +"\n" +"Register a codec search function.\n" +"\n" +"Search functions are expected to take one argument, the encoding name in\n" +"all lower case letters, and either return None, or a tuple of functions\n" +"(encoder, decoder, stream_reader, stream_writer) (or a CodecInfo object)."); + +#define _CODECS_REGISTER_METHODDEF \ + {"register", (PyCFunction)_codecs_register, METH_O, _codecs_register__doc__}, + +PyDoc_STRVAR(_codecs_lookup__doc__, +"lookup($module, encoding, /)\n" +"--\n" +"\n" +"Looks up a codec tuple in the Python codec registry and returns a CodecInfo object."); + +#define _CODECS_LOOKUP_METHODDEF \ + {"lookup", (PyCFunction)_codecs_lookup, METH_O, _codecs_lookup__doc__}, + +static PyObject * +_codecs_lookup_impl(PyModuleDef *module, const char *encoding); + +static PyObject * +_codecs_lookup(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *encoding; + + if (!PyArg_Parse(arg, "s:lookup", &encoding)) + goto exit; + return_value = _codecs_lookup_impl(module, encoding); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_encode__doc__, +"encode($module, /, obj, encoding=sys.getdefaultencoding(),\n" +" errors=\'strict\')\n" +"--\n" +"\n" +"Encodes obj using the codec registered for encoding.\n" +"\n" +"encoding defaults to the default encoding. errors may be given to set a\n" +"different error handling scheme. Default is \'strict\' meaning that encoding\n" +"errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" +"and \'backslashreplace\' as well as any other name registered with\n" +"codecs.register_error that can handle ValueErrors."); + +#define _CODECS_ENCODE_METHODDEF \ + {"encode", (PyCFunction)_codecs_encode, METH_VARARGS|METH_KEYWORDS, _codecs_encode__doc__}, + +static PyObject * +_codecs_encode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, + const char *errors); + +static PyObject * +_codecs_encode(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"obj", "encoding", "errors", NULL}; + PyObject *obj; + const char *encoding = NULL; + const char *errors = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:encode", _keywords, + &obj, &encoding, &errors)) + goto exit; + return_value = _codecs_encode_impl(module, obj, encoding, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_decode__doc__, +"decode($module, /, obj, encoding=sys.getdefaultencoding(),\n" +" errors=\'strict\')\n" +"--\n" +"\n" +"Decodes obj using the codec registered for encoding.\n" +"\n" +"encoding defaults to the default encoding. errors may be given to set a\n" +"different error handling scheme. Default is \'strict\' meaning that encoding\n" +"errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" +"and \'backslashreplace\' as well as any other name registered with\n" +"codecs.register_error that can handle ValueErrors."); + +#define _CODECS_DECODE_METHODDEF \ + {"decode", (PyCFunction)_codecs_decode, METH_VARARGS|METH_KEYWORDS, _codecs_decode__doc__}, + +static PyObject * +_codecs_decode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, + const char *errors); + +static PyObject * +_codecs_decode(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"obj", "encoding", "errors", NULL}; + PyObject *obj; + const char *encoding = NULL; + const char *errors = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:decode", _keywords, + &obj, &encoding, &errors)) + goto exit; + return_value = _codecs_decode_impl(module, obj, encoding, errors); + +exit: + return return_value; +} + PyDoc_STRVAR(_codecs__forget_codec__doc__, "_forget_codec($module, encoding, /)\n" "--\n" @@ -27,4 +142,1257 @@ exit: return return_value; } -/*[clinic end generated code: output=52cc017e06c8ef9a input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_codecs_escape_decode__doc__, +"escape_decode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_ESCAPE_DECODE_METHODDEF \ + {"escape_decode", (PyCFunction)_codecs_escape_decode, METH_VARARGS, _codecs_escape_decode__doc__}, + +static PyObject * +_codecs_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_escape_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "s*|z:escape_decode", + &data, &errors)) + goto exit; + return_value = _codecs_escape_decode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_escape_encode__doc__, +"escape_encode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_ESCAPE_ENCODE_METHODDEF \ + {"escape_encode", (PyCFunction)_codecs_escape_encode, METH_VARARGS, _codecs_escape_encode__doc__}, + +static PyObject * +_codecs_escape_encode_impl(PyModuleDef *module, PyObject *data, + const char *errors); + +static PyObject * +_codecs_escape_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *data; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O!|z:escape_encode", + &PyBytes_Type, &data, &errors)) + goto exit; + return_value = _codecs_escape_encode_impl(module, data, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_unicode_internal_decode__doc__, +"unicode_internal_decode($module, obj, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UNICODE_INTERNAL_DECODE_METHODDEF \ + {"unicode_internal_decode", (PyCFunction)_codecs_unicode_internal_decode, METH_VARARGS, _codecs_unicode_internal_decode__doc__}, + +static PyObject * +_codecs_unicode_internal_decode_impl(PyModuleDef *module, PyObject *obj, + const char *errors); + +static PyObject * +_codecs_unicode_internal_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *obj; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", + &obj, &errors)) + goto exit; + return_value = _codecs_unicode_internal_decode_impl(module, obj, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_7_decode__doc__, +"utf_7_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_7_DECODE_METHODDEF \ + {"utf_7_decode", (PyCFunction)_codecs_utf_7_decode, METH_VARARGS, _codecs_utf_7_decode__doc__}, + +static PyObject * +_codecs_utf_7_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_7_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_7_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_7_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_8_decode__doc__, +"utf_8_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_8_DECODE_METHODDEF \ + {"utf_8_decode", (PyCFunction)_codecs_utf_8_decode, METH_VARARGS, _codecs_utf_8_decode__doc__}, + +static PyObject * +_codecs_utf_8_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_8_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_8_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_8_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_decode__doc__, +"utf_16_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_DECODE_METHODDEF \ + {"utf_16_decode", (PyCFunction)_codecs_utf_16_decode, METH_VARARGS, _codecs_utf_16_decode__doc__}, + +static PyObject * +_codecs_utf_16_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_16_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_16_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_16_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_le_decode__doc__, +"utf_16_le_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_LE_DECODE_METHODDEF \ + {"utf_16_le_decode", (PyCFunction)_codecs_utf_16_le_decode, METH_VARARGS, _codecs_utf_16_le_decode__doc__}, + +static PyObject * +_codecs_utf_16_le_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_16_le_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_16_le_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_16_le_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_be_decode__doc__, +"utf_16_be_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_BE_DECODE_METHODDEF \ + {"utf_16_be_decode", (PyCFunction)_codecs_utf_16_be_decode, METH_VARARGS, _codecs_utf_16_be_decode__doc__}, + +static PyObject * +_codecs_utf_16_be_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_16_be_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_16_be_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_16_be_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_ex_decode__doc__, +"utf_16_ex_decode($module, data, errors=None, byteorder=0, final=False,\n" +" /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_EX_DECODE_METHODDEF \ + {"utf_16_ex_decode", (PyCFunction)_codecs_utf_16_ex_decode, METH_VARARGS, _codecs_utf_16_ex_decode__doc__}, + +static PyObject * +_codecs_utf_16_ex_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int byteorder, int final); + +static PyObject * +_codecs_utf_16_ex_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int byteorder = 0; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zii:utf_16_ex_decode", + &data, &errors, &byteorder, &final)) + goto exit; + return_value = _codecs_utf_16_ex_decode_impl(module, &data, errors, byteorder, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_decode__doc__, +"utf_32_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_DECODE_METHODDEF \ + {"utf_32_decode", (PyCFunction)_codecs_utf_32_decode, METH_VARARGS, _codecs_utf_32_decode__doc__}, + +static PyObject * +_codecs_utf_32_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_32_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_32_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_32_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_le_decode__doc__, +"utf_32_le_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_LE_DECODE_METHODDEF \ + {"utf_32_le_decode", (PyCFunction)_codecs_utf_32_le_decode, METH_VARARGS, _codecs_utf_32_le_decode__doc__}, + +static PyObject * +_codecs_utf_32_le_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_32_le_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_32_le_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_32_le_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_be_decode__doc__, +"utf_32_be_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_BE_DECODE_METHODDEF \ + {"utf_32_be_decode", (PyCFunction)_codecs_utf_32_be_decode, METH_VARARGS, _codecs_utf_32_be_decode__doc__}, + +static PyObject * +_codecs_utf_32_be_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_utf_32_be_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:utf_32_be_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_utf_32_be_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_ex_decode__doc__, +"utf_32_ex_decode($module, data, errors=None, byteorder=0, final=False,\n" +" /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_EX_DECODE_METHODDEF \ + {"utf_32_ex_decode", (PyCFunction)_codecs_utf_32_ex_decode, METH_VARARGS, _codecs_utf_32_ex_decode__doc__}, + +static PyObject * +_codecs_utf_32_ex_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int byteorder, int final); + +static PyObject * +_codecs_utf_32_ex_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int byteorder = 0; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zii:utf_32_ex_decode", + &data, &errors, &byteorder, &final)) + goto exit; + return_value = _codecs_utf_32_ex_decode_impl(module, &data, errors, byteorder, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_unicode_escape_decode__doc__, +"unicode_escape_decode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UNICODE_ESCAPE_DECODE_METHODDEF \ + {"unicode_escape_decode", (PyCFunction)_codecs_unicode_escape_decode, METH_VARARGS, _codecs_unicode_escape_decode__doc__}, + +static PyObject * +_codecs_unicode_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_unicode_escape_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode", + &data, &errors)) + goto exit; + return_value = _codecs_unicode_escape_decode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_raw_unicode_escape_decode__doc__, +"raw_unicode_escape_decode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_RAW_UNICODE_ESCAPE_DECODE_METHODDEF \ + {"raw_unicode_escape_decode", (PyCFunction)_codecs_raw_unicode_escape_decode, METH_VARARGS, _codecs_raw_unicode_escape_decode__doc__}, + +static PyObject * +_codecs_raw_unicode_escape_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_raw_unicode_escape_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode", + &data, &errors)) + goto exit; + return_value = _codecs_raw_unicode_escape_decode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_latin_1_decode__doc__, +"latin_1_decode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_LATIN_1_DECODE_METHODDEF \ + {"latin_1_decode", (PyCFunction)_codecs_latin_1_decode, METH_VARARGS, _codecs_latin_1_decode__doc__}, + +static PyObject * +_codecs_latin_1_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_latin_1_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "y*|z:latin_1_decode", + &data, &errors)) + goto exit; + return_value = _codecs_latin_1_decode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_ascii_decode__doc__, +"ascii_decode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_ASCII_DECODE_METHODDEF \ + {"ascii_decode", (PyCFunction)_codecs_ascii_decode, METH_VARARGS, _codecs_ascii_decode__doc__}, + +static PyObject * +_codecs_ascii_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_ascii_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "y*|z:ascii_decode", + &data, &errors)) + goto exit; + return_value = _codecs_ascii_decode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_charmap_decode__doc__, +"charmap_decode($module, data, errors=None, mapping=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_CHARMAP_DECODE_METHODDEF \ + {"charmap_decode", (PyCFunction)_codecs_charmap_decode, METH_VARARGS, _codecs_charmap_decode__doc__}, + +static PyObject * +_codecs_charmap_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, PyObject *mapping); + +static PyObject * +_codecs_charmap_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + PyObject *mapping = NULL; + + if (!PyArg_ParseTuple(args, "y*|zO:charmap_decode", + &data, &errors, &mapping)) + goto exit; + return_value = _codecs_charmap_decode_impl(module, &data, errors, mapping); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +#if defined(HAVE_MBCS) + +PyDoc_STRVAR(_codecs_mbcs_decode__doc__, +"mbcs_decode($module, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_MBCS_DECODE_METHODDEF \ + {"mbcs_decode", (PyCFunction)_codecs_mbcs_decode, METH_VARARGS, _codecs_mbcs_decode__doc__}, + +static PyObject * +_codecs_mbcs_decode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors, int final); + +static PyObject * +_codecs_mbcs_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "y*|zi:mbcs_decode", + &data, &errors, &final)) + goto exit; + return_value = _codecs_mbcs_decode_impl(module, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +#endif /* defined(HAVE_MBCS) */ + +#if defined(HAVE_MBCS) + +PyDoc_STRVAR(_codecs_code_page_decode__doc__, +"code_page_decode($module, codepage, data, errors=None, final=False, /)\n" +"--\n" +"\n"); + +#define _CODECS_CODE_PAGE_DECODE_METHODDEF \ + {"code_page_decode", (PyCFunction)_codecs_code_page_decode, METH_VARARGS, _codecs_code_page_decode__doc__}, + +static PyObject * +_codecs_code_page_decode_impl(PyModuleDef *module, int codepage, + Py_buffer *data, const char *errors, int final); + +static PyObject * +_codecs_code_page_decode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int codepage; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + int final = 0; + + if (!PyArg_ParseTuple(args, "iy*|zi:code_page_decode", + &codepage, &data, &errors, &final)) + goto exit; + return_value = _codecs_code_page_decode_impl(module, codepage, &data, errors, final); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +#endif /* defined(HAVE_MBCS) */ + +PyDoc_STRVAR(_codecs_readbuffer_encode__doc__, +"readbuffer_encode($module, data, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_READBUFFER_ENCODE_METHODDEF \ + {"readbuffer_encode", (PyCFunction)_codecs_readbuffer_encode, METH_VARARGS, _codecs_readbuffer_encode__doc__}, + +static PyObject * +_codecs_readbuffer_encode_impl(PyModuleDef *module, Py_buffer *data, + const char *errors); + +static PyObject * +_codecs_readbuffer_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_buffer data = {NULL, NULL}; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode", + &data, &errors)) + goto exit; + return_value = _codecs_readbuffer_encode_impl(module, &data, errors); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +PyDoc_STRVAR(_codecs_unicode_internal_encode__doc__, +"unicode_internal_encode($module, obj, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UNICODE_INTERNAL_ENCODE_METHODDEF \ + {"unicode_internal_encode", (PyCFunction)_codecs_unicode_internal_encode, METH_VARARGS, _codecs_unicode_internal_encode__doc__}, + +static PyObject * +_codecs_unicode_internal_encode_impl(PyModuleDef *module, PyObject *obj, + const char *errors); + +static PyObject * +_codecs_unicode_internal_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *obj; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:unicode_internal_encode", + &obj, &errors)) + goto exit; + return_value = _codecs_unicode_internal_encode_impl(module, obj, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_7_encode__doc__, +"utf_7_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_7_ENCODE_METHODDEF \ + {"utf_7_encode", (PyCFunction)_codecs_utf_7_encode, METH_VARARGS, _codecs_utf_7_encode__doc__}, + +static PyObject * +_codecs_utf_7_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_7_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_7_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_7_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_8_encode__doc__, +"utf_8_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_8_ENCODE_METHODDEF \ + {"utf_8_encode", (PyCFunction)_codecs_utf_8_encode, METH_VARARGS, _codecs_utf_8_encode__doc__}, + +static PyObject * +_codecs_utf_8_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_8_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_8_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_8_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_encode__doc__, +"utf_16_encode($module, str, errors=None, byteorder=0, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_ENCODE_METHODDEF \ + {"utf_16_encode", (PyCFunction)_codecs_utf_16_encode, METH_VARARGS, _codecs_utf_16_encode__doc__}, + +static PyObject * +_codecs_utf_16_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, int byteorder); + +static PyObject * +_codecs_utf_16_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + int byteorder = 0; + + if (!PyArg_ParseTuple(args, "O|zi:utf_16_encode", + &str, &errors, &byteorder)) + goto exit; + return_value = _codecs_utf_16_encode_impl(module, str, errors, byteorder); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_le_encode__doc__, +"utf_16_le_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_LE_ENCODE_METHODDEF \ + {"utf_16_le_encode", (PyCFunction)_codecs_utf_16_le_encode, METH_VARARGS, _codecs_utf_16_le_encode__doc__}, + +static PyObject * +_codecs_utf_16_le_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_16_le_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_16_le_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_16_le_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_16_be_encode__doc__, +"utf_16_be_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_16_BE_ENCODE_METHODDEF \ + {"utf_16_be_encode", (PyCFunction)_codecs_utf_16_be_encode, METH_VARARGS, _codecs_utf_16_be_encode__doc__}, + +static PyObject * +_codecs_utf_16_be_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_16_be_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_16_be_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_16_be_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_encode__doc__, +"utf_32_encode($module, str, errors=None, byteorder=0, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_ENCODE_METHODDEF \ + {"utf_32_encode", (PyCFunction)_codecs_utf_32_encode, METH_VARARGS, _codecs_utf_32_encode__doc__}, + +static PyObject * +_codecs_utf_32_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, int byteorder); + +static PyObject * +_codecs_utf_32_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + int byteorder = 0; + + if (!PyArg_ParseTuple(args, "O|zi:utf_32_encode", + &str, &errors, &byteorder)) + goto exit; + return_value = _codecs_utf_32_encode_impl(module, str, errors, byteorder); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_le_encode__doc__, +"utf_32_le_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_LE_ENCODE_METHODDEF \ + {"utf_32_le_encode", (PyCFunction)_codecs_utf_32_le_encode, METH_VARARGS, _codecs_utf_32_le_encode__doc__}, + +static PyObject * +_codecs_utf_32_le_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_32_le_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_32_le_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_32_le_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_utf_32_be_encode__doc__, +"utf_32_be_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UTF_32_BE_ENCODE_METHODDEF \ + {"utf_32_be_encode", (PyCFunction)_codecs_utf_32_be_encode, METH_VARARGS, _codecs_utf_32_be_encode__doc__}, + +static PyObject * +_codecs_utf_32_be_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_utf_32_be_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:utf_32_be_encode", + &str, &errors)) + goto exit; + return_value = _codecs_utf_32_be_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_unicode_escape_encode__doc__, +"unicode_escape_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_UNICODE_ESCAPE_ENCODE_METHODDEF \ + {"unicode_escape_encode", (PyCFunction)_codecs_unicode_escape_encode, METH_VARARGS, _codecs_unicode_escape_encode__doc__}, + +static PyObject * +_codecs_unicode_escape_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_unicode_escape_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:unicode_escape_encode", + &str, &errors)) + goto exit; + return_value = _codecs_unicode_escape_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_raw_unicode_escape_encode__doc__, +"raw_unicode_escape_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_RAW_UNICODE_ESCAPE_ENCODE_METHODDEF \ + {"raw_unicode_escape_encode", (PyCFunction)_codecs_raw_unicode_escape_encode, METH_VARARGS, _codecs_raw_unicode_escape_encode__doc__}, + +static PyObject * +_codecs_raw_unicode_escape_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_raw_unicode_escape_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:raw_unicode_escape_encode", + &str, &errors)) + goto exit; + return_value = _codecs_raw_unicode_escape_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_latin_1_encode__doc__, +"latin_1_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_LATIN_1_ENCODE_METHODDEF \ + {"latin_1_encode", (PyCFunction)_codecs_latin_1_encode, METH_VARARGS, _codecs_latin_1_encode__doc__}, + +static PyObject * +_codecs_latin_1_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_latin_1_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:latin_1_encode", + &str, &errors)) + goto exit; + return_value = _codecs_latin_1_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_ascii_encode__doc__, +"ascii_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_ASCII_ENCODE_METHODDEF \ + {"ascii_encode", (PyCFunction)_codecs_ascii_encode, METH_VARARGS, _codecs_ascii_encode__doc__}, + +static PyObject * +_codecs_ascii_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_ascii_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:ascii_encode", + &str, &errors)) + goto exit; + return_value = _codecs_ascii_encode_impl(module, str, errors); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_charmap_encode__doc__, +"charmap_encode($module, str, errors=None, mapping=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_CHARMAP_ENCODE_METHODDEF \ + {"charmap_encode", (PyCFunction)_codecs_charmap_encode, METH_VARARGS, _codecs_charmap_encode__doc__}, + +static PyObject * +_codecs_charmap_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors, PyObject *mapping); + +static PyObject * +_codecs_charmap_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + PyObject *mapping = NULL; + + if (!PyArg_ParseTuple(args, "O|zO:charmap_encode", + &str, &errors, &mapping)) + goto exit; + return_value = _codecs_charmap_encode_impl(module, str, errors, mapping); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_charmap_build__doc__, +"charmap_build($module, map, /)\n" +"--\n" +"\n"); + +#define _CODECS_CHARMAP_BUILD_METHODDEF \ + {"charmap_build", (PyCFunction)_codecs_charmap_build, METH_O, _codecs_charmap_build__doc__}, + +static PyObject * +_codecs_charmap_build_impl(PyModuleDef *module, PyObject *map); + +static PyObject * +_codecs_charmap_build(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *map; + + if (!PyArg_Parse(arg, "U:charmap_build", &map)) + goto exit; + return_value = _codecs_charmap_build_impl(module, map); + +exit: + return return_value; +} + +#if defined(HAVE_MBCS) + +PyDoc_STRVAR(_codecs_mbcs_encode__doc__, +"mbcs_encode($module, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_MBCS_ENCODE_METHODDEF \ + {"mbcs_encode", (PyCFunction)_codecs_mbcs_encode, METH_VARARGS, _codecs_mbcs_encode__doc__}, + +static PyObject * +_codecs_mbcs_encode_impl(PyModuleDef *module, PyObject *str, + const char *errors); + +static PyObject * +_codecs_mbcs_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "O|z:mbcs_encode", + &str, &errors)) + goto exit; + return_value = _codecs_mbcs_encode_impl(module, str, errors); + +exit: + return return_value; +} + +#endif /* defined(HAVE_MBCS) */ + +#if defined(HAVE_MBCS) + +PyDoc_STRVAR(_codecs_code_page_encode__doc__, +"code_page_encode($module, code_page, str, errors=None, /)\n" +"--\n" +"\n"); + +#define _CODECS_CODE_PAGE_ENCODE_METHODDEF \ + {"code_page_encode", (PyCFunction)_codecs_code_page_encode, METH_VARARGS, _codecs_code_page_encode__doc__}, + +static PyObject * +_codecs_code_page_encode_impl(PyModuleDef *module, int code_page, + PyObject *str, const char *errors); + +static PyObject * +_codecs_code_page_encode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int code_page; + PyObject *str; + const char *errors = NULL; + + if (!PyArg_ParseTuple(args, "iO|z:code_page_encode", + &code_page, &str, &errors)) + goto exit; + return_value = _codecs_code_page_encode_impl(module, code_page, str, errors); + +exit: + return return_value; +} + +#endif /* defined(HAVE_MBCS) */ + +PyDoc_STRVAR(_codecs_register_error__doc__, +"register_error($module, errors, handler, /)\n" +"--\n" +"\n" +"Register the specified error handler under the name errors.\n" +"\n" +"handler must be a callable object, that will be called with an exception\n" +"instance containing information about the location of the encoding/decoding\n" +"error and must return a (replacement, new position) tuple."); + +#define _CODECS_REGISTER_ERROR_METHODDEF \ + {"register_error", (PyCFunction)_codecs_register_error, METH_VARARGS, _codecs_register_error__doc__}, + +static PyObject * +_codecs_register_error_impl(PyModuleDef *module, const char *errors, + PyObject *handler); + +static PyObject * +_codecs_register_error(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + const char *errors; + PyObject *handler; + + if (!PyArg_ParseTuple(args, "sO:register_error", + &errors, &handler)) + goto exit; + return_value = _codecs_register_error_impl(module, errors, handler); + +exit: + return return_value; +} + +PyDoc_STRVAR(_codecs_lookup_error__doc__, +"lookup_error($module, name, /)\n" +"--\n" +"\n" +"lookup_error(errors) -> handler\n" +"\n" +"Return the error handler for the specified error handling name or raise a\n" +"LookupError, if no handler exists under this name."); + +#define _CODECS_LOOKUP_ERROR_METHODDEF \ + {"lookup_error", (PyCFunction)_codecs_lookup_error, METH_O, _codecs_lookup_error__doc__}, + +static PyObject * +_codecs_lookup_error_impl(PyModuleDef *module, const char *name); + +static PyObject * +_codecs_lookup_error(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *name; + + if (!PyArg_Parse(arg, "s:lookup_error", &name)) + goto exit; + return_value = _codecs_lookup_error_impl(module, name); + +exit: + return return_value; +} + +#ifndef _CODECS_MBCS_DECODE_METHODDEF + #define _CODECS_MBCS_DECODE_METHODDEF +#endif /* !defined(_CODECS_MBCS_DECODE_METHODDEF) */ + +#ifndef _CODECS_CODE_PAGE_DECODE_METHODDEF + #define _CODECS_CODE_PAGE_DECODE_METHODDEF +#endif /* !defined(_CODECS_CODE_PAGE_DECODE_METHODDEF) */ + +#ifndef _CODECS_MBCS_ENCODE_METHODDEF + #define _CODECS_MBCS_ENCODE_METHODDEF +#endif /* !defined(_CODECS_MBCS_ENCODE_METHODDEF) */ + +#ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF + #define _CODECS_CODE_PAGE_ENCODE_METHODDEF +#endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ +/*[clinic end generated code: output=713a4081788da1bc input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 12:36:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 10:36:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323870=3A_The_ppri?= =?utf-8?q?nt_module_now_supports_all_standard_collections?= Message-ID: <20150512103626.11403.78245@psf.io> https://hg.python.org/cpython/rev/73c01323cb9b changeset: 95976:73c01323cb9b user: Serhiy Storchaka date: Tue May 12 13:35:48 2015 +0300 summary: Issue #23870: The pprint module now supports all standard collections except named tuples. files: Lib/pprint.py | 80 +++++++++++++++ Lib/test/test_pprint.py | 148 ++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+), 0 deletions(-) diff --git a/Lib/pprint.py b/Lib/pprint.py --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -404,6 +404,86 @@ """ return _safe_repr(object, context, maxlevels, level) + def _pprint_default_dict(self, object, stream, indent, allowance, context, level): + if not len(object): + stream.write(repr(object)) + return + rdf = self._repr(object.default_factory, context, level) + cls = object.__class__ + indent += len(cls.__name__) + 1 + stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) + self._pprint_dict(object, stream, indent, allowance + 1, context, level) + stream.write(')') + + _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict + + def _pprint_counter(self, object, stream, indent, allowance, context, level): + if not len(object): + stream.write(repr(object)) + return + cls = object.__class__ + stream.write(cls.__name__ + '({') + if self._indent_per_level > 1: + stream.write((self._indent_per_level - 1) * ' ') + items = object.most_common() + self._format_dict_items(items, stream, + indent + len(cls.__name__) + 1, allowance + 2, + context, level) + stream.write('})') + + _dispatch[_collections.Counter.__repr__] = _pprint_counter + + def _pprint_chain_map(self, object, stream, indent, allowance, context, level): + if not len(object.maps): + stream.write(repr(object)) + return + cls = object.__class__ + stream.write(cls.__name__ + '(') + indent += len(cls.__name__) + 1 + for i, m in enumerate(object.maps): + if i == len(object.maps) - 1: + self._format(m, stream, indent, allowance + 1, context, level) + stream.write(')') + else: + self._format(m, stream, indent, 1, context, level) + stream.write(',\n' + ' ' * indent) + + _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map + + def _pprint_deque(self, object, stream, indent, allowance, context, level): + if not len(object): + stream.write(repr(object)) + return + cls = object.__class__ + stream.write(cls.__name__ + '(') + indent += len(cls.__name__) + 1 + stream.write('[') + if object.maxlen is None: + self._format_items(object, stream, indent, allowance + 2, + context, level) + stream.write('])') + else: + self._format_items(object, stream, indent, 2, + context, level) + rml = self._repr(object.maxlen, context, level) + stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) + + _dispatch[_collections.deque.__repr__] = _pprint_deque + + def _pprint_user_dict(self, object, stream, indent, allowance, context, level): + self._format(object.data, stream, indent, allowance, context, level - 1) + + _dispatch[_collections.UserDict.__repr__] = _pprint_user_dict + + def _pprint_user_list(self, object, stream, indent, allowance, context, level): + self._format(object.data, stream, indent, allowance, context, level - 1) + + _dispatch[_collections.UserList.__repr__] = _pprint_user_list + + def _pprint_user_string(self, object, stream, indent, allowance, context, level): + self._format(object.data, stream, indent, allowance, context, level - 1) + + _dispatch[_collections.UserString.__repr__] = _pprint_user_string # Return triple (repr_string, isreadable, isrecursive). diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -843,6 +843,154 @@ [[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07' b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""") + def test_default_dict(self): + d = collections.defaultdict(int) + self.assertEqual(pprint.pformat(d, width=1), "defaultdict(, {})") + words = 'the quick brown fox jumped over a lazy dog'.split() + d = collections.defaultdict(int, zip(words, itertools.count())) + self.assertEqual(pprint.pformat(d), +"""\ +defaultdict(, + {'a': 6, + 'brown': 2, + 'dog': 8, + 'fox': 3, + 'jumped': 4, + 'lazy': 7, + 'over': 5, + 'quick': 1, + 'the': 0})""") + + def test_counter(self): + d = collections.Counter() + self.assertEqual(pprint.pformat(d, width=1), "Counter()") + d = collections.Counter('senselessness') + self.assertEqual(pprint.pformat(d, width=40), +"""\ +Counter({'s': 6, + 'e': 4, + 'n': 2, + 'l': 1})""") + + def test_chainmap(self): + d = collections.ChainMap() + self.assertEqual(pprint.pformat(d, width=1), "ChainMap({})") + words = 'the quick brown fox jumped over a lazy dog'.split() + items = list(zip(words, itertools.count())) + d = collections.ChainMap(dict(items)) + self.assertEqual(pprint.pformat(d), +"""\ +ChainMap({'a': 6, + 'brown': 2, + 'dog': 8, + 'fox': 3, + 'jumped': 4, + 'lazy': 7, + 'over': 5, + 'quick': 1, + 'the': 0})""") + d = collections.ChainMap(dict(items), collections.OrderedDict(items)) + self.assertEqual(pprint.pformat(d), +"""\ +ChainMap({'a': 6, + 'brown': 2, + 'dog': 8, + 'fox': 3, + 'jumped': 4, + 'lazy': 7, + 'over': 5, + 'quick': 1, + 'the': 0}, + OrderedDict([('the', 0), + ('quick', 1), + ('brown', 2), + ('fox', 3), + ('jumped', 4), + ('over', 5), + ('a', 6), + ('lazy', 7), + ('dog', 8)]))""") + + def test_deque(self): + d = collections.deque() + self.assertEqual(pprint.pformat(d, width=1), "deque([])") + d = collections.deque(maxlen=7) + self.assertEqual(pprint.pformat(d, width=1), "deque([], maxlen=7)") + words = 'the quick brown fox jumped over a lazy dog'.split() + d = collections.deque(zip(words, itertools.count())) + self.assertEqual(pprint.pformat(d), +"""\ +deque([('the', 0), + ('quick', 1), + ('brown', 2), + ('fox', 3), + ('jumped', 4), + ('over', 5), + ('a', 6), + ('lazy', 7), + ('dog', 8)])""") + d = collections.deque(zip(words, itertools.count()), maxlen=7) + self.assertEqual(pprint.pformat(d), +"""\ +deque([('brown', 2), + ('fox', 3), + ('jumped', 4), + ('over', 5), + ('a', 6), + ('lazy', 7), + ('dog', 8)], + maxlen=7)""") + + def test_user_dict(self): + d = collections.UserDict() + self.assertEqual(pprint.pformat(d, width=1), "{}") + words = 'the quick brown fox jumped over a lazy dog'.split() + d = collections.UserDict(zip(words, itertools.count())) + self.assertEqual(pprint.pformat(d), +"""\ +{'a': 6, + 'brown': 2, + 'dog': 8, + 'fox': 3, + 'jumped': 4, + 'lazy': 7, + 'over': 5, + 'quick': 1, + 'the': 0}""") + + def test_user_dict(self): + d = collections.UserList() + self.assertEqual(pprint.pformat(d, width=1), "[]") + words = 'the quick brown fox jumped over a lazy dog'.split() + d = collections.UserList(zip(words, itertools.count())) + self.assertEqual(pprint.pformat(d), +"""\ +[('the', 0), + ('quick', 1), + ('brown', 2), + ('fox', 3), + ('jumped', 4), + ('over', 5), + ('a', 6), + ('lazy', 7), + ('dog', 8)]""") + + def test_user_string(self): + d = collections.UserString('') + self.assertEqual(pprint.pformat(d, width=1), "''") + d = collections.UserString('the quick brown fox jumped over a lazy dog') + self.assertEqual(pprint.pformat(d, width=20), +"""\ +('the quick brown ' + 'fox jumped over ' + 'a lazy dog')""") + self.assertEqual(pprint.pformat({1: d}, width=20), +"""\ +{1: 'the quick ' + 'brown fox ' + 'jumped over a ' + 'lazy dog'}""") + class DottedPrettyPrinter(pprint.PrettyPrinter): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 13:01:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 11:01:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_compilation_on_Windo?= =?utf-8?q?ws_for_issue_=2320173=2E?= Message-ID: <20150512110059.102401.92944@psf.io> https://hg.python.org/cpython/rev/39df27d97901 changeset: 95977:39df27d97901 user: Serhiy Storchaka date: Tue May 12 14:00:22 2015 +0300 summary: Fixed compilation on Windows for issue #20173. files: Modules/_codecsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -644,7 +644,7 @@ /*[clinic end generated code: output=4318e3d9971e31ba input=4f3152a304e21d51]*/ { Py_ssize_t consumed = data->len; - PyObject *decoded = PyUnicode_DecodeCodePageStateful(code_page, + PyObject *decoded = PyUnicode_DecodeCodePageStateful(codepage, data->buf, data->len, errors, final ? NULL : &consumed); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 14:14:52 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 12 May 2015 12:14:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_493_based_on_pytho?= =?utf-8?q?n-dev_discussion?= Message-ID: <20150512121452.11926.70454@psf.io> https://hg.python.org/peps/rev/b395246d0af7 changeset: 5843:b395246d0af7 user: Nick Coghlan date: Tue May 12 22:14:44 2015 +1000 summary: Update PEP 493 based on python-dev discussion files: pep-0493.txt | 233 +++++++++++++++++++++++++++++++------- 1 files changed, 191 insertions(+), 42 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -51,70 +51,152 @@ to allow system administrators to disable the feature by default in their Standard Operating Environment definition has been determined not to work in at least some cases. The specific case of interest to the authors of this PEP -is the one where a commercial redistributor aims to provide their users with -a smoother migration path than the standard one provided by consuming the -upstream CPython 2.7 distribution directly [#]. - -.. [#] https://bugzilla.redhat.com/show_bug.cgi?id=1173041 +is the one where a commercial redistributor aims to provide their users with a +`smoother migration path `__ +than the standard one provided by consuming the upstream CPython 2.7 +distribution directly, but other potential challenges have also been pointed +out with updating embedded Python runtimes and other user level installations +of Python. Rather than allowing a plethora of mutually incompatibile migration techniques -to bloom, this PEP proposes a recommended approach for redistributors to take -when addressing this problem on behalf of their users that provides the -following capabilities: +to bloom, this PEP proposes two alternative approaches that redistributors +may take when addressing these problems. Redistributors may choose to implement +one, both, or neither of these approaches based on their assessment of the +needs of their particular userbase. -* infrastructure administrators restoring the old behaviour as part of their - standard system configuration -* redistributors restoring the old behaviour as part of their standard - platform configuration -* infrastructure administators optionally and explicitly opting in to accepting - a change in default behaviour at a future point in time as determined by their - chosen redistributor +These designs are being proposed as a recommendation for redistributors, rather +than as new upstream features, as they are needed purely to support legacy +environments migrating from older versions of Python 2.7. Neither approach +is being proposed as an upstream Python 2.7 feature, nor as a feature in any +version of Python 3 (whether published directly by the Python Software +Foundation or by a redistributor). -It aims to do this without introducing any new attack vectors that allow -the security configuration to be downgraded back to the older less secure -defaults. +Recommendation for backporting to earlier Python versions +========================================================= -This design is being proposed as a recommendation for redistributors, rather -than as a new upstream feature, as it is needed primarily to support legacy -environments migrating from older versions of Python 2.7 (The PEP authors -aren't *opposed* to this capability existing as an upstream feature, we just -don't need that ourselves - our aim is to avoid different redistributors -doing different things, not to push the change upstream). +Some redistributors, most notably Linux distributions, may choose to backport +the PEP 476 HTTPS verification changes to modified Python versions based on +earlier Python 2 maintenance releases. In these cases, a configuration +mechanism is needed that provides: -Recommendation -============== +* an opt-in model that allows the decision to enable HTTPS certificate + verification to be made independently of the decision to upgrade to the + Python version where the feature was first backported +* the ability for system administrators to set the default behaviour of Python + applications and scripts run directly in the system Python installation +* the ability for system administrators to set the default behaviour of Python + applications and scripts run in a ``virtualenv`` created virtual environment +* the ability for the redistributor to consider changing the default behaviour + of *new* installations at some point in the future without impacting existing + installations that have been explicitly configured to skip verifying HTTPS + certificates by default -To smooth the migration path to verifying HTTPS certificates by default, it is -recommended that redistributors: +The recommended solution for this scenario should also avoid introducing any +new attack vectors that don't already allow direct attacks against the system +certificate store. -* patch the ``ssl`` module to read a global configuration file when the module - is imported -* default to verifying certificates if this configuration file is not present -* support the following three modes of operation in that configuration file: +This approach should not be used for any Python installation that advertises +itself as providing Python 2.7.9 or later, as most Python users will have the +reasonable expectation that all such environments will validate HTTPS +certificates by default. + +Recommended modifications to the Python standard library +-------------------------------------------------------- + +The recommended approach to backporting the PEP 476 modifications to an earlier +point release is to implement the following changes relative to the default +PEP 476 behaviour implemented in Python 2.7.9+: + +* modify the ``ssl`` module to read a system wide configuration file when the + module is first imported into a Python process +* default to verifying HTTPS certificates if this configuration file is not + present (this preserves the upstream default behaviour in the absence of the + configuration file) +* if the ``sys.real_prefix`` attribute is defined, read the configuration + setting for virtual environments, otherwise read the configuration setting + for the system Python +* support selection between the following three modes of operation: * ensure HTTPS certificate verification is enabled * ensure HTTPS certificate verification is disabled - * delegate the decision to the redistributor modifying upstream Python + * delegate the decision to the redistributor providing this Python version -An example patch is available at [#]. - -.. [#] https://bugs.python.org/issue23857 +* set the ``ssl._create_default_https_context`` function to be an alias for + either ``ssl.create_default_context`` or ``ssl._create_unverified_context`` + based on the given configuration setting. Recommended file location ------------------------- -TBD separately for \*nix and Windows +This approach is currently only defined for \*nix system Python installations. + +The recommended configuration file name is +(to be confirmed, currently ``/etc/python/cert-verification.cfg``). + +The ``.cfg`` filename extension is recommended for consistency with the +``pyvenv.cfg`` used by the ``venv`` module in Python 3's standard library. Recommended file format ----------------------- -ConfigParser ini-style format, other details TBD +The configuration file should use a ConfigParser ini-style format with a +single section named ``[https]`` containing one required setting ``verify``, +and one optional setting ``verify_in_virtualenv``. + +Permitted values for ``verify`` and ``verify_in_virtualenv`` are: + +* ``enable``: ensure HTTPS certificate verification is enabled by default +* ``disable``: ensure HTTPS certificate verification is disabled by default +* ``platform_default``: delegate the decision to the redistributor providing + this particular Python version + +If the ``[https]`` section or the ``verify`` setting are missing, or if the +``verify`` setting is set to an unknown value, it should be treated as if the +configuration file is not present. + +If ``sys.real_prefix`` is set, and the ``verify_in_virtualenv`` setting is +present and set to one of the known options, then it should be used in +preference to the ``verify`` setting. + +Example implementation +---------------------- + +:: + + def _get_https_context_factory(): + config_file = '/etc/python/cert-verification.conf' + context_factories = { + 'enable': create_default_context, + 'disable': _create_unverified_context, + 'platform_default': _create_unverified_context, # For now :) + } + # Check for a system-wide override of the default behaviour + import configparser + config = configparser.RawConfigParser() + config.read(config_file) + section = 'https' + try: + verify_mode = config.get('https', 'verify') + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + verify_mode = 'enable' + else: + # Check if there's a different default for a virtual environment + if hasattr(sys, "real_prefix"): + try: + verify_mode = config.get('https', 'verify_in_virtualenv') + except (ConfigParser.NoOptionError): + pass + return context_factories.get(verify_mode, create_default_context) + + _create_default_https_context = _get_https_context_factory() + Security Considerations -======================= +----------------------- -The specific recommendations here are designed to work for privileged, security -sensitive processes, being run in the following locked down configuration: +The specific recommendations for the backporting case are designed to work for +privileged, security sensitive processes, even those being run in the following +locked down configuration: * run from a locked down administrator controlled directory rather than a normal user directory (preventing ``sys.path[0]`` based privilege escalation attacks) @@ -126,7 +208,7 @@ escalation attacks) The intent is that the *only* reason HTTPS verification should be getting -turned off globally is because: +turned off system wide when using this approach is because: * an end user is running a redistributor supported version of CPython rather than running upstream CPython directly @@ -143,6 +225,73 @@ them to modify the configuration file, they're likely already in a position to attack the system certificate store directly. +Recommendation for an environment variable based security downgrade +=================================================================== + +Some redistributors may wish to provide a per-application option to disable +certificate verification in selected applications that run on or embed CPython +without needing to modify the application itself. + +In these cases, a configuration mechanism is needed that provides: + +* an opt-out model that allows certificate verification to be selectively + turned off for particular applications after upgrading to a version of + Python that verifies certificates by default +* the ability for all users to configure this setting on a per-application + basis, rather than on a per-system, or per-Python-installation basis + +This recommendation is not considered appropriate for system wide Python +installations, but may be suitable for user level Python installations and +versions of Python embedded in or bundled with particular applications. + +This approach may be used for Python installations that advertises +themselves as providing Python 2.7.9 or later. + +Recommended modifications to the Python standard library +-------------------------------------------------------- + +The recommended approach to providing a per-application configuration setting +for HTTPS certificate verification that doesn't require modifications to the +application itself is to: + +* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment + variable when the module is first imported into a Python process +* set the ``ssl._create_default_https_context`` function to be an alias for + ``ssl._create_unverified_context`` if this environment variable is present + and set to '0' +* otherwise, set the ``ssl._create_default_https_context`` function to be an + alias for ``ssl.create_default_context`` as usual + +Example implementation +---------------------- + +:: + + def _get_https_context_factory(): + config_setting = os.environ.get('PYTHONHTTPSVERIFY') + if config_setting == '0': + return _create_unverified_context + return create_default_context + + _create_default_https_context = _get_https_context_factory() + + +Security Considerations +----------------------- + +Relative to an unmodified version of CPython 2.7.9 or later, this approach +does introduce a new downgrade attack against the default security settings +that potentially allows a sufficiently determined attacker to revert Python +to the vulnerable configuration used in CPython 2.7.8 and earlier releases. +Such an attack requires the ability to modify the execution environment of +a Python process prior to the import of the ``ssl`` module. + +Redistributors should balance this marginal increase in risk against the +ability to offer a smoother migration path to their users when deciding whether +or not it is appropriate for them to implement this per-application "opt out" +model. + + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 16:00:58 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 12 May 2015 14:00:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323796=3A_peak_and?= =?utf-8?q?_read1_methods_of_BufferedReader_now_raise_ValueError?= Message-ID: <20150512140050.102419.55984@psf.io> https://hg.python.org/cpython/rev/41e9d324f10d changeset: 95978:41e9d324f10d user: Berker Peksag date: Tue May 12 17:01:05 2015 +0300 summary: Issue #23796: peak and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. files: Lib/test/test_io.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_io/bufferedio.c | 5 +++++ 3 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1191,6 +1191,14 @@ self.assertEqual(rawio._extraneous_reads, 0, "failed for {}: {} != 0".format(n, rawio._extraneous_reads)) + def test_read_on_closed(self): + # Issue #23796 + b = io.BufferedReader(io.BytesIO(b"12")) + b.read(1) + b.close() + self.assertRaises(ValueError, b.peek) + self.assertRaises(ValueError, b.read1, 1) + class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Library ------- +- Issue #23796: peak and read1 methods of BufferedReader now raise ValueError + if they called on a closed object. Patch by John Hergenroeder. + - Issue #21795: smtpd now supports the 8BITMIME extension whenever the new *decode_data* constructor argument is set to False. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -871,6 +871,8 @@ PyObject *res = NULL; CHECK_INITIALIZED(self) + CHECK_CLOSED(self, "peek of closed file") + if (!ENTER_BUFFERED(self)) return NULL; @@ -947,6 +949,9 @@ "read length must be positive"); return NULL; } + + CHECK_CLOSED(self, "read of closed file") + if (n == 0) return PyBytes_FromStringAndSize(NULL, 0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 16:08:41 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 12 May 2015 14:08:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_formatting_=26_wor?= =?utf-8?q?ding_tweaks?= Message-ID: <20150512140839.11423.68323@psf.io> https://hg.python.org/peps/rev/ac8f1092c2a6 changeset: 5844:ac8f1092c2a6 user: Nick Coghlan date: Wed May 13 00:08:31 2015 +1000 summary: PEP 493: formatting & wording tweaks files: pep-0493.txt | 20 +++++++++----------- 1 files changed, 9 insertions(+), 11 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -20,10 +20,8 @@ provide a smoother migration experience when helping their users to manage this change in Python's default behaviour. -.. note:: - - Note that this PEP is not currently accepted, so it is a *proposed* - recommendation, rather than an active one. +*Note that this PEP is not currently accepted, so it is a *proposed* +recommendation, rather than an active one.* Rationale ========= @@ -49,14 +47,14 @@ new settings process wide by monkeypatching the ``ssl`` module to restore the old behaviour. Unfortunately, the ``sitecustomize.py`` based technique proposed to allow system administrators to disable the feature by default in their -Standard Operating Environment definition has been determined not to work in -at least some cases. The specific case of interest to the authors of this PEP -is the one where a commercial redistributor aims to provide their users with a +Standard Operating Environment definition has been determined to be +insufficient in at least some cases. The specific case of interest to the +authors of this PEP is the one where a Linux distributor aims to provide +their users with a `smoother migration path `__ -than the standard one provided by consuming the upstream CPython 2.7 -distribution directly, but other potential challenges have also been pointed -out with updating embedded Python runtimes and other user level installations -of Python. +than the standard one provided by consuming upstream CPython 2.7 releases +directly, but other potential challenges have also been pointed out with +updating embedded Python runtimes and other user level installations of Python. Rather than allowing a plethora of mutually incompatibile migration techniques to bloom, this PEP proposes two alternative approaches that redistributors -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 12 16:15:05 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 12 May 2015 14:15:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzk2?= =?utf-8?q?=3A_peak_and_read1_methods_of_BufferedReader_now_raise_ValueErr?= =?utf-8?q?or?= Message-ID: <20150512141505.112004.55811@psf.io> https://hg.python.org/cpython/rev/7d722c9049ff changeset: 95979:7d722c9049ff branch: 3.4 parent: 95966:6df4045c7f85 user: Berker Peksag date: Tue May 12 17:13:56 2015 +0300 summary: Issue #23796: peak and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. files: Lib/test/test_io.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_io/bufferedio.c | 5 +++++ 3 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1115,6 +1115,14 @@ self.assertEqual(rawio._extraneous_reads, 0, "failed for {}: {} != 0".format(n, rawio._extraneous_reads)) + def test_read_on_closed(self): + # Issue #23796 + b = io.BufferedReader(io.BytesIO(b"12")) + b.read(1) + b.close() + self.assertRaises(ValueError, b.peek) + self.assertRaises(ValueError, b.read1, 1) + class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #23796: peak and read1 methods of BufferedReader now raise ValueError + if they called on a closed object. Patch by John Hergenroeder. + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks are not longer successful if the callable is None. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -889,6 +889,8 @@ PyObject *res = NULL; CHECK_INITIALIZED(self) + CHECK_CLOSED(self, "peek of closed file") + if (!PyArg_ParseTuple(args, "|n:peek", &n)) { return NULL; } @@ -963,6 +965,9 @@ "read length must be positive"); return NULL; } + + CHECK_CLOSED(self, "read of closed file") + if (n == 0) return PyBytes_FromStringAndSize(NULL, 0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 16:15:05 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 12 May 2015 14:15:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323796=3A_Null_merge=2E?= Message-ID: <20150512141505.11936.60272@psf.io> https://hg.python.org/cpython/rev/be7636fd6438 changeset: 95980:be7636fd6438 parent: 95978:41e9d324f10d parent: 95979:7d722c9049ff user: Berker Peksag date: Tue May 12 17:15:14 2015 +0300 summary: Issue #23796: Null merge. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 16:25:27 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 12 May 2015 14:25:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323983=3A_Update_the_pty_module_example=2E?= Message-ID: <20150512142527.11922.86493@psf.io> https://hg.python.org/cpython/rev/0be7c8f46378 changeset: 95982:0be7c8f46378 parent: 95980:be7636fd6438 parent: 95981:e656bece13fa user: Berker Peksag date: Tue May 12 17:25:41 2015 +0300 summary: Issue #23983: Update the pty module example. Changes: * Fixed a ResourceWarning warning * Used argparse instead of getopt files: Doc/library/pty.rst | 54 ++++++++++++++------------------ 1 files changed, 23 insertions(+), 31 deletions(-) diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -58,40 +58,32 @@ pseudo-terminal to record all input and output of a terminal session in a "typescript". :: - import sys, os, time, getopt - import pty + import argparse + import os + import pty + import sys + import time - mode = 'wb' - shell = 'sh' - filename = 'typescript' - if 'SHELL' in os.environ: - shell = os.environ['SHELL'] + parser = argparse.ArgumentParser() + parser.add_argument('-a', dest='append', action='store_true') + parser.add_argument('-p', dest='use_python', action='store_true') + parser.add_argument('filename', nargs='?', default='typescript') + options = parser.parse_args() - try: - opts, args = getopt.getopt(sys.argv[1:], 'ap') - except getopt.error as msg: - print('%s: %s' % (sys.argv[0], msg)) - sys.exit(2) + shell = sys.executable if options.use_python else os.environ.get('SHELL', 'sh') + filename = options.filename + mode = 'ab' if options.append else 'wb' - for opt, arg in opts: - # option -a: append to typescript file - if opt == '-a': - mode = 'ab' - # option -p: use a Python shell as the terminal command - elif opt == '-p': - shell = sys.executable - if args: - filename = args[0] + with open(filename, mode) as script: + def read(fd): + data = os.read(fd, 1024) + script.write(data) + return data - script = open(filename, mode) + print('Script started, file is', filename) + script.write(('Script started on %s\n' % time.asctime()).encode()) - def read(fd): - data = os.read(fd, 1024) - script.write(data) - return data + pty.spawn(shell, read) - sys.stdout.write('Script started, file is %s\n' % filename) - script.write(('Script started on %s\n' % time.asctime()).encode()) - pty.spawn(shell, read) - script.write(('Script done on %s\n' % time.asctime()).encode()) - sys.stdout.write('Script done, file is %s\n' % filename) + script.write(('Script done on %s\n' % time.asctime()).encode()) + print('Script done, file is', filename) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 16:25:28 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 12 May 2015 14:25:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTgz?= =?utf-8?q?=3A_Update_the_pty_module_example=2E?= Message-ID: <20150512142527.7814.6428@psf.io> https://hg.python.org/cpython/rev/e656bece13fa changeset: 95981:e656bece13fa branch: 3.4 parent: 95979:7d722c9049ff user: Berker Peksag date: Tue May 12 17:25:06 2015 +0300 summary: Issue #23983: Update the pty module example. Changes: * Fixed a ResourceWarning warning * Used argparse instead of getopt files: Doc/library/pty.rst | 54 ++++++++++++++------------------ 1 files changed, 23 insertions(+), 31 deletions(-) diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -58,40 +58,32 @@ pseudo-terminal to record all input and output of a terminal session in a "typescript". :: - import sys, os, time, getopt - import pty + import argparse + import os + import pty + import sys + import time - mode = 'wb' - shell = 'sh' - filename = 'typescript' - if 'SHELL' in os.environ: - shell = os.environ['SHELL'] + parser = argparse.ArgumentParser() + parser.add_argument('-a', dest='append', action='store_true') + parser.add_argument('-p', dest='use_python', action='store_true') + parser.add_argument('filename', nargs='?', default='typescript') + options = parser.parse_args() - try: - opts, args = getopt.getopt(sys.argv[1:], 'ap') - except getopt.error as msg: - print('%s: %s' % (sys.argv[0], msg)) - sys.exit(2) + shell = sys.executable if options.use_python else os.environ.get('SHELL', 'sh') + filename = options.filename + mode = 'ab' if options.append else 'wb' - for opt, arg in opts: - # option -a: append to typescript file - if opt == '-a': - mode = 'ab' - # option -p: use a Python shell as the terminal command - elif opt == '-p': - shell = sys.executable - if args: - filename = args[0] + with open(filename, mode) as script: + def read(fd): + data = os.read(fd, 1024) + script.write(data) + return data - script = open(filename, mode) + print('Script started, file is', filename) + script.write(('Script started on %s\n' % time.asctime()).encode()) - def read(fd): - data = os.read(fd, 1024) - script.write(data) - return data + pty.spawn(shell, read) - sys.stdout.write('Script started, file is %s\n' % filename) - script.write(('Script started on %s\n' % time.asctime()).encode()) - pty.spawn(shell, read) - script.write(('Script done on %s\n' % time.asctime()).encode()) - sys.stdout.write('Script done, file is %s\n' % filename) + script.write(('Script done on %s\n' % time.asctime()).encode()) + print('Script done, file is', filename) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 17:30:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 15:30:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324017=3A_Plug_ref?= =?utf-8?q?_leak=2E?= Message-ID: <20150512153034.8141.56289@psf.io> https://hg.python.org/cpython/rev/0dc3b61f1dfa changeset: 95983:0dc3b61f1dfa user: Yury Selivanov date: Tue May 12 11:30:14 2015 -0400 summary: Issue #24017: Plug ref leak. files: Python/sysmodule.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -655,12 +655,10 @@ Py_TYPE(wrapper)->tp_name); return NULL; } - PyEval_SetCoroutineWrapper(wrapper); } else PyEval_SetCoroutineWrapper(NULL); - Py_INCREF(Py_None); Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 17:32:47 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 May 2015 15:32:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_use_our_normal_bracing_sty?= =?utf-8?q?le?= Message-ID: <20150512153245.66019.55567@psf.io> https://hg.python.org/cpython/rev/47d91697441d changeset: 95984:47d91697441d user: Benjamin Peterson date: Tue May 12 11:32:41 2015 -0400 summary: use our normal bracing style files: Python/sysmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -657,8 +657,9 @@ } PyEval_SetCoroutineWrapper(wrapper); } - else + else { PyEval_SetCoroutineWrapper(NULL); + } Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 17:45:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 15:45:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogTWFr?= =?utf-8?q?e_sure_sys=2Eset=5Fcoroutine=5Fwrapper_is_called_*only*_when_lo?= =?utf-8?q?op_is?= Message-ID: <20150512154556.1945.36369@psf.io> https://hg.python.org/cpython/rev/ee7d2c9c70ab changeset: 95985:ee7d2c9c70ab branch: 3.4 parent: 95981:e656bece13fa user: Yury Selivanov date: Tue May 12 11:43:04 2015 -0400 summary: asyncio: Make sure sys.set_coroutine_wrapper is called *only* when loop is running. Previous approach of installing coroutine wrapper in loop.set_debug() and uninstalling it in loop.close() was very fragile. Most of asyncio tests do not call loop.close() at all. Since coroutine wrapper is a global setting, we have to make sure that it's only set when the loop is running, and is automatically unset when it stops running. Issue #24017. files: Lib/asyncio/base_events.py | 80 ++++++++++++++----------- 1 files changed, 45 insertions(+), 35 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -198,6 +198,7 @@ self.slow_callback_duration = 0.1 self._current_handle = None self._task_factory = None + self._coroutine_wrapper_set = False def __repr__(self): return ('<%s running=%s closed=%s debug=%s>' @@ -291,6 +292,7 @@ self._check_closed() if self.is_running(): raise RuntimeError('Event loop is running.') + self._set_coroutine_wrapper(self._debug) self._thread_id = threading.get_ident() try: while True: @@ -300,6 +302,7 @@ break finally: self._thread_id = None + self._set_coroutine_wrapper(False) def run_until_complete(self, future): """Run until the Future is done. @@ -360,18 +363,13 @@ return if self._debug: logger.debug("Close %r", self) - try: - self._closed = True - self._ready.clear() - self._scheduled.clear() - executor = self._default_executor - if executor is not None: - self._default_executor = None - executor.shutdown(wait=False) - finally: - # It is important to unregister "sys.coroutine_wrapper" - # if it was registered. - self.set_debug(False) + self._closed = True + self._ready.clear() + self._scheduled.clear() + executor = self._default_executor + if executor is not None: + self._default_executor = None + executor.shutdown(wait=False) def is_closed(self): """Returns True if the event loop was closed.""" @@ -1199,32 +1197,44 @@ handle._run() handle = None # Needed to break cycles when an exception occurs. + def _set_coroutine_wrapper(self, enabled): + try: + set_wrapper = sys.set_coroutine_wrapper + get_wrapper = sys.get_coroutine_wrapper + except AttributeError: + return + + enabled = bool(enabled) + if self._coroutine_wrapper_set is enabled: + return + + wrapper = coroutines.debug_wrapper + current_wrapper = get_wrapper() + + if enabled: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(True): cannot set debug coroutine " + "wrapper; another wrapper is already set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(wrapper) + self._coroutine_wrapper_set = True + else: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(False): cannot unset debug coroutine " + "wrapper; another wrapper was set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(None) + self._coroutine_wrapper_set = False + def get_debug(self): return self._debug def set_debug(self, enabled): self._debug = enabled - wrapper = coroutines.debug_wrapper - try: - set_wrapper = sys.set_coroutine_wrapper - except AttributeError: - pass - else: - current_wrapper = sys.get_coroutine_wrapper() - if enabled: - if current_wrapper not in (None, wrapper): - warnings.warn( - "loop.set_debug(True): cannot set debug coroutine " - "wrapper; another wrapper is already set %r" % - current_wrapper, RuntimeWarning) - else: - set_wrapper(wrapper) - else: - if current_wrapper not in (None, wrapper): - warnings.warn( - "loop.set_debug(False): cannot unset debug coroutine " - "wrapper; another wrapper was set %r" % - current_wrapper, RuntimeWarning) - else: - set_wrapper(None) + if self.is_running(): + self._set_coroutine_wrapper(enabled) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 17:46:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 15:46:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_asyncio=3A_Make_sure_sys=2Eset=5Fcoroutine=5Fwrapper_is_?= =?utf-8?q?called_*only*_when_loop_is?= Message-ID: <20150512154556.63258.16395@psf.io> https://hg.python.org/cpython/rev/874edaa34b54 changeset: 95986:874edaa34b54 parent: 95984:47d91697441d parent: 95985:ee7d2c9c70ab user: Yury Selivanov date: Tue May 12 11:43:35 2015 -0400 summary: asyncio: Make sure sys.set_coroutine_wrapper is called *only* when loop is running. Previous approach of installing coroutine wrapper in loop.set_debug() and uninstalling it in loop.close() was very fragile. Most of asyncio tests do not call loop.close() at all. Since coroutine wrapper is a global setting, we have to make sure that it's only set when the loop is running, and is automatically unset when it stops running. Issue #24017. files: Lib/asyncio/base_events.py | 80 ++++++++++++++----------- 1 files changed, 45 insertions(+), 35 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -198,6 +198,7 @@ self.slow_callback_duration = 0.1 self._current_handle = None self._task_factory = None + self._coroutine_wrapper_set = False def __repr__(self): return ('<%s running=%s closed=%s debug=%s>' @@ -291,6 +292,7 @@ self._check_closed() if self.is_running(): raise RuntimeError('Event loop is running.') + self._set_coroutine_wrapper(self._debug) self._thread_id = threading.get_ident() try: while True: @@ -300,6 +302,7 @@ break finally: self._thread_id = None + self._set_coroutine_wrapper(False) def run_until_complete(self, future): """Run until the Future is done. @@ -360,18 +363,13 @@ return if self._debug: logger.debug("Close %r", self) - try: - self._closed = True - self._ready.clear() - self._scheduled.clear() - executor = self._default_executor - if executor is not None: - self._default_executor = None - executor.shutdown(wait=False) - finally: - # It is important to unregister "sys.coroutine_wrapper" - # if it was registered. - self.set_debug(False) + self._closed = True + self._ready.clear() + self._scheduled.clear() + executor = self._default_executor + if executor is not None: + self._default_executor = None + executor.shutdown(wait=False) def is_closed(self): """Returns True if the event loop was closed.""" @@ -1199,32 +1197,44 @@ handle._run() handle = None # Needed to break cycles when an exception occurs. + def _set_coroutine_wrapper(self, enabled): + try: + set_wrapper = sys.set_coroutine_wrapper + get_wrapper = sys.get_coroutine_wrapper + except AttributeError: + return + + enabled = bool(enabled) + if self._coroutine_wrapper_set is enabled: + return + + wrapper = coroutines.debug_wrapper + current_wrapper = get_wrapper() + + if enabled: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(True): cannot set debug coroutine " + "wrapper; another wrapper is already set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(wrapper) + self._coroutine_wrapper_set = True + else: + if current_wrapper not in (None, wrapper): + warnings.warn( + "loop.set_debug(False): cannot unset debug coroutine " + "wrapper; another wrapper was set %r" % + current_wrapper, RuntimeWarning) + else: + set_wrapper(None) + self._coroutine_wrapper_set = False + def get_debug(self): return self._debug def set_debug(self, enabled): self._debug = enabled - wrapper = coroutines.debug_wrapper - try: - set_wrapper = sys.set_coroutine_wrapper - except AttributeError: - pass - else: - current_wrapper = sys.get_coroutine_wrapper() - if enabled: - if current_wrapper not in (None, wrapper): - warnings.warn( - "loop.set_debug(True): cannot set debug coroutine " - "wrapper; another wrapper is already set %r" % - current_wrapper, RuntimeWarning) - else: - set_wrapper(wrapper) - else: - if current_wrapper not in (None, wrapper): - warnings.warn( - "loop.set_debug(False): cannot unset debug coroutine " - "wrapper; another wrapper was set %r" % - current_wrapper, RuntimeWarning) - else: - set_wrapper(None) + if self.is_running(): + self._set_coroutine_wrapper(enabled) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 20:28:32 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 12 May 2015 18:28:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324017=3A_Unset_as?= =?utf-8?q?yncio_event_loop_after_test=2E?= Message-ID: <20150512182832.8143.12041@psf.io> https://hg.python.org/cpython/rev/9d2c4d887c19 changeset: 95987:9d2c4d887c19 user: Yury Selivanov date: Tue May 12 14:28:08 2015 -0400 summary: Issue #24017: Unset asyncio event loop after test. files: Lib/test/test_coroutines.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -772,13 +772,15 @@ raise MyException buffer.append('unreachable') - loop = asyncio.get_event_loop() + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) try: loop.run_until_complete(f()) except MyException: pass finally: loop.close() + asyncio.set_event_loop(None) self.assertEqual(buffer, [1, 2, 'MyException']) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 22:13:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 20:13:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315027=3A_The_UTF-?= =?utf-8?q?32_encoder_is_now_3x_to_7x_faster=2E?= Message-ID: <20150512201306.45110.71091@psf.io> https://hg.python.org/cpython/rev/80cf7723c4cf changeset: 95988:80cf7723c4cf user: Serhiy Storchaka date: Tue May 12 23:12:45 2015 +0300 summary: Issue #15027: The UTF-32 encoder is now 3x to 7x faster. files: Doc/whatsnew/3.5.rst | 3 + Misc/NEWS | 2 + Objects/stringlib/codecs.h | 87 +++++++++++++++++++ Objects/unicodeobject.c | 110 ++++++++++-------------- 4 files changed, 137 insertions(+), 65 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -629,6 +629,9 @@ versions 0--2 on typical data, and up to 5x in best cases). (Contributed by Serhiy Storchaka in :issue:`20416` and :issue:`23344`.) +* The UTF-32 encoder is now 3x to 7x faster. (Contributed by Serhiy Storchaka + in :issue:`15027`.) + Build and C API Changes ======================= diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #15027: The UTF-32 encoder is now 3x to 7x faster. + - Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -718,6 +718,93 @@ return len - (end - in + 1); #endif } + +#if STRINGLIB_SIZEOF_CHAR == 1 +# define SWAB4(CH, tmp) ((CH) << 24) /* high bytes are zero */ +#elif STRINGLIB_SIZEOF_CHAR == 2 +# define SWAB4(CH, tmp) (tmp = (CH), \ + ((tmp & 0x00FFu) << 24) + ((tmp & 0xFF00u) << 8)) + /* high bytes are zero */ +#else +# define SWAB4(CH, tmp) (tmp = (CH), \ + tmp = ((tmp & 0x00FF00FFu) << 8) + ((tmp >> 8) & 0x00FF00FFu), \ + ((tmp & 0x0000FFFFu) << 16) + ((tmp >> 16) & 0x0000FFFFu)) +#endif +Py_LOCAL_INLINE(Py_ssize_t) +STRINGLIB(utf32_encode)(const STRINGLIB_CHAR *in, + Py_ssize_t len, + PY_UINT32_T **outptr, + int native_ordering) +{ + PY_UINT32_T *out = *outptr; + const STRINGLIB_CHAR *end = in + len; + if (native_ordering) { + const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4); + while (in < unrolled_end) { +#if STRINGLIB_SIZEOF_CHAR > 1 + /* check if any character is a surrogate character */ + if (((in[0] ^ 0xd800) & + (in[1] ^ 0xd800) & + (in[2] ^ 0xd800) & + (in[3] ^ 0xd800) & 0xf800) == 0) + break; +#endif + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + in += 4; out += 4; + } + while (in < end) { + Py_UCS4 ch; + ch = *in++; +#if STRINGLIB_SIZEOF_CHAR > 1 + if (Py_UNICODE_IS_SURROGATE(ch)) { + /* reject surrogate characters (U+DC800-U+DFFF) */ + goto fail; + } +#endif + *out++ = ch; + } + } else { + const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4); + while (in < unrolled_end) { +#if STRINGLIB_SIZEOF_CHAR > 1 + Py_UCS4 ch1, ch2, ch3, ch4; + /* check if any character is a surrogate character */ + if (((in[0] ^ 0xd800) & + (in[1] ^ 0xd800) & + (in[2] ^ 0xd800) & + (in[3] ^ 0xd800) & 0xf800) == 0) + break; +#endif + out[0] = SWAB4(in[0], ch1); + out[1] = SWAB4(in[1], ch2); + out[2] = SWAB4(in[2], ch3); + out[3] = SWAB4(in[3], ch4); + in += 4; out += 4; + } + while (in < end) { + Py_UCS4 ch = *in++; +#if STRINGLIB_SIZEOF_CHAR > 1 + if (Py_UNICODE_IS_SURROGATE(ch)) { + /* reject surrogate characters (U+DC800-U+DFFF) */ + goto fail; + } +#endif + *out++ = SWAB4(ch, ch); + } + } + *outptr = out; + return len; +#if STRINGLIB_SIZEOF_CHAR > 1 + fail: + *outptr = out; + return len - (end - in + 1); +#endif +} +#undef SWAB4 + #endif #endif /* STRINGLIB_IS_UNICODE */ diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5051,32 +5051,22 @@ const char *errors, int byteorder) { - int kind; - void *data; + enum PyUnicode_Kind kind; + const void *data; Py_ssize_t len; PyObject *v; - unsigned char *p; - Py_ssize_t nsize, i; - /* Offsets from p for storing byte pairs in the right order. */ + PY_UINT32_T *out; #if PY_LITTLE_ENDIAN - int iorder[] = {0, 1, 2, 3}; + int native_ordering = byteorder <= 0; #else - int iorder[] = {3, 2, 1, 0}; + int native_ordering = byteorder >= 0; #endif const char *encoding; + Py_ssize_t nsize, pos; PyObject *errorHandler = NULL; PyObject *exc = NULL; PyObject *rep = NULL; -#define STORECHAR(CH) \ - do { \ - p[iorder[3]] = ((CH) >> 24) & 0xff; \ - p[iorder[2]] = ((CH) >> 16) & 0xff; \ - p[iorder[1]] = ((CH) >> 8) & 0xff; \ - p[iorder[0]] = (CH) & 0xff; \ - p += 4; \ - } while(0) - if (!PyUnicode_Check(str)) { PyErr_BadArgument(); return NULL; @@ -5087,59 +5077,53 @@ data = PyUnicode_DATA(str); len = PyUnicode_GET_LENGTH(str); + if (len > PY_SSIZE_T_MAX / 4 - (byteorder == 0)) + return PyErr_NoMemory(); nsize = len + (byteorder == 0); - if (nsize > PY_SSIZE_T_MAX / 4) - return PyErr_NoMemory(); v = PyBytes_FromStringAndSize(NULL, nsize * 4); if (v == NULL) return NULL; - p = (unsigned char *)PyBytes_AS_STRING(v); + /* output buffer is 4-bytes aligned */ + assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(v), 4)); + out = (PY_UINT32_T *)PyBytes_AS_STRING(v); if (byteorder == 0) - STORECHAR(0xFEFF); + *out++ = 0xFEFF; if (len == 0) - return v; - - if (byteorder == -1) { - /* force LE */ - iorder[0] = 0; - iorder[1] = 1; - iorder[2] = 2; - iorder[3] = 3; + goto done; + + if (byteorder == -1) encoding = "utf-32-le"; - } - else if (byteorder == 1) { - /* force BE */ - iorder[0] = 3; - iorder[1] = 2; - iorder[2] = 1; - iorder[3] = 0; + else if (byteorder == 1) encoding = "utf-32-be"; - } else encoding = "utf-32"; if (kind == PyUnicode_1BYTE_KIND) { - for (i = 0; i < len; i++) - STORECHAR(PyUnicode_READ(kind, data, i)); - return v; - } - - for (i = 0; i < len;) { + ucs1lib_utf32_encode((const Py_UCS1 *)data, len, &out, native_ordering); + goto done; + } + + pos = 0; + while (pos < len) { Py_ssize_t repsize, moreunits; - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - i++; - assert(ch <= MAX_UNICODE); - if (!Py_UNICODE_IS_SURROGATE(ch)) { - STORECHAR(ch); - continue; - } + + if (kind == PyUnicode_2BYTE_KIND) { + pos += ucs2lib_utf32_encode((const Py_UCS2 *)data + pos, len - pos, + &out, native_ordering); + } + else { + assert(kind == PyUnicode_4BYTE_KIND); + pos += ucs4lib_utf32_encode((const Py_UCS4 *)data + pos, len - pos, + &out, native_ordering); + } + if (pos == len) + break; rep = unicode_encode_call_errorhandler( errors, &errorHandler, encoding, "surrogates not allowed", - str, &exc, i-1, i, &i); - + str, &exc, pos, pos + 1, &pos); if (!rep) goto error; @@ -5147,7 +5131,7 @@ repsize = PyBytes_GET_SIZE(rep); if (repsize & 3) { raise_encode_exception(&exc, encoding, - str, i - 1, i, + str, pos - 1, pos, "surrogates not allowed"); goto error; } @@ -5160,7 +5144,7 @@ moreunits = repsize = PyUnicode_GET_LENGTH(rep); if (!PyUnicode_IS_ASCII(rep)) { raise_encode_exception(&exc, encoding, - str, i - 1, i, + str, pos - 1, pos, "surrogates not allowed"); goto error; } @@ -5168,7 +5152,7 @@ /* four bytes are reserved for each surrogate */ if (moreunits > 1) { - Py_ssize_t outpos = p - (unsigned char*) PyBytes_AS_STRING(v); + Py_ssize_t outpos = out - (PY_UINT32_T*) PyBytes_AS_STRING(v); Py_ssize_t morebytes = 4 * (moreunits - 1); if (PyBytes_GET_SIZE(v) > PY_SSIZE_T_MAX - morebytes) { /* integer overflow */ @@ -5177,20 +5161,16 @@ } if (_PyBytes_Resize(&v, PyBytes_GET_SIZE(v) + morebytes) < 0) goto error; - p = (unsigned char*) PyBytes_AS_STRING(v) + outpos; + out = (PY_UINT32_T*) PyBytes_AS_STRING(v) + outpos; } if (PyBytes_Check(rep)) { - Py_MEMCPY(p, PyBytes_AS_STRING(rep), repsize); - p += repsize; + Py_MEMCPY(out, PyBytes_AS_STRING(rep), repsize); + out += moreunits; } else /* rep is unicode */ { - const Py_UCS1 *repdata; assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND); - repdata = PyUnicode_1BYTE_DATA(rep); - while (repsize--) { - Py_UCS4 ch = *repdata++; - STORECHAR(ch); - } + ucs1lib_utf32_encode(PyUnicode_1BYTE_DATA(rep), repsize, + &out, native_ordering); } Py_CLEAR(rep); @@ -5199,11 +5179,12 @@ /* Cut back to size actually needed. This is necessary for, for example, encoding of a string containing isolated surrogates and the 'ignore' handler is used. */ - nsize = p - (unsigned char*) PyBytes_AS_STRING(v); + nsize = (unsigned char*) out - (unsigned char*) PyBytes_AS_STRING(v); if (nsize != PyBytes_GET_SIZE(v)) _PyBytes_Resize(&v, nsize); Py_XDECREF(errorHandler); Py_XDECREF(exc); + done: return v; error: Py_XDECREF(rep); @@ -5211,7 +5192,6 @@ Py_XDECREF(exc); Py_XDECREF(v); return NULL; -#undef STORECHAR } PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 22:24:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 20:24:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322682=3A_Added_su?= =?utf-8?q?pport_for_the_kz1048_encoding=2E?= Message-ID: <20150512202436.120081.83313@psf.io> https://hg.python.org/cpython/rev/6e1fe5bfba48 changeset: 95989:6e1fe5bfba48 user: Serhiy Storchaka date: Tue May 12 23:16:55 2015 +0300 summary: Issue #22682: Added support for the kz1048 encoding. files: Doc/library/codecs.rst | 4 ++++ Doc/whatsnew/3.5.rst | 3 +++ Lib/encodings/aliases.py | 5 +++++ Lib/locale.py | 1 + Lib/test/test_codecs.py | 1 + Lib/test/test_unicode.py | 4 ++-- Lib/test/test_xml_etree.py | 2 +- Misc/NEWS | 2 ++ 8 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1162,6 +1162,10 @@ +-----------------+--------------------------------+--------------------------------+ | koi8_u | | Ukrainian | +-----------------+--------------------------------+--------------------------------+ +| kz1048 | kz_1048, strk1048_2002, rk1048 | Kazakh | +| | | | +| | | .. versionadded:: 3.5 | ++-----------------+--------------------------------+--------------------------------+ | mac_cyrillic | maccyrillic | Bulgarian, Byelorussian, | | | | Macedonian, Russian, Serbian | +-----------------+--------------------------------+--------------------------------+ diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -231,6 +231,9 @@ * The :option:`-b` option now affects comparisons of :class:`bytes` with :class:`int`. (Contributed by Serhiy Storchaka in :issue:`23681`) +* New Kazakh :ref:`codec ` ``kz1048``. (Contributed by + Serhiy Storchaka in :issue:`22682`.) + New Modules =========== diff --git a/Lib/encodings/aliases.py b/Lib/encodings/aliases.py --- a/Lib/encodings/aliases.py +++ b/Lib/encodings/aliases.py @@ -412,6 +412,11 @@ # koi8_r codec 'cskoi8r' : 'koi8_r', + # kz1048 codec + 'kz_1048' : 'kz1048', + 'rk1048' : 'kz1048', + 'strk1048_2002' : 'kz1048', + # latin_1 codec # # Note that the latin_1 codec is implemented internally in C and a diff --git a/Lib/locale.py b/Lib/locale.py --- a/Lib/locale.py +++ b/Lib/locale.py @@ -700,6 +700,7 @@ 'utf_8': 'UTF-8', 'koi8_r': 'KOI8-R', 'koi8_u': 'KOI8-U', + 'kz1048': 'RK1048', 'cp1251': 'CP1251', 'cp1255': 'CP1255', 'cp1256': 'CP1256', diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1823,6 +1823,7 @@ "johab", "koi8_r", "koi8_u", + "kz1048", "latin_1", "mac_cyrillic", "mac_greek", diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -2081,7 +2081,7 @@ 'cp863', 'cp865', 'cp866', 'cp1125', 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', - 'iso8859_7', 'iso8859_9', 'koi8_r', 'latin_1', + 'iso8859_7', 'iso8859_9', 'koi8_r', 'kz1048', 'latin_1', 'mac_cyrillic', 'mac_latin2', 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', @@ -2116,7 +2116,7 @@ #'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', #'cp1256', 'cp1257', 'cp1258', #'cp424', 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', - #'iso8859_3', 'iso8859_6', 'iso8859_7', + #'iso8859_3', 'iso8859_6', 'iso8859_7', 'kz1048', #'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', ### These fail the round-trip: diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -704,7 +704,7 @@ 'mac-roman', 'mac-turkish', 'iso2022-jp', 'iso2022-jp-1', 'iso2022-jp-2', 'iso2022-jp-2004', 'iso2022-jp-3', 'iso2022-jp-ext', - 'koi8-r', 'koi8-u', + 'koi8-r', 'koi8-u', 'kz1048', 'hz', 'ptcp154', ] for encoding in supported_encodings: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,8 @@ Library ------- +- Issue #22682: Added support for the kz1048 encoding. + - Issue #23796: peak and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 22:24:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 20:24:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322681=3A_Added_su?= =?utf-8?q?pport_for_the_koi8=5Ft_encoding=2E?= Message-ID: <20150512202436.13249.15004@psf.io> https://hg.python.org/cpython/rev/78de5d040492 changeset: 95990:78de5d040492 user: Serhiy Storchaka date: Tue May 12 23:24:19 2015 +0300 summary: Issue #22681: Added support for the koi8_t encoding. files: Doc/library/codecs.rst | 4 ++++ Doc/whatsnew/3.5.rst | 3 +++ Lib/locale.py | 1 + Lib/test/test_codecs.py | 1 + Lib/test/test_unicode.py | 7 ++++--- Lib/test/test_xml_etree.py | 2 +- Misc/NEWS | 2 ++ 7 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1160,6 +1160,10 @@ +-----------------+--------------------------------+--------------------------------+ | koi8_r | | Russian | +-----------------+--------------------------------+--------------------------------+ +| koi8_t | | Tajik | +| | | | +| | | .. versionadded:: 3.5 | ++-----------------+--------------------------------+--------------------------------+ | koi8_u | | Ukrainian | +-----------------+--------------------------------+--------------------------------+ | kz1048 | kz_1048, strk1048_2002, rk1048 | Kazakh | diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -234,6 +234,9 @@ * New Kazakh :ref:`codec ` ``kz1048``. (Contributed by Serhiy Storchaka in :issue:`22682`.) +* New Tajik :ref:`codec ` ``koi8_t``. (Contributed by + Serhiy Storchaka in :issue:`22681`.) + New Modules =========== diff --git a/Lib/locale.py b/Lib/locale.py --- a/Lib/locale.py +++ b/Lib/locale.py @@ -699,6 +699,7 @@ 'euc_kr': 'eucKR', 'utf_8': 'UTF-8', 'koi8_r': 'KOI8-R', + 'koi8_t': 'KOI8-T', 'koi8_u': 'KOI8-U', 'kz1048': 'RK1048', 'cp1251': 'CP1251', diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1822,6 +1822,7 @@ "iso8859_9", "johab", "koi8_r", + "koi8_t", "koi8_u", "kz1048", "latin_1", diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -2081,7 +2081,8 @@ 'cp863', 'cp865', 'cp866', 'cp1125', 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', - 'iso8859_7', 'iso8859_9', 'koi8_r', 'kz1048', 'latin_1', + 'iso8859_7', 'iso8859_9', + 'koi8_r', 'koi8_t', 'koi8_u', 'kz1048', 'latin_1', 'mac_cyrillic', 'mac_latin2', 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', @@ -2109,14 +2110,14 @@ 'cp863', 'cp865', 'cp866', 'cp1125', 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_2', 'iso8859_4', 'iso8859_5', - 'iso8859_9', 'koi8_r', 'latin_1', + 'iso8859_9', 'koi8_r', 'koi8_u', 'latin_1', 'mac_cyrillic', 'mac_latin2', ### These have undefined mappings: #'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', #'cp1256', 'cp1257', 'cp1258', #'cp424', 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', - #'iso8859_3', 'iso8859_6', 'iso8859_7', 'kz1048', + #'iso8859_3', 'iso8859_6', 'iso8859_7', 'koi8_t', 'kz1048', #'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', ### These fail the round-trip: diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -704,7 +704,7 @@ 'mac-roman', 'mac-turkish', 'iso2022-jp', 'iso2022-jp-1', 'iso2022-jp-2', 'iso2022-jp-2004', 'iso2022-jp-3', 'iso2022-jp-ext', - 'koi8-r', 'koi8-u', 'kz1048', + 'koi8-r', 'koi8-t', 'koi8-u', 'kz1048', 'hz', 'ptcp154', ] for encoding in supported_encodings: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,8 @@ Library ------- +- Issue #22681: Added support for the koi8_t encoding. + - Issue #22682: Added support for the kz1048 encoding. - Issue #23796: peak and read1 methods of BufferedReader now raise ValueError -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 23:20:23 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 21:20:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322486=3A_Added_th?= =?utf-8?q?e_math=2Egcd=28=29_function=2E__The_fractions=2Egcd=28=29_funct?= =?utf-8?q?ion_now?= Message-ID: <20150512212022.92561.87732@psf.io> https://hg.python.org/cpython/rev/34648ce02bd4 changeset: 95991:34648ce02bd4 user: Serhiy Storchaka date: Wed May 13 00:19:51 2015 +0300 summary: Issue #22486: Added the math.gcd() function. The fractions.gcd() function now is deprecated. Based on patch by Mark Dickinson. files: Doc/library/fractions.rst | 3 + Doc/library/math.rst | 8 + Include/longobject.h | 3 + Lib/fractions.py | 21 ++- Lib/test/test_fractions.py | 33 ++- Lib/test/test_math.py | 51 ++++++ Misc/NEWS | 3 + Modules/mathmodule.c | 28 +++ Objects/longobject.c | 205 +++++++++++++++++++++++++ 9 files changed, 342 insertions(+), 13 deletions(-) diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -172,6 +172,9 @@ sign as *b* if *b* is nonzero; otherwise it takes the sign of *a*. ``gcd(0, 0)`` returns ``0``. + .. deprecated:: 3.5 + Use :func:`math.gcd` instead. + .. seealso:: diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -100,6 +100,14 @@ `_\. +.. function:: gcd(a, b) + + Return the greatest common divisor of the integers *a* and *b*. If either + *a* or *b* is nonzero, then the value of ``gcd(a, b)`` is the largest + positive integer that divides both *a* and *b*. ``gcd(0, 0)`` returns + ``0``. + + .. function:: isfinite(x) Return ``True`` if *x* is neither an infinity nor a NaN, and diff --git a/Include/longobject.h b/Include/longobject.h --- a/Include/longobject.h +++ b/Include/longobject.h @@ -198,6 +198,9 @@ PyAPI_FUNC(unsigned long) PyOS_strtoul(const char *, char **, int); PyAPI_FUNC(long) PyOS_strtol(const char *, char **, int); +/* For use by the gcd function in mathmodule.c */ +PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); + #ifdef __cplusplus } #endif diff --git a/Lib/fractions.py b/Lib/fractions.py --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -20,6 +20,17 @@ Unless b==0, the result will have the same sign as b (so that when b is divided by it, the result comes out positive). """ + import warnings + warnings.warn('fractions.gcd() is deprecated. Use math.gcd() instead.', + DeprecationWarning, 2) + if type(a) is int is type(b): + if (b or a) < 0: + return -math.gcd(a, b) + return math.gcd(a, b) + return _gcd(a, b) + +def _gcd(a, b): + # Supports non-integers for backward compatibility. while b: a, b = b, a%b return a @@ -159,7 +170,7 @@ "or a Rational instance") elif type(numerator) is int is type(denominator): - pass # *very* normal case + pass # *very* normal case elif (isinstance(numerator, numbers.Rational) and isinstance(denominator, numbers.Rational)): @@ -174,7 +185,13 @@ if denominator == 0: raise ZeroDivisionError('Fraction(%s, 0)' % numerator) if _normalize: - g = gcd(numerator, denominator) + if type(numerator) is int is type(denominator): + # *very* normal case + g = math.gcd(numerator, denominator) + if denominator < 0: + g = -g + else: + g = _gcd(numerator, denominator) numerator //= g denominator //= g self._numerator = numerator diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -8,6 +8,7 @@ import fractions import sys import unittest +import warnings from copy import copy, deepcopy from pickle import dumps, loads F = fractions.Fraction @@ -49,7 +50,7 @@ """Test comparison of Fraction with a naive rational implementation.""" def __init__(self, num, den): - g = gcd(num, den) + g = math.gcd(num, den) self.num = num // g self.den = den // g @@ -83,16 +84,26 @@ class GcdTest(unittest.TestCase): def testMisc(self): - self.assertEqual(0, gcd(0, 0)) - self.assertEqual(1, gcd(1, 0)) - self.assertEqual(-1, gcd(-1, 0)) - self.assertEqual(1, gcd(0, 1)) - self.assertEqual(-1, gcd(0, -1)) - self.assertEqual(1, gcd(7, 1)) - self.assertEqual(-1, gcd(7, -1)) - self.assertEqual(1, gcd(-23, 15)) - self.assertEqual(12, gcd(120, 84)) - self.assertEqual(-12, gcd(84, -120)) + # fractions.gcd() is deprecated + with self.assertWarnsRegex(DeprecationWarning, r'fractions\.gcd'): + gcd(1, 1) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'fractions\.gcd', + DeprecationWarning) + self.assertEqual(0, gcd(0, 0)) + self.assertEqual(1, gcd(1, 0)) + self.assertEqual(-1, gcd(-1, 0)) + self.assertEqual(1, gcd(0, 1)) + self.assertEqual(-1, gcd(0, -1)) + self.assertEqual(1, gcd(7, 1)) + self.assertEqual(-1, gcd(7, -1)) + self.assertEqual(1, gcd(-23, 15)) + self.assertEqual(12, gcd(120, 84)) + self.assertEqual(-12, gcd(84, -120)) + self.assertEqual(gcd(120.0, 84), 12.0) + self.assertEqual(gcd(120, 84.0), 12.0) + self.assertEqual(gcd(F(120), F(84)), F(12)) + self.assertEqual(gcd(F(120, 77), F(84, 55)), F(12, 385)) def _components(r): diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -175,6 +175,14 @@ flags ) +# Class providing an __index__ method. +class MyIndexable(object): + def __init__(self, value): + self.value = value + + def __index__(self): + return self.value + class MathTests(unittest.TestCase): def ftest(self, name, value, expected): @@ -595,6 +603,49 @@ s = msum(vals) self.assertEqual(msum(vals), math.fsum(vals)) + def testGcd(self): + gcd = math.gcd + self.assertEqual(gcd(0, 0), 0) + self.assertEqual(gcd(1, 0), 1) + self.assertEqual(gcd(-1, 0), 1) + self.assertEqual(gcd(0, 1), 1) + self.assertEqual(gcd(0, -1), 1) + self.assertEqual(gcd(7, 1), 1) + self.assertEqual(gcd(7, -1), 1) + self.assertEqual(gcd(-23, 15), 1) + self.assertEqual(gcd(120, 84), 12) + self.assertEqual(gcd(84, -120), 12) + self.assertEqual(gcd(1216342683557601535506311712, + 436522681849110124616458784), 32) + c = 652560 + x = 434610456570399902378880679233098819019853229470286994367836600566 + y = 1064502245825115327754847244914921553977 + a = x * c + b = y * c + self.assertEqual(gcd(a, b), c) + self.assertEqual(gcd(b, a), c) + self.assertEqual(gcd(-a, b), c) + self.assertEqual(gcd(b, -a), c) + self.assertEqual(gcd(a, -b), c) + self.assertEqual(gcd(-b, a), c) + self.assertEqual(gcd(-a, -b), c) + self.assertEqual(gcd(-b, -a), c) + c = 576559230871654959816130551884856912003141446781646602790216406874 + a = x * c + b = y * c + self.assertEqual(gcd(a, b), c) + self.assertEqual(gcd(b, a), c) + self.assertEqual(gcd(-a, b), c) + self.assertEqual(gcd(b, -a), c) + self.assertEqual(gcd(a, -b), c) + self.assertEqual(gcd(-b, a), c) + self.assertEqual(gcd(-a, -b), c) + self.assertEqual(gcd(-b, -a), c) + + self.assertRaises(TypeError, gcd, 120.0, 84) + self.assertRaises(TypeError, gcd, 120, 84.0) + self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12) + def testHypot(self): self.assertRaises(TypeError, math.hypot) self.ftest('hypot(0,0)', math.hypot(0,0), 0) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ Library ------- +- Issue #22486: Added the math.gcd() function. The fractions.gcd() function now is + deprecated. Based on patch by Mark Dickinson. + - Issue #22681: Added support for the koi8_t encoding. - Issue #22682: Added support for the kz1048 encoding. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -685,6 +685,33 @@ } +static PyObject * +math_gcd(PyObject *self, PyObject *args) +{ + PyObject *a, *b, *g; + + if (!PyArg_ParseTuple(args, "OO:gcd", &a, &b)) + return NULL; + + a = PyNumber_Index(a); + if (a == NULL) + return NULL; + b = PyNumber_Index(b); + if (b == NULL) { + Py_DECREF(a); + return NULL; + } + g = _PyLong_GCD(a, b); + Py_DECREF(a); + Py_DECREF(b); + return g; +} + +PyDoc_STRVAR(math_gcd_doc, +"gcd(x, y) -> int\n\ +greatest common divisor of x and y"); + + /* Call is_error when errno != 0, and where x is the result libm * returned. is_error will usually set up an exception and return * true (1), but may return false (0) without setting up an exception. @@ -1987,6 +2014,7 @@ {"frexp", math_frexp, METH_O, math_frexp_doc}, {"fsum", math_fsum, METH_O, math_fsum_doc}, {"gamma", math_gamma, METH_O, math_gamma_doc}, + {"gcd", math_gcd, METH_VARARGS, math_gcd_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, {"isfinite", math_isfinite, METH_O, math_isfinite_doc}, {"isinf", math_isinf, METH_O, math_isinf_doc}, diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4327,6 +4327,211 @@ return v; } +PyObject * +_PyLong_GCD(PyObject *aarg, PyObject *barg) +{ + PyLongObject *a, *b, *c = NULL, *d = NULL, *r; + stwodigits x, y, q, s, t, c_carry, d_carry; + stwodigits A, B, C, D, T; + int nbits, k; + Py_ssize_t size_a, size_b, alloc_a, alloc_b; + digit *a_digit, *b_digit, *c_digit, *d_digit, *a_end, *b_end; + + a = (PyLongObject *)aarg; + b = (PyLongObject *)barg; + size_a = Py_SIZE(a); + size_b = Py_SIZE(b); + if (-2 <= size_a && size_a <= 2 && -2 <= size_b && size_b <= 2) { + Py_INCREF(a); + Py_INCREF(b); + goto simple; + } + + /* Initial reduction: make sure that 0 <= b <= a. */ + a = (PyLongObject *)long_abs(a); + if (a == NULL) + return NULL; + b = (PyLongObject *)long_abs(b); + if (b == NULL) { + Py_DECREF(a); + return NULL; + } + if (long_compare(a, b) < 0) { + r = a; + a = b; + b = r; + } + /* We now own references to a and b */ + + alloc_a = Py_SIZE(a); + alloc_b = Py_SIZE(b); + /* reduce until a fits into 2 digits */ + while ((size_a = Py_SIZE(a)) > 2) { + nbits = bits_in_digit(a->ob_digit[size_a-1]); + /* extract top 2*PyLong_SHIFT bits of a into x, along with + corresponding bits of b into y */ + size_b = Py_SIZE(b); + assert(size_b <= size_a); + if (size_b == 0) { + if (size_a < alloc_a) { + r = (PyLongObject *)_PyLong_Copy(a); + Py_DECREF(a); + } + else + r = a; + Py_DECREF(b); + Py_XDECREF(c); + Py_XDECREF(d); + return (PyObject *)r; + } + x = (((twodigits)a->ob_digit[size_a-1] << (2*PyLong_SHIFT-nbits)) | + ((twodigits)a->ob_digit[size_a-2] << (PyLong_SHIFT-nbits)) | + (a->ob_digit[size_a-3] >> nbits)); + + y = ((size_b >= size_a - 2 ? b->ob_digit[size_a-3] >> nbits : 0) | + (size_b >= size_a - 1 ? (twodigits)b->ob_digit[size_a-2] << (PyLong_SHIFT-nbits) : 0) | + (size_b >= size_a ? (twodigits)b->ob_digit[size_a-1] << (2*PyLong_SHIFT-nbits) : 0)); + + /* inner loop of Lehmer's algorithm; A, B, C, D never grow + larger than PyLong_MASK during the algorithm. */ + A = 1; B = 0; C = 0; D = 1; + for (k=0;; k++) { + if (y-C == 0) + break; + q = (x+(A-1))/(y-C); + s = B+q*D; + t = x-q*y; + if (s > t) + break; + x = y; y = t; + t = A+q*C; A = D; B = C; C = s; D = t; + } + + if (k == 0) { + /* no progress; do a Euclidean step */ + if (l_divmod(a, b, NULL, &r) < 0) + goto error; + Py_DECREF(a); + a = b; + b = r; + alloc_a = alloc_b; + alloc_b = Py_SIZE(b); + continue; + } + + /* + a, b = A*b-B*a, D*a-C*b if k is odd + a, b = A*a-B*b, D*b-C*a if k is even + */ + if (k&1) { + T = -A; A = -B; B = T; + T = -C; C = -D; D = T; + } + if (c != NULL) + Py_SIZE(c) = size_a; + else if (Py_REFCNT(a) == 1) { + Py_INCREF(a); + c = a; + } + else { + alloc_a = size_a; + c = _PyLong_New(size_a); + if (c == NULL) + goto error; + } + + if (d != NULL) + Py_SIZE(d) = size_a; + else if (Py_REFCNT(b) == 1 && size_a <= alloc_b) { + Py_INCREF(b); + d = b; + Py_SIZE(d) = size_a; + } + else { + alloc_b = size_a; + d = _PyLong_New(size_a); + if (d == NULL) + goto error; + } + a_end = a->ob_digit + size_a; + b_end = b->ob_digit + size_b; + + /* compute new a and new b in parallel */ + a_digit = a->ob_digit; + b_digit = b->ob_digit; + c_digit = c->ob_digit; + d_digit = d->ob_digit; + c_carry = 0; + d_carry = 0; + while (b_digit < b_end) { + c_carry += (A * *a_digit) - (B * *b_digit); + d_carry += (D * *b_digit++) - (C * *a_digit++); + *c_digit++ = (digit)(c_carry & PyLong_MASK); + *d_digit++ = (digit)(d_carry & PyLong_MASK); + c_carry >>= PyLong_SHIFT; + d_carry >>= PyLong_SHIFT; + } + while (a_digit < a_end) { + c_carry += A * *a_digit; + d_carry -= C * *a_digit++; + *c_digit++ = (digit)(c_carry & PyLong_MASK); + *d_digit++ = (digit)(d_carry & PyLong_MASK); + c_carry >>= PyLong_SHIFT; + d_carry >>= PyLong_SHIFT; + } + assert(c_carry == 0); + assert(d_carry == 0); + + Py_INCREF(c); + Py_INCREF(d); + Py_DECREF(a); + Py_DECREF(b); + a = long_normalize(c); + b = long_normalize(d); + } + Py_XDECREF(c); + Py_XDECREF(d); + +simple: + assert(Py_REFCNT(a) > 0); + assert(Py_REFCNT(b) > 0); +#if LONG_MAX >> 2*PyLong_SHIFT + /* a fits into a long, so b must too */ + x = PyLong_AsLong((PyObject *)a); + y = PyLong_AsLong((PyObject *)b); +#elif defined(PY_LONG_LONG) && PY_LLONG_MAX >> 2*PyLong_SHIFT + x = PyLong_AsLongLong((PyObject *)a); + y = PyLong_AsLongLong((PyObject *)b); +#else +# error "_PyLong_GCD" +#endif + x = Py_ABS(x); + y = Py_ABS(y); + Py_DECREF(a); + Py_DECREF(b); + + /* usual Euclidean algorithm for longs */ + while (y != 0) { + t = y; + y = x % y; + x = t; + } +#if LONG_MAX >> 2*PyLong_SHIFT + return PyLong_FromLong(x); +#elif defined(PY_LONG_LONG) && PY_LLONG_MAX >> 2*PyLong_SHIFT + return PyLong_FromLongLong(x); +#else +# error "_PyLong_GCD" +#endif + +error: + Py_DECREF(a); + Py_DECREF(b); + Py_XDECREF(c); + Py_XDECREF(d); + return NULL; +} + static PyObject * long_float(PyObject *v) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 23:24:26 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 May 2015 21:24:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_versionadded?= Message-ID: <20150512212423.45098.11538@psf.io> https://hg.python.org/cpython/rev/2737116a7c89 changeset: 95992:2737116a7c89 user: Benjamin Peterson date: Tue May 12 17:24:17 2015 -0400 summary: versionadded files: Doc/library/math.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -107,6 +107,8 @@ positive integer that divides both *a* and *b*. ``gcd(0, 0)`` returns ``0``. + .. versionadded:: 3.5 + .. function:: isfinite(x) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 23:35:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 21:35:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_forgotten_new_files_?= =?utf-8?q?for_issues_=2322681_and_=2322682=2E?= Message-ID: <20150512213514.45102.36355@psf.io> https://hg.python.org/cpython/rev/def3bab79c8f changeset: 95993:def3bab79c8f user: Serhiy Storchaka date: Wed May 13 00:34:53 2015 +0300 summary: Added forgotten new files for issues #22681 and #22682. files: Lib/encodings/koi8_r.py | 131 +++--- Lib/encodings/cp1251.py | 534 ++++++++++++++-------------- 2 files changed, 333 insertions(+), 332 deletions(-) diff --git a/Lib/encodings/koi8_r.py b/Lib/encodings/koi8_t.py copy from Lib/encodings/koi8_r.py copy to Lib/encodings/koi8_t.py --- a/Lib/encodings/koi8_r.py +++ b/Lib/encodings/koi8_t.py @@ -1,6 +1,7 @@ -""" Python Character Mapping Codec koi8_r generated from 'MAPPINGS/VENDORS/MISC/KOI8-R.TXT' with gencodec.py. - -"""#" +""" Python Character Mapping Codec koi8_t +""" +# http://ru.wikipedia.org/wiki/???-8 +# http://www.opensource.apple.com/source/libiconv/libiconv-4/libiconv/tests/KOI8-T.TXT import codecs @@ -32,7 +33,7 @@ def getregentry(): return codecs.CodecInfo( - name='koi8-r', + name='koi8-t', encode=Codec().encode, decode=Codec().decode, incrementalencoder=IncrementalEncoder, @@ -173,69 +174,69 @@ '}' # 0x7D -> RIGHT CURLY BRACKET '~' # 0x7E -> TILDE '\x7f' # 0x7F -> DELETE - '\u2500' # 0x80 -> BOX DRAWINGS LIGHT HORIZONTAL - '\u2502' # 0x81 -> BOX DRAWINGS LIGHT VERTICAL - '\u250c' # 0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT - '\u2510' # 0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT - '\u2514' # 0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT - '\u2518' # 0x85 -> BOX DRAWINGS LIGHT UP AND LEFT - '\u251c' # 0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT - '\u2524' # 0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT - '\u252c' # 0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - '\u2534' # 0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL - '\u253c' # 0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - '\u2580' # 0x8B -> UPPER HALF BLOCK - '\u2584' # 0x8C -> LOWER HALF BLOCK - '\u2588' # 0x8D -> FULL BLOCK - '\u258c' # 0x8E -> LEFT HALF BLOCK - '\u2590' # 0x8F -> RIGHT HALF BLOCK - '\u2591' # 0x90 -> LIGHT SHADE - '\u2592' # 0x91 -> MEDIUM SHADE - '\u2593' # 0x92 -> DARK SHADE - '\u2320' # 0x93 -> TOP HALF INTEGRAL - '\u25a0' # 0x94 -> BLACK SQUARE - '\u2219' # 0x95 -> BULLET OPERATOR - '\u221a' # 0x96 -> SQUARE ROOT - '\u2248' # 0x97 -> ALMOST EQUAL TO - '\u2264' # 0x98 -> LESS-THAN OR EQUAL TO - '\u2265' # 0x99 -> GREATER-THAN OR EQUAL TO - '\xa0' # 0x9A -> NO-BREAK SPACE - '\u2321' # 0x9B -> BOTTOM HALF INTEGRAL - '\xb0' # 0x9C -> DEGREE SIGN - '\xb2' # 0x9D -> SUPERSCRIPT TWO - '\xb7' # 0x9E -> MIDDLE DOT - '\xf7' # 0x9F -> DIVISION SIGN - '\u2550' # 0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL - '\u2551' # 0xA1 -> BOX DRAWINGS DOUBLE VERTICAL - '\u2552' # 0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u049b' # 0x80 -> CYRILLIC SMALL LETTER KA WITH DESCENDER + '\u0493' # 0x81 -> CYRILLIC SMALL LETTER GHE WITH STROKE + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0492' # 0x83 -> CYRILLIC CAPITAL LETTER GHE WITH STROKE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\ufffe' # 0x88 -> UNDEFINED + '\u2030' # 0x89 -> PER MILLE SIGN + '\u04b3' # 0x8A -> CYRILLIC SMALL LETTER HA WITH DESCENDER + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u04b2' # 0x8C -> CYRILLIC CAPITAL LETTER HA WITH DESCENDER + '\u04b7' # 0x8D -> CYRILLIC SMALL LETTER CHE WITH DESCENDER + '\u04b6' # 0x8E -> CYRILLIC CAPITAL LETTER CHE WITH DESCENDER + '\ufffe' # 0x8F -> UNDEFINED + '\u049a' # 0x90 -> CYRILLIC CAPITAL LETTER KA WITH DESCENDER + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x9C -> UNDEFINED + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\ufffe' # 0x9F -> UNDEFINED + '\ufffe' # 0xA0 -> UNDEFINED + '\u04ef' # 0xA1 -> CYRILLIC SMALL LETTER U WITH MACRON + '\u04ee' # 0xA2 -> CYRILLIC CAPITAL LETTER U WITH MACRON '\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO - '\u2553' # 0xA4 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - '\u2554' # 0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT - '\u2555' # 0xA6 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - '\u2556' # 0xA7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - '\u2557' # 0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT - '\u2558' # 0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - '\u2559' # 0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - '\u255a' # 0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT - '\u255b' # 0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - '\u255c' # 0xAD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - '\u255d' # 0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT - '\u255e' # 0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - '\u255f' # 0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - '\u2560' # 0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - '\u2561' # 0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u04e3' # 0xA5 -> CYRILLIC SMALL LETTER I WITH MACRON + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\ufffe' # 0xA8 -> UNDEFINED + '\ufffe' # 0xA9 -> UNDEFINED + '\ufffe' # 0xAA -> UNDEFINED + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\ufffe' # 0xAF -> UNDEFINED + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO '\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO - '\u2562' # 0xB4 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - '\u2563' # 0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT - '\u2564' # 0xB6 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - '\u2565' # 0xB7 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - '\u2566' # 0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - '\u2567' # 0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - '\u2568' # 0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - '\u2569' # 0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL - '\u256a' # 0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - '\u256b' # 0xBD -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - '\u256c' # 0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\ufffe' # 0xB4 -> UNDEFINED + '\u04e2' # 0xB5 -> CYRILLIC CAPITAL LETTER I WITH MACRON + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\ufffe' # 0xB8 -> UNDEFINED + '\u2116' # 0xB9 -> NUMERO SIGN + '\ufffe' # 0xBA -> UNDEFINED + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\ufffe' # 0xBC -> UNDEFINED + '\ufffe' # 0xBD -> UNDEFINED + '\ufffe' # 0xBE -> UNDEFINED '\xa9' # 0xBF -> COPYRIGHT SIGN '\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU '\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A diff --git a/Lib/encodings/cp1251.py b/Lib/encodings/kz1048.py copy from Lib/encodings/cp1251.py copy to Lib/encodings/kz1048.py --- a/Lib/encodings/cp1251.py +++ b/Lib/encodings/kz1048.py @@ -1,4 +1,4 @@ -""" Python Character Mapping Codec cp1251 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT' with gencodec.py. +""" Python Character Mapping Codec kz1048 generated from 'MAPPINGS/VENDORS/MISC/KZ1048.TXT' with gencodec.py. """#" @@ -8,31 +8,31 @@ class Codec(codecs.Codec): - def encode(self,input,errors='strict'): - return codecs.charmap_encode(input,errors,encoding_table) + def encode(self, input, errors='strict'): + return codecs.charmap_encode(input, errors, encoding_table) - def decode(self,input,errors='strict'): - return codecs.charmap_decode(input,errors,decoding_table) + def decode(self, input, errors='strict'): + return codecs.charmap_decode(input, errors, decoding_table) class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input, final=False): - return codecs.charmap_encode(input,self.errors,encoding_table)[0] + return codecs.charmap_encode(input, self.errors, encoding_table)[0] class IncrementalDecoder(codecs.IncrementalDecoder): def decode(self, input, final=False): - return codecs.charmap_decode(input,self.errors,decoding_table)[0] + return codecs.charmap_decode(input, self.errors, decoding_table)[0] -class StreamWriter(Codec,codecs.StreamWriter): +class StreamWriter(Codec, codecs.StreamWriter): pass -class StreamReader(Codec,codecs.StreamReader): +class StreamReader(Codec, codecs.StreamReader): pass ### encodings module API def getregentry(): return codecs.CodecInfo( - name='cp1251', + name='kz1048', encode=Codec().encode, decode=Codec().decode, incrementalencoder=IncrementalEncoder, @@ -45,263 +45,263 @@ ### Decoding Table decoding_table = ( - '\x00' # 0x00 -> NULL - '\x01' # 0x01 -> START OF HEADING - '\x02' # 0x02 -> START OF TEXT - '\x03' # 0x03 -> END OF TEXT - '\x04' # 0x04 -> END OF TRANSMISSION - '\x05' # 0x05 -> ENQUIRY - '\x06' # 0x06 -> ACKNOWLEDGE - '\x07' # 0x07 -> BELL - '\x08' # 0x08 -> BACKSPACE - '\t' # 0x09 -> HORIZONTAL TABULATION - '\n' # 0x0A -> LINE FEED - '\x0b' # 0x0B -> VERTICAL TABULATION - '\x0c' # 0x0C -> FORM FEED - '\r' # 0x0D -> CARRIAGE RETURN - '\x0e' # 0x0E -> SHIFT OUT - '\x0f' # 0x0F -> SHIFT IN - '\x10' # 0x10 -> DATA LINK ESCAPE - '\x11' # 0x11 -> DEVICE CONTROL ONE - '\x12' # 0x12 -> DEVICE CONTROL TWO - '\x13' # 0x13 -> DEVICE CONTROL THREE - '\x14' # 0x14 -> DEVICE CONTROL FOUR - '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE - '\x16' # 0x16 -> SYNCHRONOUS IDLE - '\x17' # 0x17 -> END OF TRANSMISSION BLOCK - '\x18' # 0x18 -> CANCEL - '\x19' # 0x19 -> END OF MEDIUM - '\x1a' # 0x1A -> SUBSTITUTE - '\x1b' # 0x1B -> ESCAPE - '\x1c' # 0x1C -> FILE SEPARATOR - '\x1d' # 0x1D -> GROUP SEPARATOR - '\x1e' # 0x1E -> RECORD SEPARATOR - '\x1f' # 0x1F -> UNIT SEPARATOR - ' ' # 0x20 -> SPACE - '!' # 0x21 -> EXCLAMATION MARK - '"' # 0x22 -> QUOTATION MARK - '#' # 0x23 -> NUMBER SIGN - '$' # 0x24 -> DOLLAR SIGN - '%' # 0x25 -> PERCENT SIGN - '&' # 0x26 -> AMPERSAND - "'" # 0x27 -> APOSTROPHE - '(' # 0x28 -> LEFT PARENTHESIS - ')' # 0x29 -> RIGHT PARENTHESIS - '*' # 0x2A -> ASTERISK - '+' # 0x2B -> PLUS SIGN - ',' # 0x2C -> COMMA - '-' # 0x2D -> HYPHEN-MINUS - '.' # 0x2E -> FULL STOP - '/' # 0x2F -> SOLIDUS - '0' # 0x30 -> DIGIT ZERO - '1' # 0x31 -> DIGIT ONE - '2' # 0x32 -> DIGIT TWO - '3' # 0x33 -> DIGIT THREE - '4' # 0x34 -> DIGIT FOUR - '5' # 0x35 -> DIGIT FIVE - '6' # 0x36 -> DIGIT SIX - '7' # 0x37 -> DIGIT SEVEN - '8' # 0x38 -> DIGIT EIGHT - '9' # 0x39 -> DIGIT NINE - ':' # 0x3A -> COLON - ';' # 0x3B -> SEMICOLON - '<' # 0x3C -> LESS-THAN SIGN - '=' # 0x3D -> EQUALS SIGN - '>' # 0x3E -> GREATER-THAN SIGN - '?' # 0x3F -> QUESTION MARK - '@' # 0x40 -> COMMERCIAL AT - 'A' # 0x41 -> LATIN CAPITAL LETTER A - 'B' # 0x42 -> LATIN CAPITAL LETTER B - 'C' # 0x43 -> LATIN CAPITAL LETTER C - 'D' # 0x44 -> LATIN CAPITAL LETTER D - 'E' # 0x45 -> LATIN CAPITAL LETTER E - 'F' # 0x46 -> LATIN CAPITAL LETTER F - 'G' # 0x47 -> LATIN CAPITAL LETTER G - 'H' # 0x48 -> LATIN CAPITAL LETTER H - 'I' # 0x49 -> LATIN CAPITAL LETTER I - 'J' # 0x4A -> LATIN CAPITAL LETTER J - 'K' # 0x4B -> LATIN CAPITAL LETTER K - 'L' # 0x4C -> LATIN CAPITAL LETTER L - 'M' # 0x4D -> LATIN CAPITAL LETTER M - 'N' # 0x4E -> LATIN CAPITAL LETTER N - 'O' # 0x4F -> LATIN CAPITAL LETTER O - 'P' # 0x50 -> LATIN CAPITAL LETTER P - 'Q' # 0x51 -> LATIN CAPITAL LETTER Q - 'R' # 0x52 -> LATIN CAPITAL LETTER R - 'S' # 0x53 -> LATIN CAPITAL LETTER S - 'T' # 0x54 -> LATIN CAPITAL LETTER T - 'U' # 0x55 -> LATIN CAPITAL LETTER U - 'V' # 0x56 -> LATIN CAPITAL LETTER V - 'W' # 0x57 -> LATIN CAPITAL LETTER W - 'X' # 0x58 -> LATIN CAPITAL LETTER X - 'Y' # 0x59 -> LATIN CAPITAL LETTER Y - 'Z' # 0x5A -> LATIN CAPITAL LETTER Z - '[' # 0x5B -> LEFT SQUARE BRACKET - '\\' # 0x5C -> REVERSE SOLIDUS - ']' # 0x5D -> RIGHT SQUARE BRACKET - '^' # 0x5E -> CIRCUMFLEX ACCENT - '_' # 0x5F -> LOW LINE - '`' # 0x60 -> GRAVE ACCENT - 'a' # 0x61 -> LATIN SMALL LETTER A - 'b' # 0x62 -> LATIN SMALL LETTER B - 'c' # 0x63 -> LATIN SMALL LETTER C - 'd' # 0x64 -> LATIN SMALL LETTER D - 'e' # 0x65 -> LATIN SMALL LETTER E - 'f' # 0x66 -> LATIN SMALL LETTER F - 'g' # 0x67 -> LATIN SMALL LETTER G - 'h' # 0x68 -> LATIN SMALL LETTER H - 'i' # 0x69 -> LATIN SMALL LETTER I - 'j' # 0x6A -> LATIN SMALL LETTER J - 'k' # 0x6B -> LATIN SMALL LETTER K - 'l' # 0x6C -> LATIN SMALL LETTER L - 'm' # 0x6D -> LATIN SMALL LETTER M - 'n' # 0x6E -> LATIN SMALL LETTER N - 'o' # 0x6F -> LATIN SMALL LETTER O - 'p' # 0x70 -> LATIN SMALL LETTER P - 'q' # 0x71 -> LATIN SMALL LETTER Q - 'r' # 0x72 -> LATIN SMALL LETTER R - 's' # 0x73 -> LATIN SMALL LETTER S - 't' # 0x74 -> LATIN SMALL LETTER T - 'u' # 0x75 -> LATIN SMALL LETTER U - 'v' # 0x76 -> LATIN SMALL LETTER V - 'w' # 0x77 -> LATIN SMALL LETTER W - 'x' # 0x78 -> LATIN SMALL LETTER X - 'y' # 0x79 -> LATIN SMALL LETTER Y - 'z' # 0x7A -> LATIN SMALL LETTER Z - '{' # 0x7B -> LEFT CURLY BRACKET - '|' # 0x7C -> VERTICAL LINE - '}' # 0x7D -> RIGHT CURLY BRACKET - '~' # 0x7E -> TILDE - '\x7f' # 0x7F -> DELETE - '\u0402' # 0x80 -> CYRILLIC CAPITAL LETTER DJE - '\u0403' # 0x81 -> CYRILLIC CAPITAL LETTER GJE - '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK - '\u0453' # 0x83 -> CYRILLIC SMALL LETTER GJE - '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK - '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS - '\u2020' # 0x86 -> DAGGER - '\u2021' # 0x87 -> DOUBLE DAGGER - '\u20ac' # 0x88 -> EURO SIGN - '\u2030' # 0x89 -> PER MILLE SIGN - '\u0409' # 0x8A -> CYRILLIC CAPITAL LETTER LJE - '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK - '\u040a' # 0x8C -> CYRILLIC CAPITAL LETTER NJE - '\u040c' # 0x8D -> CYRILLIC CAPITAL LETTER KJE - '\u040b' # 0x8E -> CYRILLIC CAPITAL LETTER TSHE - '\u040f' # 0x8F -> CYRILLIC CAPITAL LETTER DZHE - '\u0452' # 0x90 -> CYRILLIC SMALL LETTER DJE - '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK - '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK - '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK - '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK - '\u2022' # 0x95 -> BULLET - '\u2013' # 0x96 -> EN DASH - '\u2014' # 0x97 -> EM DASH - '\ufffe' # 0x98 -> UNDEFINED - '\u2122' # 0x99 -> TRADE MARK SIGN - '\u0459' # 0x9A -> CYRILLIC SMALL LETTER LJE - '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - '\u045a' # 0x9C -> CYRILLIC SMALL LETTER NJE - '\u045c' # 0x9D -> CYRILLIC SMALL LETTER KJE - '\u045b' # 0x9E -> CYRILLIC SMALL LETTER TSHE - '\u045f' # 0x9F -> CYRILLIC SMALL LETTER DZHE - '\xa0' # 0xA0 -> NO-BREAK SPACE - '\u040e' # 0xA1 -> CYRILLIC CAPITAL LETTER SHORT U - '\u045e' # 0xA2 -> CYRILLIC SMALL LETTER SHORT U - '\u0408' # 0xA3 -> CYRILLIC CAPITAL LETTER JE - '\xa4' # 0xA4 -> CURRENCY SIGN - '\u0490' # 0xA5 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN - '\xa6' # 0xA6 -> BROKEN BAR - '\xa7' # 0xA7 -> SECTION SIGN - '\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO - '\xa9' # 0xA9 -> COPYRIGHT SIGN - '\u0404' # 0xAA -> CYRILLIC CAPITAL LETTER UKRAINIAN IE - '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - '\xac' # 0xAC -> NOT SIGN - '\xad' # 0xAD -> SOFT HYPHEN - '\xae' # 0xAE -> REGISTERED SIGN - '\u0407' # 0xAF -> CYRILLIC CAPITAL LETTER YI - '\xb0' # 0xB0 -> DEGREE SIGN - '\xb1' # 0xB1 -> PLUS-MINUS SIGN - '\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I - '\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I - '\u0491' # 0xB4 -> CYRILLIC SMALL LETTER GHE WITH UPTURN - '\xb5' # 0xB5 -> MICRO SIGN - '\xb6' # 0xB6 -> PILCROW SIGN - '\xb7' # 0xB7 -> MIDDLE DOT - '\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO - '\u2116' # 0xB9 -> NUMERO SIGN - '\u0454' # 0xBA -> CYRILLIC SMALL LETTER UKRAINIAN IE - '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - '\u0458' # 0xBC -> CYRILLIC SMALL LETTER JE - '\u0405' # 0xBD -> CYRILLIC CAPITAL LETTER DZE - '\u0455' # 0xBE -> CYRILLIC SMALL LETTER DZE - '\u0457' # 0xBF -> CYRILLIC SMALL LETTER YI - '\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A - '\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE - '\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE - '\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE - '\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE - '\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE - '\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE - '\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE - '\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I - '\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I - '\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA - '\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL - '\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM - '\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN - '\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O - '\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE - '\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER - '\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES - '\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE - '\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U - '\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF - '\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA - '\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE - '\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE - '\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA - '\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA - '\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN - '\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU - '\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN - '\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E - '\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU - '\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA - '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A - '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE - '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE - '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE - '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE - '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE - '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE - '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE - '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I - '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I - '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA - '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL - '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM - '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN - '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O - '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE - '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER - '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES - '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE - '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U - '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF - '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA - '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE - '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE - '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA - '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA - '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN - '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU - '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN - '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E - '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU - '\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u0402' # 0x80 -> CYRILLIC CAPITAL LETTER DJE + '\u0403' # 0x81 -> CYRILLIC CAPITAL LETTER GJE + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0453' # 0x83 -> CYRILLIC SMALL LETTER GJE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u20ac' # 0x88 -> EURO SIGN + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0409' # 0x8A -> CYRILLIC CAPITAL LETTER LJE + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u040a' # 0x8C -> CYRILLIC CAPITAL LETTER NJE + '\u049a' # 0x8D -> CYRILLIC CAPITAL LETTER KA WITH DESCENDER + '\u04ba' # 0x8E -> CYRILLIC CAPITAL LETTER SHHA + '\u040f' # 0x8F -> CYRILLIC CAPITAL LETTER DZHE + '\u0452' # 0x90 -> CYRILLIC SMALL LETTER DJE + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0459' # 0x9A -> CYRILLIC SMALL LETTER LJE + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u045a' # 0x9C -> CYRILLIC SMALL LETTER NJE + '\u049b' # 0x9D -> CYRILLIC SMALL LETTER KA WITH DESCENDER + '\u04bb' # 0x9E -> CYRILLIC SMALL LETTER SHHA + '\u045f' # 0x9F -> CYRILLIC SMALL LETTER DZHE + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u04b0' # 0xA1 -> CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE + '\u04b1' # 0xA2 -> CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE + '\u04d8' # 0xA3 -> CYRILLIC CAPITAL LETTER SCHWA + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u04e8' # 0xA5 -> CYRILLIC CAPITAL LETTER BARRED O + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0492' # 0xAA -> CYRILLIC CAPITAL LETTER GHE WITH STROKE + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u04ae' # 0xAF -> CYRILLIC CAPITAL LETTER STRAIGHT U + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u04e9' # 0xB4 -> CYRILLIC SMALL LETTER BARRED O + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO + '\u2116' # 0xB9 -> NUMERO SIGN + '\u0493' # 0xBA -> CYRILLIC SMALL LETTER GHE WITH STROKE + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u04d9' # 0xBC -> CYRILLIC SMALL LETTER SCHWA + '\u04a2' # 0xBD -> CYRILLIC CAPITAL LETTER EN WITH DESCENDER + '\u04a3' # 0xBE -> CYRILLIC SMALL LETTER EN WITH DESCENDER + '\u04af' # 0xBF -> CYRILLIC SMALL LETTER STRAIGHT U + '\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + '\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA ) ### Encoding table -encoding_table=codecs.charmap_build(decoding_table) +encoding_table = codecs.charmap_build(decoding_table) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 12 23:53:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 12 May 2015 21:53:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Converted_os=2E=5Fgetfullp?= =?utf-8?q?athname=28=29_and_os=2E=5Fisdir=28=29_to_Argument_Clinic=2E?= Message-ID: <20150512215300.25449.45135@psf.io> https://hg.python.org/cpython/rev/4d7175af607e changeset: 95994:4d7175af607e user: Serhiy Storchaka date: Wed May 13 00:52:39 2015 +0300 summary: Converted os._getfullpathname() and os._isdir() to Argument Clinic. files: Modules/clinic/posixmodule.c.h | 74 +++++++++++++- Modules/posixmodule.c | 112 ++++++++------------ 2 files changed, 119 insertions(+), 67 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -890,6 +890,38 @@ #if defined(MS_WINDOWS) +PyDoc_STRVAR(os__getfullpathname__doc__, +"_getfullpathname($module, path, /)\n" +"--\n" +"\n"); + +#define OS__GETFULLPATHNAME_METHODDEF \ + {"_getfullpathname", (PyCFunction)os__getfullpathname, METH_O, os__getfullpathname__doc__}, + +static PyObject * +os__getfullpathname_impl(PyModuleDef *module, path_t *path); + +static PyObject * +os__getfullpathname(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); + + if (!PyArg_Parse(arg, "O&:_getfullpathname", path_converter, &path)) + goto exit; + return_value = os__getfullpathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + PyDoc_STRVAR(os__getfinalpathname__doc__, "_getfinalpathname($module, path, /)\n" "--\n" @@ -920,6 +952,38 @@ #if defined(MS_WINDOWS) +PyDoc_STRVAR(os__isdir__doc__, +"_isdir($module, path, /)\n" +"--\n" +"\n"); + +#define OS__ISDIR_METHODDEF \ + {"_isdir", (PyCFunction)os__isdir, METH_O, os__isdir__doc__}, + +static PyObject * +os__isdir_impl(PyModuleDef *module, path_t *path); + +static PyObject * +os__isdir(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_isdir", "path", 0, 0); + + if (!PyArg_Parse(arg, "O&:_isdir", path_converter, &path)) + goto exit; + return_value = os__isdir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + PyDoc_STRVAR(os__getvolumepathname__doc__, "_getvolumepathname($module, /, path)\n" "--\n" @@ -5313,10 +5377,18 @@ #define OS_LINK_METHODDEF #endif /* !defined(OS_LINK_METHODDEF) */ +#ifndef OS__GETFULLPATHNAME_METHODDEF + #define OS__GETFULLPATHNAME_METHODDEF +#endif /* !defined(OS__GETFULLPATHNAME_METHODDEF) */ + #ifndef OS__GETFINALPATHNAME_METHODDEF #define OS__GETFINALPATHNAME_METHODDEF #endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ +#ifndef OS__ISDIR_METHODDEF + #define OS__ISDIR_METHODDEF +#endif /* !defined(OS__ISDIR_METHODDEF) */ + #ifndef OS__GETVOLUMEPATHNAME_METHODDEF #define OS__GETVOLUMEPATHNAME_METHODDEF #endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ @@ -5716,4 +5788,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=bba73c13a01c09a0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f3f92b2d2e2c3fe3 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3748,62 +3748,53 @@ #ifdef MS_WINDOWS /* A helper function for abspath on win32 */ -/* AC 3.5: probably just convert to using path converter */ -static PyObject * -posix__getfullpathname(PyObject *self, PyObject *args) -{ - const char *path; - char outbuf[MAX_PATH]; - char *temp; - PyObject *po; - - if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) +/*[clinic input] +os._getfullpathname + + path: path_t + / + +[clinic start generated code]*/ + +static PyObject * +os__getfullpathname_impl(PyModuleDef *module, path_t *path) +/*[clinic end generated code: output=b90b1f103b08773f input=332ed537c29d0a3e]*/ +{ + if (!path->narrow) { - wchar_t *wpath; wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; wchar_t *wtemp; DWORD result; PyObject *v; - wpath = PyUnicode_AsUnicode(po); - if (wpath == NULL) - return NULL; - result = GetFullPathNameW(wpath, + result = GetFullPathNameW(path->wide, Py_ARRAY_LENGTH(woutbuf), woutbuf, &wtemp); if (result > Py_ARRAY_LENGTH(woutbuf)) { woutbufp = PyMem_New(wchar_t, result); if (!woutbufp) return PyErr_NoMemory(); - result = GetFullPathNameW(wpath, result, woutbufp, &wtemp); + result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp); } if (result) v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); else - v = win32_error_object("GetFullPathNameW", po); + v = win32_error_object("GetFullPathNameW", path->object); if (woutbufp != woutbuf) PyMem_Free(woutbufp); return v; } - /* Drop the argument parsing error as narrow strings - are also valid. */ - PyErr_Clear(); - - if (!PyArg_ParseTuple (args, "y:_getfullpathname", - &path)) - return NULL; - if (win32_warn_bytes_api()) - return NULL; - if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf), - outbuf, &temp)) { - win32_error("GetFullPathName", path); - return NULL; - } - if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { - return PyUnicode_Decode(outbuf, strlen(outbuf), - Py_FileSystemDefaultEncoding, NULL); - } - return PyBytes_FromString(outbuf); + else { + char outbuf[MAX_PATH]; + char *temp; + + if (!GetFullPathName(path->narrow, Py_ARRAY_LENGTH(outbuf), + outbuf, &temp)) { + win32_error_object("GetFullPathName", path->object); + return NULL; + } + return PyBytes_FromString(outbuf); + } } @@ -3872,37 +3863,28 @@ PyDoc_STRVAR(posix__isdir__doc__, "Return true if the pathname refers to an existing directory."); -/* AC 3.5: convert using path converter */ -static PyObject * -posix__isdir(PyObject *self, PyObject *args) -{ - const char *path; - PyObject *po; +/*[clinic input] +os._isdir + + path: path_t + / + +[clinic start generated code]*/ + +static PyObject * +os__isdir_impl(PyModuleDef *module, path_t *path) +/*[clinic end generated code: output=f17b2d4e1994b0ff input=e794f12faab62a2a]*/ +{ DWORD attributes; - if (PyArg_ParseTuple(args, "U|:_isdir", &po)) { - wchar_t *wpath = PyUnicode_AsUnicode(po); - if (wpath == NULL) - return NULL; - - attributes = GetFileAttributesW(wpath); - if (attributes == INVALID_FILE_ATTRIBUTES) - Py_RETURN_FALSE; - goto check; - } - /* Drop the argument parsing error as narrow strings - are also valid. */ - PyErr_Clear(); - - if (!PyArg_ParseTuple(args, "y:_isdir", &path)) - return NULL; - if (win32_warn_bytes_api()) - return NULL; - attributes = GetFileAttributesA(path); + if (!path->narrow) + attributes = GetFileAttributesW(path->wide); + else + attributes = GetFileAttributesA(path->narrow); + if (attributes == INVALID_FILE_ATTRIBUTES) Py_RETURN_FALSE; -check: if (attributes & FILE_ATTRIBUTE_DIRECTORY) Py_RETURN_TRUE; else @@ -12351,10 +12333,8 @@ OS_FPATHCONF_METHODDEF OS_PATHCONF_METHODDEF OS_ABORT_METHODDEF -#ifdef MS_WINDOWS - {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL}, - {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__}, -#endif + OS__GETFULLPATHNAME_METHODDEF + OS__ISDIR_METHODDEF OS__GETDISKUSAGE_METHODDEF OS__GETFINALPATHNAME_METHODDEF OS__GETVOLUMEPATHNAME_METHODDEF -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 01:16:25 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 May 2015 23:16:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_use_imperative?= Message-ID: <20150512231624.92577.59287@psf.io> https://hg.python.org/cpython/rev/4e62311e1eb1 changeset: 95996:4e62311e1eb1 branch: 3.4 parent: 95985:ee7d2c9c70ab user: Benjamin Peterson date: Tue May 12 19:15:53 2015 -0400 summary: use imperative files: Doc/library/math.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -280,12 +280,12 @@ .. function:: degrees(x) - Converts angle *x* from radians to degrees. + Convert angle *x* from radians to degrees. .. function:: radians(x) - Converts angle *x* from degrees to radians. + Convert angle *x* from degrees to radians. Hyperbolic functions -------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 01:16:25 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 May 2015 23:16:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150512231625.56717.13696@psf.io> https://hg.python.org/cpython/rev/4c03e1aebbc7 changeset: 95997:4c03e1aebbc7 parent: 95994:4d7175af607e parent: 95996:4e62311e1eb1 user: Benjamin Peterson date: Tue May 12 19:16:20 2015 -0400 summary: merge 3.4 files: Doc/library/math.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -290,12 +290,12 @@ .. function:: degrees(x) - Converts angle *x* from radians to degrees. + Convert angle *x* from radians to degrees. .. function:: radians(x) - Converts angle *x* from degrees to radians. + Convert angle *x* from degrees to radians. Hyperbolic functions -------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 01:16:24 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 12 May 2015 23:16:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_imperative?= Message-ID: <20150512231624.11946.47933@psf.io> https://hg.python.org/cpython/rev/19c5fb692b39 changeset: 95995:19c5fb692b39 branch: 2.7 parent: 95968:0e8a17f437b5 user: Benjamin Peterson date: Tue May 12 19:15:53 2015 -0400 summary: use imperative files: Doc/library/math.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -280,12 +280,12 @@ .. function:: degrees(x) - Converts angle *x* from radians to degrees. + Convert angle *x* from radians to degrees. .. function:: radians(x) - Converts angle *x* from degrees to radians. + Convert angle *x* from degrees to radians. Hyperbolic functions -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 06:26:57 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 04:26:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Reduce_the_overhead_in_fun?= =?utf-8?q?ctools=2Etotal=5Fordering_by_localizing_NotImplemented=2E?= Message-ID: <20150513042657.25449.35901@psf.io> https://hg.python.org/cpython/rev/5853af86c6a9 changeset: 95998:5853af86c6a9 user: Raymond Hettinger date: Tue May 12 21:26:37 2015 -0700 summary: Reduce the overhead in functools.total_ordering by localizing NotImplemented. (Sugguested by Serhiy Storchaka) files: Lib/functools.py | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -94,80 +94,80 @@ # infinite recursion that could occur when the operator dispatch logic # detects a NotImplemented result and then calls a reflected method. -def _gt_from_lt(self, other): +def _gt_from_lt(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).' op_result = self.__lt__(other) if op_result is NotImplemented: return op_result return not op_result and self != other -def _le_from_lt(self, other): +def _le_from_lt(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).' op_result = self.__lt__(other) return op_result or self == other -def _ge_from_lt(self, other): +def _ge_from_lt(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (not a < b).' op_result = self.__lt__(other) if op_result is NotImplemented: return op_result return not op_result -def _ge_from_le(self, other): +def _ge_from_le(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).' op_result = self.__le__(other) if op_result is NotImplemented: return op_result return not op_result or self == other -def _lt_from_le(self, other): +def _lt_from_le(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).' op_result = self.__le__(other) if op_result is NotImplemented: return op_result return op_result and self != other -def _gt_from_le(self, other): +def _gt_from_le(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (not a <= b).' op_result = self.__le__(other) if op_result is NotImplemented: return op_result return not op_result -def _lt_from_gt(self, other): +def _lt_from_gt(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).' op_result = self.__gt__(other) if op_result is NotImplemented: return op_result return not op_result and self != other -def _ge_from_gt(self, other): +def _ge_from_gt(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).' op_result = self.__gt__(other) return op_result or self == other -def _le_from_gt(self, other): +def _le_from_gt(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (not a > b).' op_result = self.__gt__(other) if op_result is NotImplemented: return op_result return not op_result -def _le_from_ge(self, other): +def _le_from_ge(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).' op_result = self.__ge__(other) if op_result is NotImplemented: return op_result return not op_result or self == other -def _gt_from_ge(self, other): +def _gt_from_ge(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).' op_result = self.__ge__(other) if op_result is NotImplemented: return op_result return op_result and self != other -def _lt_from_ge(self, other): +def _lt_from_ge(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (not a >= b).' op_result = self.__ge__(other) if op_result is NotImplemented: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 06:40:56 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 04:40:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_More_timings_suggest_that_?= =?utf-8?q?2500_is_closer_to_the_break-even_point=2E?= Message-ID: <20150513044056.82437.29565@psf.io> https://hg.python.org/cpython/rev/159433ed7a36 changeset: 95999:159433ed7a36 user: Raymond Hettinger date: Tue May 12 21:40:50 2015 -0700 summary: More timings suggest that 2500 is closer to the break-even point. files: Modules/_heapqmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -335,7 +335,7 @@ in cache, we prefer the simpler algorithm with less branching. */ n = PyList_GET_SIZE(heap); - if (n > 10000) + if (n > 2500) return cache_friendly_heapify(heap, siftup_func); /* Transform bottom-up. The largest index there's any point to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 06:42:47 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 04:42:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Extend_test_coverage_to_in?= =?utf-8?q?clude_heapifying_large_heaps?= Message-ID: <20150513044247.17001.29456@psf.io> https://hg.python.org/cpython/rev/d246984e1ca0 changeset: 96000:d246984e1ca0 user: Raymond Hettinger date: Tue May 12 21:42:40 2015 -0700 summary: Extend test coverage to include heapifying large heaps files: Lib/test/test_heapq.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -65,7 +65,7 @@ self.assertTrue(heap[parentpos] <= item) def test_heapify(self): - for size in range(30): + for size in list(range(30)) + [20000]: heap = [random.random() for dummy in range(size)] self.module.heapify(heap) self.check_invariant(heap) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 07:01:57 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 05:01:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323193=3A_Skip_num?= =?utf-8?q?eric=5Fowner_tests_on_platforms_where_they_don=27t_make_sense?= Message-ID: <20150513050157.1943.44862@psf.io> https://hg.python.org/cpython/rev/e5a53d75dc19 changeset: 96001:e5a53d75dc19 user: Zachary Ware date: Tue May 12 23:57:21 2015 -0500 summary: Issue #23193: Skip numeric_owner tests on platforms where they don't make sense In particular, the tests bomb out on Windows. The feature is a no-op on platforms without the pwd module or os.geteuid anyway. files: Lib/test/test_tarfile.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -2279,6 +2279,8 @@ return True + at unittest.skipUnless(hasattr(os, 'chown'), "missing os.chown") + at unittest.skipUnless(hasattr(os, 'geteuid'), "missing os.geteuid") class NumericOwnerTest(unittest.TestCase): # mock the following: # os.chown: so we can test what's being called -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 07:27:58 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 05:27:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323731=3A_Fix_trac?= =?utf-8?q?emalloc_test_on_Windows=2E?= Message-ID: <20150513052758.122016.46238@psf.io> https://hg.python.org/cpython/rev/bbdbc4399b52 changeset: 96002:bbdbc4399b52 user: Zachary Ware date: Wed May 13 00:27:01 2015 -0500 summary: Issue #23731: Fix tracemalloc test on Windows. 'a.pyo' can no longer match 'a.py', so 'a.PYO' can't either. files: Lib/test/test_tracemalloc.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -671,7 +671,6 @@ self.assertTrue(fnmatch('aBcDe', 'Ab*dE')) self.assertTrue(fnmatch('a.pyc', 'a.PY')) - self.assertTrue(fnmatch('a.PYO', 'a.py')) self.assertTrue(fnmatch('a.py', 'a.PYC')) else: # case sensitive @@ -679,7 +678,6 @@ self.assertFalse(fnmatch('aBcDe', 'Ab*dE')) self.assertFalse(fnmatch('a.pyc', 'a.PY')) - self.assertFalse(fnmatch('a.PYO', 'a.py')) self.assertFalse(fnmatch('a.py', 'a.PYC')) if os.name == 'nt': @@ -695,6 +693,9 @@ self.assertFalse(fnmatch(r'a/b\c', r'a\b/c')) self.assertFalse(fnmatch(r'a/b/c', r'a\b\c')) + # as of 3.5, .pyo is no longer munged to .py + self.assertFalse(fnmatch('a.pyo', 'a.py')) + def test_filter_match_trace(self): t1 = (("a.py", 2), ("b.py", 3)) t2 = (("b.py", 4), ("b.py", 5)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 07:35:05 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 05:35:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323911=3A_Fix_ctyp?= =?utf-8?q?es_test_on_Windows=2E?= Message-ID: <20150513053505.122028.56203@psf.io> https://hg.python.org/cpython/rev/cc2e52878393 changeset: 96003:cc2e52878393 user: Zachary Ware date: Wed May 13 00:34:39 2015 -0500 summary: Issue #23911: Fix ctypes test on Windows. Comparing equality of list and tuple is always False. files: Lib/ctypes/test/test_values.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py --- a/Lib/ctypes/test/test_values.py +++ b/Lib/ctypes/test/test_values.py @@ -62,10 +62,10 @@ # found, but don't worry about its size too much. The same # applies to _frozen_importlib_external. bootstrap_seen = [] - bootstrap_expected = ( + bootstrap_expected = [ b'_frozen_importlib', b'_frozen_importlib_external', - ) + ] for entry in ft: # This is dangerous. We *can* iterate over a pointer, but # the loop will not terminate (maybe with an access -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 07:54:13 2015 From: python-checkins at python.org (nick.coghlan) Date: Wed, 13 May 2015 05:54:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24017=3A_fix_for_=22?= =?utf-8?q?async_with=22_refcounting?= Message-ID: <20150513055413.108332.93197@psf.io> https://hg.python.org/cpython/rev/e39fd5a8501a changeset: 96004:e39fd5a8501a user: Nick Coghlan date: Wed May 13 15:54:02 2015 +1000 summary: Issue 24017: fix for "async with" refcounting * adds missing INCREF in WITH_CLEANUP_START * adds missing DECREF in WITH_CLEANUP_FINISH * adds several new tests Yury created while investigating this files: Lib/test/test_coroutines.py | 118 +++++++++++++++++++++++- Python/ceval.c | 2 + 2 files changed, 119 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -497,17 +497,133 @@ return self def __aexit__(self, *e): + return 444 + + async def foo(): + async with CM(): + 1/0 + + try: + run_async(foo()) + except TypeError as exc: + self.assertRegex( + exc.args[0], "object int can't be used in 'await' expression") + self.assertTrue(exc.__context__ is not None) + self.assertTrue(isinstance(exc.__context__, ZeroDivisionError)) + else: + self.fail('invalid asynchronous context manager did not fail') + + + def test_with_8(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + def __aexit__(self, *e): return 456 async def foo(): + nonlocal CNT async with CM(): - pass + CNT += 1 + with self.assertRaisesRegex( TypeError, "object int can't be used in 'await' expression"): run_async(foo()) + self.assertEqual(CNT, 1) + + + def test_with_9(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + CNT += 1 + + with self.assertRaises(ZeroDivisionError): + run_async(foo()) + + self.assertEqual(CNT, 1) + + def test_with_10(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + async with CM(): + raise RuntimeError + + try: + run_async(foo()) + except ZeroDivisionError as exc: + self.assertTrue(exc.__context__ is not None) + self.assertTrue(isinstance(exc.__context__, ZeroDivisionError)) + self.assertTrue(isinstance(exc.__context__.__context__, + RuntimeError)) + else: + self.fail('exception from __aexit__ did not propagate') + + def test_with_11(self): + CNT = 0 + + class CM: + async def __aenter__(self): + raise NotImplementedError + + async def __aexit__(self, *e): + 1/0 + + async def foo(): + nonlocal CNT + async with CM(): + raise RuntimeError + + try: + run_async(foo()) + except NotImplementedError as exc: + self.assertTrue(exc.__context__ is None) + else: + self.fail('exception from __aenter__ did not propagate') + + def test_with_12(self): + CNT = 0 + + class CM: + async def __aenter__(self): + return self + + async def __aexit__(self, *e): + return True + + async def foo(): + nonlocal CNT + async with CM() as cm: + self.assertIs(cm.__class__, CM) + raise RuntimeError + + run_async(foo()) + def test_for_1(self): aiter_calls = 0 diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3156,6 +3156,7 @@ if (res == NULL) goto error; + Py_INCREF(exc); /* Duplicating the exception on the stack */ PUSH(exc); PUSH(res); PREDICT(WITH_CLEANUP_FINISH); @@ -3174,6 +3175,7 @@ err = 0; Py_DECREF(res); + Py_DECREF(exc); if (err < 0) goto error; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 08:03:26 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 06:03:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Clean_up_test=5Fcoroutines?= =?utf-8?q?_a_bit=2E?= Message-ID: <20150513060326.1933.29606@psf.io> https://hg.python.org/cpython/rev/78f06ef0ae5a changeset: 96005:78f06ef0ae5a user: Zachary Ware date: Wed May 13 01:03:06 2015 -0500 summary: Clean up test_coroutines a bit. No more test_main(), s/assertEquals/assertEqual/, and remove unused import. files: Lib/test/test_coroutines.py | 15 +++------------ 1 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -1,5 +1,4 @@ import contextlib -import gc import sys import types import unittest @@ -185,8 +184,8 @@ await bar() f = foo() - self.assertEquals(f.send(None), 1) - self.assertEquals(f.send(None), 2) + self.assertEqual(f.send(None), 1) + self.assertEqual(f.send(None), 2) with self.assertRaises(StopIteration): f.send(None) @@ -968,13 +967,5 @@ self.assertEqual(foo().send(None), 1) -def test_main(): - support.run_unittest(AsyncBadSyntaxTest, - CoroutineTest, - CoroAsyncIOCompatTest, - SysSetCoroWrapperTest, - CAPITest) - - if __name__=="__main__": - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 08:32:28 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 06:32:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320172=3A_Convert_?= =?utf-8?q?the_winsound_module_to_Argument_Clinic=2E?= Message-ID: <20150513063228.8157.35819@psf.io> https://hg.python.org/cpython/rev/d3582826d24c changeset: 96006:d3582826d24c user: Zachary Ware date: Wed May 13 01:21:21 2015 -0500 summary: Issue #20172: Convert the winsound module to Argument Clinic. files: PC/clinic/winsound.c.h | 103 +++++++++++++++++++++++ PC/winsound.c | 129 ++++++++++++++++------------ 2 files changed, 176 insertions(+), 56 deletions(-) diff --git a/PC/clinic/winsound.c.h b/PC/clinic/winsound.c.h new file mode 100644 --- /dev/null +++ b/PC/clinic/winsound.c.h @@ -0,0 +1,103 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(winsound_PlaySound__doc__, +"PlaySound($module, sound, flags, /)\n" +"--\n" +"\n" +"A wrapper around the Windows PlaySound API.\n" +"\n" +" sound\n" +" The sound to play; a filename, data, or None.\n" +" flags\n" +" Flag values, ored together. See module documentation."); + +#define WINSOUND_PLAYSOUND_METHODDEF \ + {"PlaySound", (PyCFunction)winsound_PlaySound, METH_VARARGS, winsound_PlaySound__doc__}, + +static PyObject * +winsound_PlaySound_impl(PyModuleDef *module, Py_UNICODE *sound, int flags); + +static PyObject * +winsound_PlaySound(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_UNICODE *sound; + int flags; + + if (!PyArg_ParseTuple(args, + "Zi:PlaySound", + &sound, &flags)) + goto exit; + return_value = winsound_PlaySound_impl(module, sound, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(winsound_Beep__doc__, +"Beep($module, frequency, duration, /)\n" +"--\n" +"\n" +"A wrapper around the Windows Beep API.\n" +"\n" +" frequency\n" +" Frequency of the sound in hertz.\n" +" Must be in the range 37 through 32,767.\n" +" duration\n" +" How long the sound should play, in milliseconds."); + +#define WINSOUND_BEEP_METHODDEF \ + {"Beep", (PyCFunction)winsound_Beep, METH_VARARGS, winsound_Beep__doc__}, + +static PyObject * +winsound_Beep_impl(PyModuleDef *module, int frequency, int duration); + +static PyObject * +winsound_Beep(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int frequency; + int duration; + + if (!PyArg_ParseTuple(args, + "ii:Beep", + &frequency, &duration)) + goto exit; + return_value = winsound_Beep_impl(module, frequency, duration); + +exit: + return return_value; +} + +PyDoc_STRVAR(winsound_MessageBeep__doc__, +"MessageBeep($module, x=MB_OK, /)\n" +"--\n" +"\n" +"Call Windows MessageBeep(x).\n" +"\n" +"x defaults to MB_OK."); + +#define WINSOUND_MESSAGEBEEP_METHODDEF \ + {"MessageBeep", (PyCFunction)winsound_MessageBeep, METH_VARARGS, winsound_MessageBeep__doc__}, + +static PyObject * +winsound_MessageBeep_impl(PyModuleDef *module, int x); + +static PyObject * +winsound_MessageBeep(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int x = MB_OK; + + if (!PyArg_ParseTuple(args, + "|i:MessageBeep", + &x)) + goto exit; + return_value = winsound_MessageBeep_impl(module, x); + +exit: + return return_value; +} +/*[clinic end generated code: output=89c85ed36c3af2fd input=a9049054013a1b77]*/ diff --git a/PC/winsound.c b/PC/winsound.c --- a/PC/winsound.c +++ b/PC/winsound.c @@ -39,22 +39,6 @@ #include #include -PyDoc_STRVAR(sound_playsound_doc, -"PlaySound(sound, flags) - a wrapper around the Windows PlaySound API\n" -"\n" -"The sound argument can be a filename, data, or None.\n" -"For flag values, ored together, see module documentation."); - -PyDoc_STRVAR(sound_beep_doc, -"Beep(frequency, duration) - a wrapper around the Windows Beep API\n" -"\n" -"The frequency argument specifies frequency, in hertz, of the sound.\n" -"This parameter must be in the range 37 through 32,767.\n" -"The duration argument specifies the number of milliseconds.\n"); - -PyDoc_STRVAR(sound_msgbeep_doc, -"MessageBeep(x) - call Windows MessageBeep(x). x defaults to MB_OK."); - PyDoc_STRVAR(sound_module_doc, "PlaySound(sound, flags) - play a sound\n" "SND_FILENAME - sound is a wav file name\n" @@ -67,79 +51,112 @@ "SND_NOSTOP - Do not interrupt any sounds currently playing\n" // Raising RuntimeError if needed "SND_NOWAIT - Return immediately if the sound driver is busy\n" // Without any errors "\n" -"Beep(frequency, duration) - Make a beep through the PC speaker."); +"Beep(frequency, duration) - Make a beep through the PC speaker.\n" +"MessageBeep(x) - Call Windows MessageBeep."); + +/*[clinic input] +module winsound +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a18401142d97b8d5]*/ + +#include "clinic/winsound.c.h" + +/*[clinic input] +winsound.PlaySound + + sound: Py_UNICODE(nullable=True) + The sound to play; a filename, data, or None. + flags: int + Flag values, ored together. See module documentation. + / + +A wrapper around the Windows PlaySound API. +[clinic start generated code]*/ static PyObject * -sound_playsound(PyObject *s, PyObject *args) +winsound_PlaySound_impl(PyModuleDef *module, Py_UNICODE *sound, int flags) +/*[clinic end generated code: output=614273784bf59e5c input=c86fab5d8e86f31d]*/ { - wchar_t *wsound; - int flags; int ok; - if (PyArg_ParseTuple(args, "Zi:PlaySound", &wsound, &flags)) { - if (flags & SND_ASYNC && flags & SND_MEMORY) { - /* Sidestep reference counting headache; unfortunately this also - prevent SND_LOOP from memory. */ - PyErr_SetString(PyExc_RuntimeError, "Cannot play asynchronously from memory"); - return NULL; - } - Py_BEGIN_ALLOW_THREADS - ok = PlaySoundW(wsound, NULL, flags); - Py_END_ALLOW_THREADS - if (!ok) { - PyErr_SetString(PyExc_RuntimeError, "Failed to play sound"); - return NULL; - } - Py_INCREF(Py_None); - return Py_None; + if (flags & SND_ASYNC && flags & SND_MEMORY) { + /* Sidestep reference counting headache; unfortunately this also + prevent SND_LOOP from memory. */ + PyErr_SetString(PyExc_RuntimeError, + "Cannot play asynchronously from memory"); + return NULL; } - return NULL; + + Py_BEGIN_ALLOW_THREADS + ok = PlaySoundW(sound, NULL, flags); + Py_END_ALLOW_THREADS + if (!ok) { + PyErr_SetString(PyExc_RuntimeError, "Failed to play sound"); + return NULL; + } + Py_RETURN_NONE; } +/*[clinic input] +winsound.Beep + + frequency: int + Frequency of the sound in hertz. + Must be in the range 37 through 32,767. + duration: int + How long the sound should play, in milliseconds. + / + +A wrapper around the Windows Beep API. +[clinic start generated code]*/ + static PyObject * -sound_beep(PyObject *self, PyObject *args) +winsound_Beep_impl(PyModuleDef *module, int frequency, int duration) +/*[clinic end generated code: output=c75f282035a872bd input=628a99d2ddf73798]*/ { - int freq; - int dur; BOOL ok; - if (!PyArg_ParseTuple(args, "ii:Beep", &freq, &dur)) - return NULL; - - if (freq < 37 || freq > 32767) { + if (frequency < 37 || frequency > 32767) { PyErr_SetString(PyExc_ValueError, "frequency must be in 37 thru 32767"); return NULL; } Py_BEGIN_ALLOW_THREADS - ok = Beep(freq, dur); + ok = Beep(frequency, duration); Py_END_ALLOW_THREADS if (!ok) { PyErr_SetString(PyExc_RuntimeError,"Failed to beep"); return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winsound.MessageBeep + + x: int(c_default="MB_OK") = MB_OK + / + +Call Windows MessageBeep(x). + +x defaults to MB_OK. +[clinic start generated code]*/ + static PyObject * -sound_msgbeep(PyObject *self, PyObject *args) +winsound_MessageBeep_impl(PyModuleDef *module, int x) +/*[clinic end generated code: output=92aa6a822bdc66ad input=a776c8a85c9853f6]*/ { - int x = MB_OK; - if (!PyArg_ParseTuple(args, "|i:MessageBeep", &x)) - return NULL; MessageBeep(x); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static struct PyMethodDef sound_methods[] = { - {"PlaySound", sound_playsound, METH_VARARGS, sound_playsound_doc}, - {"Beep", sound_beep, METH_VARARGS, sound_beep_doc}, - {"MessageBeep", sound_msgbeep, METH_VARARGS, sound_msgbeep_doc}, + WINSOUND_PLAYSOUND_METHODDEF + WINSOUND_BEEP_METHODDEF + WINSOUND_MESSAGEBEEP_METHODDEF {NULL, NULL} }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 08:32:28 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 06:32:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320172=3A_Convert_?= =?utf-8?q?the_winreg_module_to_Argument_Clinic=2E?= Message-ID: <20150513063228.1913.77017@psf.io> https://hg.python.org/cpython/rev/6e613ecd70f0 changeset: 96007:6e613ecd70f0 user: Zachary Ware date: Wed May 13 01:21:57 2015 -0500 summary: Issue #20172: Convert the winreg module to Argument Clinic. files: PC/clinic/winreg.c.h | 1078 +++++++++++++++++++++++ PC/winreg.c | 1393 +++++++++++++++-------------- 2 files changed, 1801 insertions(+), 670 deletions(-) diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h new file mode 100644 --- /dev/null +++ b/PC/clinic/winreg.c.h @@ -0,0 +1,1078 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(winreg_HKEYType_Close__doc__, +"Close($self, /)\n" +"--\n" +"\n" +"Closes the underlying Windows handle.\n" +"\n" +"If the handle is already closed, no error is raised."); + +#define WINREG_HKEYTYPE_CLOSE_METHODDEF \ + {"Close", (PyCFunction)winreg_HKEYType_Close, METH_NOARGS, winreg_HKEYType_Close__doc__}, + +static PyObject * +winreg_HKEYType_Close_impl(PyHKEYObject *self); + +static PyObject * +winreg_HKEYType_Close(PyHKEYObject *self, PyObject *Py_UNUSED(ignored)) +{ + return winreg_HKEYType_Close_impl(self); +} + +PyDoc_STRVAR(winreg_HKEYType_Detach__doc__, +"Detach($self, /)\n" +"--\n" +"\n" +"Detaches the Windows handle from the handle object.\n" +"\n" +"The result is the value of the handle before it is detached. If the\n" +"handle is already detached, this will return zero.\n" +"\n" +"After calling this function, the handle is effectively invalidated,\n" +"but the handle is not closed. You would call this function when you\n" +"need the underlying win32 handle to exist beyond the lifetime of the\n" +"handle object."); + +#define WINREG_HKEYTYPE_DETACH_METHODDEF \ + {"Detach", (PyCFunction)winreg_HKEYType_Detach, METH_NOARGS, winreg_HKEYType_Detach__doc__}, + +static PyObject * +winreg_HKEYType_Detach_impl(PyHKEYObject *self); + +static PyObject * +winreg_HKEYType_Detach(PyHKEYObject *self, PyObject *Py_UNUSED(ignored)) +{ + return winreg_HKEYType_Detach_impl(self); +} + +PyDoc_STRVAR(winreg_HKEYType___enter____doc__, +"__enter__($self, /)\n" +"--\n" +"\n"); + +#define WINREG_HKEYTYPE___ENTER___METHODDEF \ + {"__enter__", (PyCFunction)winreg_HKEYType___enter__, METH_NOARGS, winreg_HKEYType___enter____doc__}, + +static PyHKEYObject * +winreg_HKEYType___enter___impl(PyHKEYObject *self); + +static PyObject * +winreg_HKEYType___enter__(PyHKEYObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + PyHKEYObject *_return_value; + + _return_value = winreg_HKEYType___enter___impl(self); + return_value = (PyObject *)_return_value; + + return return_value; +} + +PyDoc_STRVAR(winreg_HKEYType___exit____doc__, +"__exit__($self, /, exc_type, exc_value, traceback)\n" +"--\n" +"\n"); + +#define WINREG_HKEYTYPE___EXIT___METHODDEF \ + {"__exit__", (PyCFunction)winreg_HKEYType___exit__, METH_VARARGS|METH_KEYWORDS, winreg_HKEYType___exit____doc__}, + +static PyObject * +winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback); + +static PyObject * +winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"exc_type", "exc_value", "traceback", NULL}; + PyObject *exc_type; + PyObject *exc_value; + PyObject *traceback; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "OOO:__exit__", _keywords, + &exc_type, &exc_value, &traceback)) + goto exit; + return_value = winreg_HKEYType___exit___impl(self, exc_type, exc_value, traceback); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_CloseKey__doc__, +"CloseKey($module, hkey, /)\n" +"--\n" +"\n" +"Closes a previously opened registry key.\n" +"\n" +" hkey\n" +" A previously opened key.\n" +"\n" +"Note that if the key is not closed using this method, it will be\n" +"closed when the hkey object is destroyed by Python."); + +#define WINREG_CLOSEKEY_METHODDEF \ + {"CloseKey", (PyCFunction)winreg_CloseKey, METH_O, winreg_CloseKey__doc__}, + +PyDoc_STRVAR(winreg_ConnectRegistry__doc__, +"ConnectRegistry($module, computer_name, key, /)\n" +"--\n" +"\n" +"Establishes a connection to the registry on on another computer.\n" +"\n" +" computer_name\n" +" The name of the remote computer, of the form r\"\\\\computername\". If\n" +" None, the local computer is used.\n" +" key\n" +" The predefined key to connect to.\n" +"\n" +"The return value is the handle of the opened key.\n" +"If the function fails, an OSError exception is raised."); + +#define WINREG_CONNECTREGISTRY_METHODDEF \ + {"ConnectRegistry", (PyCFunction)winreg_ConnectRegistry, METH_VARARGS, winreg_ConnectRegistry__doc__}, + +static HKEY +winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, HKEY key); + +static PyObject * +winreg_ConnectRegistry(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_UNICODE *computer_name; + HKEY key; + HKEY _return_value; + + if (!PyArg_ParseTuple(args, + "ZO&:ConnectRegistry", + &computer_name, clinic_HKEY_converter, &key)) + goto exit; + _return_value = winreg_ConnectRegistry_impl(module, computer_name, key); + if (_return_value == NULL) + goto exit; + return_value = PyHKEY_FromHKEY(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_CreateKey__doc__, +"CreateKey($module, key, sub_key, /)\n" +"--\n" +"\n" +"Creates or opens the specified key.\n" +"\n" +" key\n" +" An already open key, or one of the predefined HKEY_* constants.\n" +" sub_key\n" +" The name of the key this method opens or creates.\n" +"\n" +"If key is one of the predefined keys, sub_key may be None. In that case,\n" +"the handle returned is the same key handle passed in to the function.\n" +"\n" +"If the key already exists, this function opens the existing key.\n" +"\n" +"The return value is the handle of the opened key.\n" +"If the function fails, an OSError exception is raised."); + +#define WINREG_CREATEKEY_METHODDEF \ + {"CreateKey", (PyCFunction)winreg_CreateKey, METH_VARARGS, winreg_CreateKey__doc__}, + +static HKEY +winreg_CreateKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key); + +static PyObject * +winreg_CreateKey(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *sub_key; + HKEY _return_value; + + if (!PyArg_ParseTuple(args, + "O&Z:CreateKey", + clinic_HKEY_converter, &key, &sub_key)) + goto exit; + _return_value = winreg_CreateKey_impl(module, key, sub_key); + if (_return_value == NULL) + goto exit; + return_value = PyHKEY_FromHKEY(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_CreateKeyEx__doc__, +"CreateKeyEx($module, /, key, sub_key, reserved=0,\n" +" access=winreg.KEY_WRITE)\n" +"--\n" +"\n" +"Creates or opens the specified key.\n" +"\n" +" key\n" +" An already open key, or one of the predefined HKEY_* constants.\n" +" sub_key\n" +" The name of the key this method opens or creates.\n" +" reserved\n" +" A reserved integer, and must be zero. Default is zero.\n" +" access\n" +" An integer that specifies an access mask that describes the\n" +" desired security access for the key. Default is KEY_WRITE.\n" +"\n" +"If key is one of the predefined keys, sub_key may be None. In that case,\n" +"the handle returned is the same key handle passed in to the function.\n" +"\n" +"If the key already exists, this function opens the existing key\n" +"\n" +"The return value is the handle of the opened key.\n" +"If the function fails, an OSError exception is raised."); + +#define WINREG_CREATEKEYEX_METHODDEF \ + {"CreateKeyEx", (PyCFunction)winreg_CreateKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_CreateKeyEx__doc__}, + +static HKEY +winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); + +static PyObject * +winreg_CreateKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL}; + HKEY key; + Py_UNICODE *sub_key; + int reserved = 0; + REGSAM access = KEY_WRITE; + HKEY _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&Z|ii:CreateKeyEx", _keywords, + clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) + goto exit; + _return_value = winreg_CreateKeyEx_impl(module, key, sub_key, reserved, access); + if (_return_value == NULL) + goto exit; + return_value = PyHKEY_FromHKEY(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_DeleteKey__doc__, +"DeleteKey($module, key, sub_key, /)\n" +"--\n" +"\n" +"Deletes the specified key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that must be the name of a subkey of the key identified by\n" +" the key parameter. This value must not be None, and the key may not\n" +" have subkeys.\n" +"\n" +"This method can not delete keys with subkeys.\n" +"\n" +"If the function succeeds, the entire key, including all of its values,\n" +"is removed. If the function fails, an OSError exception is raised."); + +#define WINREG_DELETEKEY_METHODDEF \ + {"DeleteKey", (PyCFunction)winreg_DeleteKey, METH_VARARGS, winreg_DeleteKey__doc__}, + +static PyObject * +winreg_DeleteKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key); + +static PyObject * +winreg_DeleteKey(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *sub_key; + + if (!PyArg_ParseTuple(args, + "O&u:DeleteKey", + clinic_HKEY_converter, &key, &sub_key)) + goto exit; + return_value = winreg_DeleteKey_impl(module, key, sub_key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_DeleteKeyEx__doc__, +"DeleteKeyEx($module, /, key, sub_key, access=winreg.KEY_WOW64_64KEY,\n" +" reserved=0)\n" +"--\n" +"\n" +"Deletes the specified key (64-bit OS only).\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that must be the name of a subkey of the key identified by\n" +" the key parameter. This value must not be None, and the key may not\n" +" have subkeys.\n" +" access\n" +" An integer that specifies an access mask that describes the\n" +" desired security access for the key. Default is KEY_WOW64_64KEY.\n" +" reserved\n" +" A reserved integer, and must be zero. Default is zero.\n" +"\n" +"This method can not delete keys with subkeys.\n" +"\n" +"If the function succeeds, the entire key, including all of its values,\n" +"is removed. If the function fails, an OSError exception is raised.\n" +"On unsupported Windows versions, NotImplementedError is raised."); + +#define WINREG_DELETEKEYEX_METHODDEF \ + {"DeleteKeyEx", (PyCFunction)winreg_DeleteKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_DeleteKeyEx__doc__}, + +static PyObject * +winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, REGSAM access, int reserved); + +static PyObject * +winreg_DeleteKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "sub_key", "access", "reserved", NULL}; + HKEY key; + Py_UNICODE *sub_key; + REGSAM access = KEY_WOW64_64KEY; + int reserved = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&u|ii:DeleteKeyEx", _keywords, + clinic_HKEY_converter, &key, &sub_key, &access, &reserved)) + goto exit; + return_value = winreg_DeleteKeyEx_impl(module, key, sub_key, access, reserved); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_DeleteValue__doc__, +"DeleteValue($module, key, value, /)\n" +"--\n" +"\n" +"Removes a named value from a registry key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" value\n" +" A string that identifies the value to remove."); + +#define WINREG_DELETEVALUE_METHODDEF \ + {"DeleteValue", (PyCFunction)winreg_DeleteValue, METH_VARARGS, winreg_DeleteValue__doc__}, + +static PyObject * +winreg_DeleteValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value); + +static PyObject * +winreg_DeleteValue(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *value; + + if (!PyArg_ParseTuple(args, + "O&Z:DeleteValue", + clinic_HKEY_converter, &key, &value)) + goto exit; + return_value = winreg_DeleteValue_impl(module, key, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_EnumKey__doc__, +"EnumKey($module, key, index, /)\n" +"--\n" +"\n" +"Enumerates subkeys of an open registry key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" index\n" +" An integer that identifies the index of the key to retrieve.\n" +"\n" +"The function retrieves the name of one subkey each time it is called.\n" +"It is typically called repeatedly until an OSError exception is\n" +"raised, indicating no more values are available."); + +#define WINREG_ENUMKEY_METHODDEF \ + {"EnumKey", (PyCFunction)winreg_EnumKey, METH_VARARGS, winreg_EnumKey__doc__}, + +static PyObject * +winreg_EnumKey_impl(PyModuleDef *module, HKEY key, int index); + +static PyObject * +winreg_EnumKey(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + int index; + + if (!PyArg_ParseTuple(args, + "O&i:EnumKey", + clinic_HKEY_converter, &key, &index)) + goto exit; + return_value = winreg_EnumKey_impl(module, key, index); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_EnumValue__doc__, +"EnumValue($module, key, index, /)\n" +"--\n" +"\n" +"Enumerates values of an open registry key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" index\n" +" An integer that identifies the index of the value to retrieve.\n" +"\n" +"The function retrieves the name of one subkey each time it is called.\n" +"It is typically called repeatedly, until an OSError exception\n" +"is raised, indicating no more values.\n" +"\n" +"The result is a tuple of 3 items:\n" +" value_name\n" +" A string that identifies the value.\n" +" value_data\n" +" An object that holds the value data, and whose type depends\n" +" on the underlying registry type.\n" +" data_type\n" +" An integer that identifies the type of the value data."); + +#define WINREG_ENUMVALUE_METHODDEF \ + {"EnumValue", (PyCFunction)winreg_EnumValue, METH_VARARGS, winreg_EnumValue__doc__}, + +static PyObject * +winreg_EnumValue_impl(PyModuleDef *module, HKEY key, int index); + +static PyObject * +winreg_EnumValue(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + int index; + + if (!PyArg_ParseTuple(args, + "O&i:EnumValue", + clinic_HKEY_converter, &key, &index)) + goto exit; + return_value = winreg_EnumValue_impl(module, key, index); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_ExpandEnvironmentStrings__doc__, +"ExpandEnvironmentStrings($module, string, /)\n" +"--\n" +"\n" +"Expand environment vars."); + +#define WINREG_EXPANDENVIRONMENTSTRINGS_METHODDEF \ + {"ExpandEnvironmentStrings", (PyCFunction)winreg_ExpandEnvironmentStrings, METH_O, winreg_ExpandEnvironmentStrings__doc__}, + +static PyObject * +winreg_ExpandEnvironmentStrings_impl(PyModuleDef *module, Py_UNICODE *string); + +static PyObject * +winreg_ExpandEnvironmentStrings(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_UNICODE *string; + + if (!PyArg_Parse(arg, + "u:ExpandEnvironmentStrings", + &string)) + goto exit; + return_value = winreg_ExpandEnvironmentStrings_impl(module, string); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_FlushKey__doc__, +"FlushKey($module, key, /)\n" +"--\n" +"\n" +"Writes all the attributes of a key to the registry.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +"\n" +"It is not necessary to call FlushKey to change a key. Registry changes\n" +"are flushed to disk by the registry using its lazy flusher. Registry\n" +"changes are also flushed to disk at system shutdown. Unlike\n" +"CloseKey(), the FlushKey() method returns only when all the data has\n" +"been written to the registry.\n" +"\n" +"An application should only call FlushKey() if it requires absolute\n" +"certainty that registry changes are on disk. If you don\'t know whether\n" +"a FlushKey() call is required, it probably isn\'t."); + +#define WINREG_FLUSHKEY_METHODDEF \ + {"FlushKey", (PyCFunction)winreg_FlushKey, METH_O, winreg_FlushKey__doc__}, + +static PyObject * +winreg_FlushKey_impl(PyModuleDef *module, HKEY key); + +static PyObject * +winreg_FlushKey(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HKEY key; + + if (!PyArg_Parse(arg, + "O&:FlushKey", + clinic_HKEY_converter, &key)) + goto exit; + return_value = winreg_FlushKey_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_LoadKey__doc__, +"LoadKey($module, key, sub_key, file_name, /)\n" +"--\n" +"\n" +"Insert data into the registry from a file.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that identifies the sub-key to load.\n" +" file_name\n" +" The name of the file to load registry data from. This file must\n" +" have been created with the SaveKey() function. Under the file\n" +" allocation table (FAT) file system, the filename may not have an\n" +" extension.\n" +"\n" +"Creates a subkey under the specified key and stores registration\n" +"information from a specified file into that subkey.\n" +"\n" +"A call to LoadKey() fails if the calling process does not have the\n" +"SE_RESTORE_PRIVILEGE privilege.\n" +"\n" +"If key is a handle returned by ConnectRegistry(), then the path\n" +"specified in fileName is relative to the remote computer.\n" +"\n" +"The MSDN docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE\n" +"tree."); + +#define WINREG_LOADKEY_METHODDEF \ + {"LoadKey", (PyCFunction)winreg_LoadKey, METH_VARARGS, winreg_LoadKey__doc__}, + +static PyObject * +winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, Py_UNICODE *file_name); + +static PyObject * +winreg_LoadKey(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *sub_key; + Py_UNICODE *file_name; + + if (!PyArg_ParseTuple(args, + "O&uu:LoadKey", + clinic_HKEY_converter, &key, &sub_key, &file_name)) + goto exit; + return_value = winreg_LoadKey_impl(module, key, sub_key, file_name); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_OpenKey__doc__, +"OpenKey($module, /, key, sub_key, reserved=0, access=winreg.KEY_READ)\n" +"--\n" +"\n" +"Opens the specified key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that identifies the sub_key to open.\n" +" reserved\n" +" A reserved integer that must be zero. Default is zero.\n" +" access\n" +" An integer that specifies an access mask that describes the desired\n" +" security access for the key. Default is KEY_READ.\n" +"\n" +"The result is a new handle to the specified key.\n" +"If the function fails, an OSError exception is raised."); + +#define WINREG_OPENKEY_METHODDEF \ + {"OpenKey", (PyCFunction)winreg_OpenKey, METH_VARARGS|METH_KEYWORDS, winreg_OpenKey__doc__}, + +static HKEY +winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); + +static PyObject * +winreg_OpenKey(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL}; + HKEY key; + Py_UNICODE *sub_key; + int reserved = 0; + REGSAM access = KEY_READ; + HKEY _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&Z|ii:OpenKey", _keywords, + clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) + goto exit; + _return_value = winreg_OpenKey_impl(module, key, sub_key, reserved, access); + if (_return_value == NULL) + goto exit; + return_value = PyHKEY_FromHKEY(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_OpenKeyEx__doc__, +"OpenKeyEx($module, /, key, sub_key, reserved=0, access=winreg.KEY_READ)\n" +"--\n" +"\n" +"Opens the specified key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that identifies the sub_key to open.\n" +" reserved\n" +" A reserved integer that must be zero. Default is zero.\n" +" access\n" +" An integer that specifies an access mask that describes the desired\n" +" security access for the key. Default is KEY_READ.\n" +"\n" +"The result is a new handle to the specified key.\n" +"If the function fails, an OSError exception is raised."); + +#define WINREG_OPENKEYEX_METHODDEF \ + {"OpenKeyEx", (PyCFunction)winreg_OpenKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_OpenKeyEx__doc__}, + +static HKEY +winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); + +static PyObject * +winreg_OpenKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL}; + HKEY key; + Py_UNICODE *sub_key; + int reserved = 0; + REGSAM access = KEY_READ; + HKEY _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&Z|ii:OpenKeyEx", _keywords, + clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) + goto exit; + _return_value = winreg_OpenKeyEx_impl(module, key, sub_key, reserved, access); + if (_return_value == NULL) + goto exit; + return_value = PyHKEY_FromHKEY(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_QueryInfoKey__doc__, +"QueryInfoKey($module, key, /)\n" +"--\n" +"\n" +"Returns information about a key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +"\n" +"The result is a tuple of 3 items:\n" +"An integer that identifies the number of sub keys this key has.\n" +"An integer that identifies the number of values this key has.\n" +"An integer that identifies when the key was last modified (if available)\n" +"as 100\'s of nanoseconds since Jan 1, 1600."); + +#define WINREG_QUERYINFOKEY_METHODDEF \ + {"QueryInfoKey", (PyCFunction)winreg_QueryInfoKey, METH_O, winreg_QueryInfoKey__doc__}, + +static PyObject * +winreg_QueryInfoKey_impl(PyModuleDef *module, HKEY key); + +static PyObject * +winreg_QueryInfoKey(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HKEY key; + + if (!PyArg_Parse(arg, + "O&:QueryInfoKey", + clinic_HKEY_converter, &key)) + goto exit; + return_value = winreg_QueryInfoKey_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_QueryValue__doc__, +"QueryValue($module, key, sub_key, /)\n" +"--\n" +"\n" +"Retrieves the unnamed value for a key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that holds the name of the subkey with which the value\n" +" is associated. If this parameter is None or empty, the function\n" +" retrieves the value set by the SetValue() method for the key\n" +" identified by key.\n" +"\n" +"Values in the registry have name, type, and data components. This method\n" +"retrieves the data for a key\'s first value that has a NULL name.\n" +"But since the underlying API call doesn\'t return the type, you\'ll\n" +"probably be happier using QueryValueEx; this function is just here for\n" +"completeness."); + +#define WINREG_QUERYVALUE_METHODDEF \ + {"QueryValue", (PyCFunction)winreg_QueryValue, METH_VARARGS, winreg_QueryValue__doc__}, + +static PyObject * +winreg_QueryValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key); + +static PyObject * +winreg_QueryValue(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *sub_key; + + if (!PyArg_ParseTuple(args, + "O&Z:QueryValue", + clinic_HKEY_converter, &key, &sub_key)) + goto exit; + return_value = winreg_QueryValue_impl(module, key, sub_key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_QueryValueEx__doc__, +"QueryValueEx($module, key, name, /)\n" +"--\n" +"\n" +"Retrieves the type and value of a specified sub-key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" name\n" +" A string indicating the value to query.\n" +"\n" +"Behaves mostly like QueryValue(), but also returns the type of the\n" +"specified value name associated with the given open registry key.\n" +"\n" +"The return value is a tuple of the value and the type_id."); + +#define WINREG_QUERYVALUEEX_METHODDEF \ + {"QueryValueEx", (PyCFunction)winreg_QueryValueEx, METH_VARARGS, winreg_QueryValueEx__doc__}, + +static PyObject * +winreg_QueryValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *name); + +static PyObject * +winreg_QueryValueEx(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *name; + + if (!PyArg_ParseTuple(args, + "O&Z:QueryValueEx", + clinic_HKEY_converter, &key, &name)) + goto exit; + return_value = winreg_QueryValueEx_impl(module, key, name); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_SaveKey__doc__, +"SaveKey($module, key, file_name, /)\n" +"--\n" +"\n" +"Saves the specified key, and all its subkeys to the specified file.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" file_name\n" +" The name of the file to save registry data to. This file cannot\n" +" already exist. If this filename includes an extension, it cannot be\n" +" used on file allocation table (FAT) file systems by the LoadKey(),\n" +" ReplaceKey() or RestoreKey() methods.\n" +"\n" +"If key represents a key on a remote computer, the path described by\n" +"file_name is relative to the remote computer.\n" +"\n" +"The caller of this method must possess the SeBackupPrivilege\n" +"security privilege. This function passes NULL for security_attributes\n" +"to the API."); + +#define WINREG_SAVEKEY_METHODDEF \ + {"SaveKey", (PyCFunction)winreg_SaveKey, METH_VARARGS, winreg_SaveKey__doc__}, + +static PyObject * +winreg_SaveKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *file_name); + +static PyObject * +winreg_SaveKey(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *file_name; + + if (!PyArg_ParseTuple(args, + "O&u:SaveKey", + clinic_HKEY_converter, &key, &file_name)) + goto exit; + return_value = winreg_SaveKey_impl(module, key, file_name); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_SetValue__doc__, +"SetValue($module, key, sub_key, type, value, /)\n" +"--\n" +"\n" +"Associates a value with a specified key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" sub_key\n" +" A string that names the subkey with which the value is associated.\n" +" type\n" +" An integer that specifies the type of the data. Currently this must\n" +" be REG_SZ, meaning only strings are supported.\n" +" value\n" +" A string that specifies the new value.\n" +"\n" +"If the key specified by the sub_key parameter does not exist, the\n" +"SetValue function creates it.\n" +"\n" +"Value lengths are limited by available memory. Long values (more than\n" +"2048 bytes) should be stored as files with the filenames stored in\n" +"the configuration registry to help the registry perform efficiently.\n" +"\n" +"The key identified by the key parameter must have been opened with\n" +"KEY_SET_VALUE access."); + +#define WINREG_SETVALUE_METHODDEF \ + {"SetValue", (PyCFunction)winreg_SetValue, METH_VARARGS, winreg_SetValue__doc__}, + +static PyObject * +winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, DWORD type, Py_UNICODE *value, Py_ssize_clean_t value_length); + +static PyObject * +winreg_SetValue(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *sub_key; + DWORD type; + Py_UNICODE *value; + Py_ssize_clean_t value_length; + + if (!PyArg_ParseTuple(args, + "O&Zku#:SetValue", + clinic_HKEY_converter, &key, &sub_key, &type, &value, &value_length)) + goto exit; + return_value = winreg_SetValue_impl(module, key, sub_key, type, value, value_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_SetValueEx__doc__, +"SetValueEx($module, key, value_name, reserved, type, value, /)\n" +"--\n" +"\n" +"Stores data in the value field of an open registry key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +" value_name\n" +" A string containing the name of the value to set, or None.\n" +" reserved\n" +" Can be anything - zero is always passed to the API.\n" +" type\n" +" An integer that specifies the type of the data, one of:\n" +" REG_BINARY -- Binary data in any form.\n" +" REG_DWORD -- A 32-bit number.\n" +" REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format.\n" +" REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format.\n" +" REG_EXPAND_SZ -- A null-terminated string that contains unexpanded\n" +" references to environment variables (for example,\n" +" %PATH%).\n" +" REG_LINK -- A Unicode symbolic link.\n" +" REG_MULTI_SZ -- An sequence of null-terminated strings, terminated\n" +" by two null characters. Note that Python handles\n" +" this termination automatically.\n" +" REG_NONE -- No defined value type.\n" +" REG_RESOURCE_LIST -- A device-driver resource list.\n" +" REG_SZ -- A null-terminated string.\n" +" value\n" +" A string that specifies the new value.\n" +"\n" +"This method can also set additional value and type information for the\n" +"specified key. The key identified by the key parameter must have been\n" +"opened with KEY_SET_VALUE access.\n" +"\n" +"To open the key, use the CreateKeyEx() or OpenKeyEx() methods.\n" +"\n" +"Value lengths are limited by available memory. Long values (more than\n" +"2048 bytes) should be stored as files with the filenames stored in\n" +"the configuration registry to help the registry perform efficiently."); + +#define WINREG_SETVALUEEX_METHODDEF \ + {"SetValueEx", (PyCFunction)winreg_SetValueEx, METH_VARARGS, winreg_SetValueEx__doc__}, + +static PyObject * +winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, PyObject *reserved, DWORD type, PyObject *value); + +static PyObject * +winreg_SetValueEx(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HKEY key; + Py_UNICODE *value_name; + PyObject *reserved; + DWORD type; + PyObject *value; + + if (!PyArg_ParseTuple(args, + "O&ZOkO:SetValueEx", + clinic_HKEY_converter, &key, &value_name, &reserved, &type, &value)) + goto exit; + return_value = winreg_SetValueEx_impl(module, key, value_name, reserved, type, value); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_DisableReflectionKey__doc__, +"DisableReflectionKey($module, key, /)\n" +"--\n" +"\n" +"Disables registry reflection for 32bit processes running on a 64bit OS.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +"\n" +"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"\n" +"If the key is not on the reflection list, the function succeeds but has\n" +"no effect. Disabling reflection for a key does not affect reflection\n" +"of any subkeys."); + +#define WINREG_DISABLEREFLECTIONKEY_METHODDEF \ + {"DisableReflectionKey", (PyCFunction)winreg_DisableReflectionKey, METH_O, winreg_DisableReflectionKey__doc__}, + +static PyObject * +winreg_DisableReflectionKey_impl(PyModuleDef *module, HKEY key); + +static PyObject * +winreg_DisableReflectionKey(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HKEY key; + + if (!PyArg_Parse(arg, + "O&:DisableReflectionKey", + clinic_HKEY_converter, &key)) + goto exit; + return_value = winreg_DisableReflectionKey_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_EnableReflectionKey__doc__, +"EnableReflectionKey($module, key, /)\n" +"--\n" +"\n" +"Restores registry reflection for the specified disabled key.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +"\n" +"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"Restoring reflection for a key does not affect reflection of any\n" +"subkeys."); + +#define WINREG_ENABLEREFLECTIONKEY_METHODDEF \ + {"EnableReflectionKey", (PyCFunction)winreg_EnableReflectionKey, METH_O, winreg_EnableReflectionKey__doc__}, + +static PyObject * +winreg_EnableReflectionKey_impl(PyModuleDef *module, HKEY key); + +static PyObject * +winreg_EnableReflectionKey(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HKEY key; + + if (!PyArg_Parse(arg, + "O&:EnableReflectionKey", + clinic_HKEY_converter, &key)) + goto exit; + return_value = winreg_EnableReflectionKey_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(winreg_QueryReflectionKey__doc__, +"QueryReflectionKey($module, key, /)\n" +"--\n" +"\n" +"Returns the reflection state for the specified key as a bool.\n" +"\n" +" key\n" +" An already open key, or any one of the predefined HKEY_* constants.\n" +"\n" +"Will generally raise NotImplemented if executed on a 32bit OS."); + +#define WINREG_QUERYREFLECTIONKEY_METHODDEF \ + {"QueryReflectionKey", (PyCFunction)winreg_QueryReflectionKey, METH_O, winreg_QueryReflectionKey__doc__}, + +static PyObject * +winreg_QueryReflectionKey_impl(PyModuleDef *module, HKEY key); + +static PyObject * +winreg_QueryReflectionKey(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HKEY key; + + if (!PyArg_Parse(arg, + "O&:QueryReflectionKey", + clinic_HKEY_converter, &key)) + goto exit; + return_value = winreg_QueryReflectionKey_impl(module, key); + +exit: + return return_value; +} +/*[clinic end generated code: output=be6e50b901570878 input=a9049054013a1b77]*/ diff --git a/PC/winreg.c b/PC/winreg.c --- a/PC/winreg.c +++ b/PC/winreg.c @@ -17,6 +17,7 @@ #include "windows.h" static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK); +static BOOL clinic_HKEY_converter(PyObject *ob, void *p); static PyObject *PyHKEY_FromHKEY(HKEY h); static BOOL PyHKEY_Close(PyObject *obHandle); @@ -46,10 +47,12 @@ "DeleteValue() - Removes a named value from the specified registry key.\n" "EnumKey() - Enumerates subkeys of the specified open registry key.\n" "EnumValue() - Enumerates values of the specified open registry key.\n" -"ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ string.\n" +"ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ\n" +" string.\n" "FlushKey() - Writes all the attributes of the specified key to the registry.\n" -"LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores\n" -" registration information from a specified file into that subkey.\n" +"LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and\n" +" stores registration information from a specified file into that\n" +" subkey.\n" "OpenKey() - Opens the specified key.\n" "OpenKeyEx() - Alias of OpenKey().\n" "QueryValue() - Retrieves the value associated with the unnamed value for a\n" @@ -71,299 +74,6 @@ "to see what constants are used, and where."); -PyDoc_STRVAR(CloseKey_doc, -"CloseKey(hkey)\n" -"Closes a previously opened registry key.\n" -"\n" -"The hkey argument specifies a previously opened key.\n" -"\n" -"Note that if the key is not closed using this method, it will be\n" -"closed when the hkey object is destroyed by Python."); - -PyDoc_STRVAR(ConnectRegistry_doc, -"ConnectRegistry(computer_name, key) -> key\n" -"Establishes a connection to a predefined registry handle on another computer.\n" -"\n" -"computer_name is the name of the remote computer, of the form \\\\computername.\n" -" If None, the local computer is used.\n" -"key is the predefined handle to connect to.\n" -"\n" -"The return value is the handle of the opened key.\n" -"If the function fails, an OSError exception is raised."); - -PyDoc_STRVAR(CreateKey_doc, -"CreateKey(key, sub_key) -> key\n" -"Creates or opens the specified key.\n" -"\n" -"key is an already open key, or one of the predefined HKEY_* constants.\n" -"sub_key is a string that names the key this method opens or creates.\n" -"\n" -"If key is one of the predefined keys, sub_key may be None. In that case,\n" -"the handle returned is the same key handle passed in to the function.\n" -"\n" -"If the key already exists, this function opens the existing key.\n" -"\n" -"The return value is the handle of the opened key.\n" -"If the function fails, an OSError exception is raised."); - -PyDoc_STRVAR(CreateKeyEx_doc, -"CreateKeyEx(key, sub_key, reserved=0, access=KEY_WRITE) -> key\n" -"Creates or opens the specified key.\n" -"\n" -"key is an already open key, or one of the predefined HKEY_* constants\n" -"sub_key is a string that names the key this method opens or creates.\n" -"reserved is a reserved integer, and must be zero. Default is zero.\n" -"access is an integer that specifies an access mask that describes the \n" -" desired security access for the key. Default is KEY_WRITE.\n" -"\n" -"If key is one of the predefined keys, sub_key may be None. In that case,\n" -"the handle returned is the same key handle passed in to the function.\n" -"\n" -"If the key already exists, this function opens the existing key\n" -"\n" -"The return value is the handle of the opened key.\n" -"If the function fails, an OSError exception is raised."); - -PyDoc_STRVAR(DeleteKey_doc, -"DeleteKey(key, sub_key)\n" -"Deletes the specified key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that must be a subkey of the key identified by the key\n" -" parameter. This value must not be None, and the key may not have\n" -" subkeys.\n" -"\n" -"This method can not delete keys with subkeys.\n" -"\n" -"If the function succeeds, the entire key, including all of its values,\n" -"is removed. If the function fails, an OSError exception is raised."); - -PyDoc_STRVAR(DeleteKeyEx_doc, -"DeleteKeyEx(key, sub_key, access=KEY_WOW64_64KEY, reserved=0)\n" -"Deletes the specified key (64-bit OS only).\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that must be a subkey of the key identified by the key\n" -" parameter. This value must not be None, and the key may not have\n" -" subkeys.\n" -"reserved is a reserved integer, and must be zero. Default is zero.\n" -"access is an integer that specifies an access mask that describes the \n" -" desired security access for the key. Default is KEY_WOW64_64KEY.\n" -"\n" -"This method can not delete keys with subkeys.\n" -"\n" -"If the function succeeds, the entire key, including all of its values,\n" -"is removed. If the function fails, an OSError exception is raised.\n" -"On unsupported Windows versions, NotImplementedError is raised."); - -PyDoc_STRVAR(DeleteValue_doc, -"DeleteValue(key, value)\n" -"Removes a named value from a registry key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"value is a string that identifies the value to remove."); - -PyDoc_STRVAR(EnumKey_doc, -"EnumKey(key, index) -> string\n" -"Enumerates subkeys of an open registry key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"index is an integer that identifies the index of the key to retrieve.\n" -"\n" -"The function retrieves the name of one subkey each time it is called.\n" -"It is typically called repeatedly until an OSError exception is\n" -"raised, indicating no more values are available."); - -PyDoc_STRVAR(EnumValue_doc, -"EnumValue(key, index) -> tuple\n" -"Enumerates values of an open registry key.\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"index is an integer that identifies the index of the value to retrieve.\n" -"\n" -"The function retrieves the name of one subkey each time it is called.\n" -"It is typically called repeatedly, until an OSError exception\n" -"is raised, indicating no more values.\n" -"\n" -"The result is a tuple of 3 items:\n" -"value_name is a string that identifies the value.\n" -"value_data is an object that holds the value data, and whose type depends\n" -" on the underlying registry type.\n" -"data_type is an integer that identifies the type of the value data."); - -PyDoc_STRVAR(ExpandEnvironmentStrings_doc, -"ExpandEnvironmentStrings(string) -> string\n" -"Expand environment vars.\n"); - -PyDoc_STRVAR(FlushKey_doc, -"FlushKey(key)\n" -"Writes all the attributes of a key to the registry.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"\n" -"It is not necessary to call FlushKey to change a key. Registry changes are\n" -"flushed to disk by the registry using its lazy flusher. Registry changes are\n" -"also flushed to disk at system shutdown. Unlike CloseKey(), the FlushKey()\n" -"method returns only when all the data has been written to the registry.\n" -"\n" -"An application should only call FlushKey() if it requires absolute certainty\n" -"that registry changes are on disk. If you don't know whether a FlushKey()\n" -"call is required, it probably isn't."); - -PyDoc_STRVAR(LoadKey_doc, -"LoadKey(key, sub_key, file_name)\n" -"Creates a subkey under the specified key and stores registration information\n" -"from a specified file into that subkey.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that identifies the sub_key to load.\n" -"file_name is the name of the file to load registry data from. This file must\n" -" have been created with the SaveKey() function. Under the file\n" -" allocation table (FAT) file system, the filename may not have an\n" -" extension.\n" -"\n" -"A call to LoadKey() fails if the calling process does not have the\n" -"SE_RESTORE_PRIVILEGE privilege.\n" -"\n" -"If key is a handle returned by ConnectRegistry(), then the path specified\n" -"in fileName is relative to the remote computer.\n" -"\n" -"The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree"); - -PyDoc_STRVAR(OpenKey_doc, -"OpenKey(key, sub_key, reserved=0, access=KEY_READ) -> key\n" -"Opens the specified key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that identifies the sub_key to open.\n" -"reserved is a reserved integer, and must be zero. Default is zero.\n" -"access is an integer that specifies an access mask that describes the desired\n" -" security access for the key. Default is KEY_READ\n" -"\n" -"The result is a new handle to the specified key\n" -"If the function fails, an OSError exception is raised."); - -PyDoc_STRVAR(OpenKeyEx_doc, "See OpenKey()"); - -PyDoc_STRVAR(QueryInfoKey_doc, -"QueryInfoKey(key) -> tuple\n" -"Returns information about a key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"\n" -"The result is a tuple of 3 items:" -"An integer that identifies the number of sub keys this key has.\n" -"An integer that identifies the number of values this key has.\n" -"An integer that identifies when the key was last modified (if available)\n" -" as 100's of nanoseconds since Jan 1, 1600."); - -PyDoc_STRVAR(QueryValue_doc, -"QueryValue(key, sub_key) -> string\n" -"Retrieves the unnamed value for a key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that holds the name of the subkey with which the value\n" -" is associated. If this parameter is None or empty, the function\n" -" retrieves the value set by the SetValue() method for the key\n" -" identified by key." -"\n" -"Values in the registry have name, type, and data components. This method\n" -"retrieves the data for a key's first value that has a NULL name.\n" -"But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE THIS!!!"); - -PyDoc_STRVAR(QueryValueEx_doc, -"QueryValueEx(key, value_name) -> (value, type_id)\n" -"Retrieves the type and data for a specified value name associated with an\n" -"open registry key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"value_name is a string indicating the value to query"); - -PyDoc_STRVAR(SaveKey_doc, -"SaveKey(key, file_name)\n" -"Saves the specified key, and all its subkeys to the specified file.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"file_name is the name of the file to save registry data to. This file cannot\n" -" already exist. If this filename includes an extension, it cannot be\n" -" used on file allocation table (FAT) file systems by the LoadKey(),\n" -" ReplaceKey() or RestoreKey() methods.\n" -"\n" -"If key represents a key on a remote computer, the path described by file_name\n" -"is relative to the remote computer.\n" -"\n" -"The caller of this method must possess the SeBackupPrivilege security\n" -"privilege. This function passes NULL for security_attributes to the API."); - -PyDoc_STRVAR(SetValue_doc, -"SetValue(key, sub_key, type, value)\n" -"Associates a value with a specified key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"sub_key is a string that names the subkey with which the value is associated.\n" -"type is an integer that specifies the type of the data. Currently this must\n" -" be REG_SZ, meaning only strings are supported.\n" -"value is a string that specifies the new value.\n" -"\n" -"If the key specified by the sub_key parameter does not exist, the SetValue\n" -"function creates it.\n" -"\n" -"Value lengths are limited by available memory. Long values (more than\n" -"2048 bytes) should be stored as files with the filenames stored in \n" -"the configuration registry. This helps the registry perform efficiently.\n" -"\n" -"The key identified by the key parameter must have been opened with\n" -"KEY_SET_VALUE access."); - -PyDoc_STRVAR(SetValueEx_doc, -"SetValueEx(key, value_name, reserved, type, value)\n" -"Stores data in the value field of an open registry key.\n" -"\n" -"key is an already open key, or any one of the predefined HKEY_* constants.\n" -"value_name is a string containing the name of the value to set, or None.\n" -"reserved can be anything - zero is always passed to the API.\n" -"type is an integer that specifies the type of the data. This should be one of:\n" -" REG_BINARY -- Binary data in any form.\n" -" REG_DWORD -- A 32-bit number.\n" -" REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format.\n" -" REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format.\n" -" REG_EXPAND_SZ -- A null-terminated string that contains unexpanded references\n" -" to environment variables (for example, %PATH%).\n" -" REG_LINK -- A Unicode symbolic link.\n" -" REG_MULTI_SZ -- An sequence of null-terminated strings, terminated by\n" -" two null characters. Note that Python handles this\n" -" termination automatically.\n" -" REG_NONE -- No defined value type.\n" -" REG_RESOURCE_LIST -- A device-driver resource list.\n" -" REG_SZ -- A null-terminated string.\n" -"value is a string that specifies the new value.\n" -"\n" -"This method can also set additional value and type information for the\n" -"specified key. The key identified by the key parameter must have been\n" -"opened with KEY_SET_VALUE access.\n" -"\n" -"To open the key, use the CreateKeyEx() or OpenKeyEx() methods.\n" -"\n" -"Value lengths are limited by available memory. Long values (more than\n" -"2048 bytes) should be stored as files with the filenames stored in \n" -"the configuration registry. This helps the registry perform efficiently."); - -PyDoc_STRVAR(DisableReflectionKey_doc, -"Disables registry reflection for 32-bit processes running on a 64-bit\n" -"Operating System. Will generally raise NotImplemented if executed on\n" -"a 32-bit Operating System.\n" -"\n" -"If the key is not on the reflection list, the function succeeds but has no effect.\n" -"Disabling reflection for a key does not affect reflection of any subkeys."); - -PyDoc_STRVAR(EnableReflectionKey_doc, -"Restores registry reflection for the specified disabled key.\n" -"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n" -"Restoring reflection for a key does not affect reflection of any subkeys."); - -PyDoc_STRVAR(QueryReflectionKey_doc, -"QueryReflectionKey(hkey) -> bool\n" -"Determines the reflection state for the specified key.\n" -"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n"); /* PyHKEY docstrings */ PyDoc_STRVAR(PyHKEY_doc, @@ -389,24 +99,6 @@ "rich comparison - Handle objects are compared using the handle value."); -PyDoc_STRVAR(PyHKEY_Close_doc, -"key.Close()\n" -"Closes the underlying Windows handle.\n" -"\n" -"If the handle is already closed, no error is raised."); - -PyDoc_STRVAR(PyHKEY_Detach_doc, -"key.Detach() -> int\n" -"Detaches the Windows handle from the handle object.\n" -"\n" -"The result is the value of the handle before it is detached. If the\n" -"handle is already detached, this will return zero.\n" -"\n" -"After calling this function, the handle is effectively invalidated,\n" -"but the handle is not closed. You would call this function when you\n" -"need the underlying win32 handle to exist beyond the lifetime of the\n" -"handle object."); - /************************************************************************ @@ -516,16 +208,134 @@ PyHKEY_unaryFailureFunc, /* nb_float */ }; -static PyObject *PyHKEY_CloseMethod(PyObject *self, PyObject *args); -static PyObject *PyHKEY_DetachMethod(PyObject *self, PyObject *args); -static PyObject *PyHKEY_Enter(PyObject *self); -static PyObject *PyHKEY_Exit(PyObject *self, PyObject *args); +/*[clinic input] +module winreg +class winreg.HKEYType "PyHKEYObject *" "&PyHKEY_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4c964eba3bf914d6]*/ + +/*[python input] +class REGSAM_converter(CConverter): + type = 'REGSAM' + format_unit = 'i' + +class DWORD_converter(CConverter): + type = 'DWORD' + format_unit = 'k' + +class HKEY_converter(CConverter): + type = 'HKEY' + converter = 'clinic_HKEY_converter' + +class HKEY_return_converter(CReturnConverter): + type = 'HKEY' + + def render(self, function, data): + self.declare(data) + self.err_occurred_if_null_pointer("_return_value", data) + data.return_conversion.append( + 'return_value = PyHKEY_FromHKEY(_return_value);\n') + +# HACK: this only works for PyHKEYObjects, nothing else. +# Should this be generalized and enshrined in clinic.py, +# destroy this converter with prejudice. +class self_return_converter(CReturnConverter): + type = 'PyHKEYObject *' + + def render(self, function, data): + self.declare(data) + data.return_conversion.append( + 'return_value = (PyObject *)_return_value;\n') +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=22f7aedc6d68e80e]*/ + +#include "clinic/winreg.c.h" + +/************************************************************************ + + The PyHKEY object methods + +************************************************************************/ +/*[clinic input] +winreg.HKEYType.Close + +Closes the underlying Windows handle. + +If the handle is already closed, no error is raised. +[clinic start generated code]*/ + +static PyObject * +winreg_HKEYType_Close_impl(PyHKEYObject *self) +/*[clinic end generated code: output=fced3a624fb0c344 input=6786ac75f6b89de6]*/ +{ + if (!PyHKEY_Close((PyObject *)self)) + return NULL; + Py_RETURN_NONE; +} + +/*[clinic input] +winreg.HKEYType.Detach + +Detaches the Windows handle from the handle object. + +The result is the value of the handle before it is detached. If the +handle is already detached, this will return zero. + +After calling this function, the handle is effectively invalidated, +but the handle is not closed. You would call this function when you +need the underlying win32 handle to exist beyond the lifetime of the +handle object. +[clinic start generated code]*/ + +static PyObject * +winreg_HKEYType_Detach_impl(PyHKEYObject *self) +/*[clinic end generated code: output=dda5a9e1a01ae78f input=dd2cc09e6c6ba833]*/ +{ + void* ret; + ret = (void*)self->hkey; + self->hkey = 0; + return PyLong_FromVoidPtr(ret); +} + +/*[clinic input] +winreg.HKEYType.__enter__ -> self +[clinic start generated code]*/ + +static PyHKEYObject * +winreg_HKEYType___enter___impl(PyHKEYObject *self) +/*[clinic end generated code: output=52c34986dab28990 input=c40fab1f0690a8e2]*/ +{ + Py_XINCREF(self); + return self; +} + + +/*[clinic input] +winreg.HKEYType.__exit__ + + exc_type: object + exc_value: object + traceback: object +[clinic start generated code]*/ + +static PyObject * +winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback) +/*[clinic end generated code: output=51adcc1522e9c847 input=fb32489ee92403c7]*/ +{ + if (!PyHKEY_Close((PyObject *)self)) + return NULL; + Py_RETURN_NONE; +} + +/*[clinic input] +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/ static struct PyMethodDef PyHKEY_methods[] = { - {"Close", PyHKEY_CloseMethod, METH_VARARGS, PyHKEY_Close_doc}, - {"Detach", PyHKEY_DetachMethod, METH_VARARGS, PyHKEY_Detach_doc}, - {"__enter__", (PyCFunction)PyHKEY_Enter, METH_NOARGS, NULL}, - {"__exit__", PyHKEY_Exit, METH_VARARGS, NULL}, + WINREG_HKEYTYPE_CLOSE_METHODDEF + WINREG_HKEYTYPE_DETACH_METHODDEF + WINREG_HKEYTYPE___ENTER___METHODDEF + WINREG_HKEYTYPE___EXIT___METHODDEF {NULL} }; @@ -570,50 +380,6 @@ }; /************************************************************************ - - The PyHKEY object methods - -************************************************************************/ -static PyObject * -PyHKEY_CloseMethod(PyObject *self, PyObject *args) -{ - if (!PyArg_ParseTuple(args, ":Close")) - return NULL; - if (!PyHKEY_Close(self)) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -PyHKEY_DetachMethod(PyObject *self, PyObject *args) -{ - void* ret; - PyHKEYObject *pThis = (PyHKEYObject *)self; - if (!PyArg_ParseTuple(args, ":Detach")) - return NULL; - ret = (void*)pThis->hkey; - pThis->hkey = 0; - return PyLong_FromVoidPtr(ret); -} - -static PyObject * -PyHKEY_Enter(PyObject *self) -{ - Py_XINCREF(self); - return self; -} - -static PyObject * -PyHKEY_Exit(PyObject *self, PyObject *args) -{ - if (!PyHKEY_Close(self)) - return NULL; - Py_RETURN_NONE; -} - - -/************************************************************************ The public PyHKEY API (well, not public yet :-) ************************************************************************/ PyObject * @@ -675,6 +441,14 @@ return TRUE; } +BOOL +clinic_HKEY_converter(PyObject *ob, void *p) +{ + if (!PyHKEY_AsHKEY(ob, (HKEY *)p, FALSE)) + return FALSE; + return TRUE; +} + PyObject * PyHKEY_FromHKEY(HKEY h) { @@ -985,120 +759,196 @@ /* The Python methods */ +/*[clinic input] +winreg.CloseKey + + hkey: object + A previously opened key. + / + +Closes a previously opened registry key. + +Note that if the key is not closed using this method, it will be +closed when the hkey object is destroyed by Python. +[clinic start generated code]*/ + static PyObject * -PyCloseKey(PyObject *self, PyObject *args) +winreg_CloseKey(PyModuleDef *module, PyObject *hkey) +/*[clinic end generated code: output=d96f73439403a064 input=5b1aac65ba5127ad]*/ { - PyObject *obKey; - if (!PyArg_ParseTuple(args, "O:CloseKey", &obKey)) + if (!PyHKEY_Close(hkey)) return NULL; - if (!PyHKEY_Close(obKey)) - return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -static PyObject * -PyConnectRegistry(PyObject *self, PyObject *args) +/*[clinic input] +winreg.ConnectRegistry -> HKEY + + computer_name: Py_UNICODE(nullable=True) + The name of the remote computer, of the form r"\\computername". If + None, the local computer is used. + key: HKEY + The predefined key to connect to. + / + +Establishes a connection to the registry on on another computer. + +The return value is the handle of the opened key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, HKEY key) +/*[clinic end generated code: output=bce735a41d767290 input=dcea2c433af51576]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *szCompName = NULL; HKEY retKey; long rc; - if (!PyArg_ParseTuple(args, "ZO:ConnectRegistry", &szCompName, &obKey)) + Py_BEGIN_ALLOW_THREADS + rc = RegConnectRegistryW(computer_name, key, &retKey); + Py_END_ALLOW_THREADS + if (rc != ERROR_SUCCESS) { + PyErr_SetFromWindowsErrWithFunction(rc, "ConnectRegistry"); return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rc = RegConnectRegistryW(szCompName, hKey, &retKey); - Py_END_ALLOW_THREADS - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, - "ConnectRegistry"); - return PyHKEY_FromHKEY(retKey); + } + return retKey; } -static PyObject * -PyCreateKey(PyObject *self, PyObject *args) +/*[clinic input] +winreg.CreateKey -> HKEY + + key: HKEY + An already open key, or one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(nullable=True) + The name of the key this method opens or creates. + / + +Creates or opens the specified key. + +If key is one of the predefined keys, sub_key may be None. In that case, +the handle returned is the same key handle passed in to the function. + +If the key already exists, this function opens the existing key. + +The return value is the handle of the opened key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_CreateKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key) +/*[clinic end generated code: output=cd6843f30a73fc0e input=8014b171a5682fe7]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; HKEY retKey; long rc; - if (!PyArg_ParseTuple(args, "OZ:CreateKey", &obKey, &subKey)) + + rc = RegCreateKeyW(key, sub_key, &retKey); + if (rc != ERROR_SUCCESS) { + PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey"); return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - rc = RegCreateKeyW(hKey, subKey, &retKey); - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey"); - return PyHKEY_FromHKEY(retKey); + } + return retKey; } -static PyObject * -PyCreateKeyEx(PyObject *self, PyObject *args, PyObject *kwargs) +/*[clinic input] +winreg.CreateKeyEx -> HKEY + + key: HKEY + An already open key, or one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(nullable=True) + The name of the key this method opens or creates. + reserved: int = 0 + A reserved integer, and must be zero. Default is zero. + access: REGSAM(c_default='KEY_WRITE') = winreg.KEY_WRITE + An integer that specifies an access mask that describes the + desired security access for the key. Default is KEY_WRITE. + +Creates or opens the specified key. + +If key is one of the predefined keys, sub_key may be None. In that case, +the handle returned is the same key handle passed in to the function. + +If the key already exists, this function opens the existing key + +The return value is the handle of the opened key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) +/*[clinic end generated code: output=543d176b19183749 input=4322acd5c7f2e787]*/ { - HKEY hKey; - PyObject *key; - wchar_t *sub_key; HKEY retKey; - int reserved = 0; - REGSAM access = KEY_WRITE; long rc; - char *kwlist[] = {"key", "sub_key", "reserved", "access", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OZ|ii:CreateKeyEx", kwlist, - &key, &sub_key, &reserved, &access)) + rc = RegCreateKeyExW(key, sub_key, reserved, NULL, (DWORD)NULL, + access, NULL, &retKey, NULL); + if (rc != ERROR_SUCCESS) { + PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx"); return NULL; - if (!PyHKEY_AsHKEY(key, &hKey, FALSE)) - return NULL; - - rc = RegCreateKeyExW(hKey, sub_key, reserved, NULL, (DWORD)NULL, - access, NULL, &retKey, NULL); - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx"); - return PyHKEY_FromHKEY(retKey); + } + return retKey; } +/*[clinic input] +winreg.DeleteKey + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE + A string that must be the name of a subkey of the key identified by + the key parameter. This value must not be None, and the key may not + have subkeys. + / + +Deletes the specified key. + +This method can not delete keys with subkeys. + +If the function succeeds, the entire key, including all of its values, +is removed. If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + static PyObject * -PyDeleteKey(PyObject *self, PyObject *args) +winreg_DeleteKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key) +/*[clinic end generated code: output=875c8917dacbc99d input=b31d225b935e4211]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; long rc; - if (!PyArg_ParseTuple(args, "Ou:DeleteKey", &obKey, &subKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - rc = RegDeleteKeyW(hKey, subKey ); + rc = RegDeleteKeyW(key, sub_key ); if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.DeleteKeyEx + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE + A string that must be the name of a subkey of the key identified by + the key parameter. This value must not be None, and the key may not + have subkeys. + access: REGSAM(c_default='KEY_WOW64_64KEY') = winreg.KEY_WOW64_64KEY + An integer that specifies an access mask that describes the + desired security access for the key. Default is KEY_WOW64_64KEY. + reserved: int = 0 + A reserved integer, and must be zero. Default is zero. + +Deletes the specified key (64-bit OS only). + +This method can not delete keys with subkeys. + +If the function succeeds, the entire key, including all of its values, +is removed. If the function fails, an OSError exception is raised. +On unsupported Windows versions, NotImplementedError is raised. +[clinic start generated code]*/ + static PyObject * -PyDeleteKeyEx(PyObject *self, PyObject *args, PyObject *kwargs) +winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, REGSAM access, int reserved) +/*[clinic end generated code: output=8b8a20684a59a902 input=711d9d89e7ecbed7]*/ { - HKEY hKey; - PyObject *key; HMODULE hMod; typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int); RDKEFunc pfn = NULL; - wchar_t *sub_key; long rc; - int reserved = 0; - REGSAM access = KEY_WOW64_64KEY; - - char *kwlist[] = {"key", "sub_key", "access", "reserved", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ou|ii:DeleteKeyEx", kwlist, - &key, &sub_key, &access, &reserved)) - return NULL; - if (!PyHKEY_AsHKEY(key, &hKey, FALSE)) - return NULL; /* Only available on 64bit platforms, so we must load it dynamically. */ @@ -1112,42 +962,60 @@ return NULL; } Py_BEGIN_ALLOW_THREADS - rc = (*pfn)(hKey, sub_key, access, reserved); + rc = (*pfn)(key, sub_key, access, reserved); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKeyEx"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.DeleteValue + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + value: Py_UNICODE(nullable=True) + A string that identifies the value to remove. + / + +Removes a named value from a registry key. +[clinic start generated code]*/ + static PyObject * -PyDeleteValue(PyObject *self, PyObject *args) +winreg_DeleteValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value) +/*[clinic end generated code: output=308550b8cdcfd8e1 input=417a5c1005cbbddc]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; long rc; - if (!PyArg_ParseTuple(args, "OZ:DeleteValue", &obKey, &subKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; Py_BEGIN_ALLOW_THREADS - rc = RegDeleteValueW(hKey, subKey); + rc = RegDeleteValueW(key, value); Py_END_ALLOW_THREADS if (rc !=ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteValue"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.EnumKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + index: int + An integer that identifies the index of the key to retrieve. + / + +Enumerates subkeys of an open registry key. + +The function retrieves the name of one subkey each time it is called. +It is typically called repeatedly until an OSError exception is +raised, indicating no more values are available. +[clinic start generated code]*/ + static PyObject * -PyEnumKey(PyObject *self, PyObject *args) +winreg_EnumKey_impl(PyModuleDef *module, HKEY key, int index) +/*[clinic end generated code: output=58074ffabbc67896 input=fad9a7c00ab0e04b]*/ { - HKEY hKey; - PyObject *obKey; - int index; long rc; PyObject *retStr; @@ -1160,13 +1028,8 @@ wchar_t tmpbuf[257]; DWORD len = sizeof(tmpbuf)/sizeof(wchar_t); /* includes NULL terminator */ - if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rc = RegEnumKeyExW(hKey, index, tmpbuf, &len, NULL, NULL, NULL, NULL); + rc = RegEnumKeyExW(key, index, tmpbuf, &len, NULL, NULL, NULL, NULL); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKeyEx"); @@ -1175,12 +1038,35 @@ return retStr; /* can be NULL */ } +/*[clinic input] +winreg.EnumValue + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + index: int + An integer that identifies the index of the value to retrieve. + / + +Enumerates values of an open registry key. + +The function retrieves the name of one subkey each time it is called. +It is typically called repeatedly, until an OSError exception +is raised, indicating no more values. + +The result is a tuple of 3 items: + value_name + A string that identifies the value. + value_data + An object that holds the value data, and whose type depends + on the underlying registry type. + data_type + An integer that identifies the type of the value data. +[clinic start generated code]*/ + static PyObject * -PyEnumValue(PyObject *self, PyObject *args) +winreg_EnumValue_impl(PyModuleDef *module, HKEY key, int index) +/*[clinic end generated code: output=4570367ebaf0e979 input=4414f47a6fb238b5]*/ { - HKEY hKey; - PyObject *obKey; - int index; long rc; wchar_t *retValueBuf; BYTE *tmpBuf; @@ -1191,12 +1077,7 @@ PyObject *obData; PyObject *retVal; - if (!PyArg_ParseTuple(args, "Oi:EnumValue", &obKey, &index)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - - if ((rc = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, + if ((rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &retValueSize, &retDataSize, NULL, NULL)) != ERROR_SUCCESS) @@ -1217,7 +1098,7 @@ while (1) { Py_BEGIN_ALLOW_THREADS - rc = RegEnumValueW(hKey, + rc = RegEnumValueW(key, index, retValueBuf, &retValueSize, @@ -1260,19 +1141,25 @@ return retVal; } +/*[clinic input] +winreg.ExpandEnvironmentStrings + + string: Py_UNICODE + / + +Expand environment vars. +[clinic start generated code]*/ + static PyObject * -PyExpandEnvironmentStrings(PyObject *self, PyObject *args) +winreg_ExpandEnvironmentStrings_impl(PyModuleDef *module, Py_UNICODE *string) +/*[clinic end generated code: output=4cb6914065a8663c input=b2a9714d2b751aa6]*/ { wchar_t *retValue = NULL; - wchar_t *src; DWORD retValueSize; DWORD rc; PyObject *o; - if (!PyArg_ParseTuple(args, "u:ExpandEnvironmentStrings", &src)) - return NULL; - - retValueSize = ExpandEnvironmentStringsW(src, retValue, 0); + retValueSize = ExpandEnvironmentStringsW(string, retValue, 0); if (retValueSize == 0) { return PyErr_SetFromWindowsErrWithFunction(retValueSize, "ExpandEnvironmentStrings"); @@ -1282,7 +1169,7 @@ return PyErr_NoMemory(); } - rc = ExpandEnvironmentStringsW(src, retValue, retValueSize); + rc = ExpandEnvironmentStringsW(string, retValue, retValueSize); if (rc == 0) { PyMem_Free(retValue); return PyErr_SetFromWindowsErrWithFunction(retValueSize, @@ -1293,90 +1180,163 @@ return o; } +/*[clinic input] +winreg.FlushKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + / + +Writes all the attributes of a key to the registry. + +It is not necessary to call FlushKey to change a key. Registry changes +are flushed to disk by the registry using its lazy flusher. Registry +changes are also flushed to disk at system shutdown. Unlike +CloseKey(), the FlushKey() method returns only when all the data has +been written to the registry. + +An application should only call FlushKey() if it requires absolute +certainty that registry changes are on disk. If you don't know whether +a FlushKey() call is required, it probably isn't. +[clinic start generated code]*/ + static PyObject * -PyFlushKey(PyObject *self, PyObject *args) +winreg_FlushKey_impl(PyModuleDef *module, HKEY key) +/*[clinic end generated code: output=b9a7a6e405466420 input=f57457c12297d82f]*/ { - HKEY hKey; - PyObject *obKey; long rc; - if (!PyArg_ParseTuple(args, "O:FlushKey", &obKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; Py_BEGIN_ALLOW_THREADS - rc = RegFlushKey(hKey); + rc = RegFlushKey(key); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegFlushKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } + + +/*[clinic input] +winreg.LoadKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE + A string that identifies the sub-key to load. + file_name: Py_UNICODE + The name of the file to load registry data from. This file must + have been created with the SaveKey() function. Under the file + allocation table (FAT) file system, the filename may not have an + extension. + / + +Insert data into the registry from a file. + +Creates a subkey under the specified key and stores registration +information from a specified file into that subkey. + +A call to LoadKey() fails if the calling process does not have the +SE_RESTORE_PRIVILEGE privilege. + +If key is a handle returned by ConnectRegistry(), then the path +specified in fileName is relative to the remote computer. + +The MSDN docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE +tree. +[clinic start generated code]*/ + static PyObject * -PyLoadKey(PyObject *self, PyObject *args) +winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, Py_UNICODE *file_name) +/*[clinic end generated code: output=53b22607f8e73d34 input=e3b5b45ade311582]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; - wchar_t *fileName; + long rc; - long rc; - if (!PyArg_ParseTuple(args, "Ouu:LoadKey", &obKey, &subKey, &fileName)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; Py_BEGIN_ALLOW_THREADS - rc = RegLoadKeyW(hKey, subKey, fileName ); + rc = RegLoadKeyW(key, sub_key, file_name ); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegLoadKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -static PyObject * -PyOpenKey(PyObject *self, PyObject *args, PyObject *kwargs) +/*[clinic input] +winreg.OpenKey -> HKEY + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(nullable=True) + A string that identifies the sub_key to open. + reserved: int = 0 + A reserved integer that must be zero. Default is zero. + access: REGSAM(c_default='KEY_READ') = winreg.KEY_READ + An integer that specifies an access mask that describes the desired + security access for the key. Default is KEY_READ. + +Opens the specified key. + +The result is a new handle to the specified key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) +/*[clinic end generated code: output=8bf50881521469c6 input=dc84a4af4af4d387]*/ { - HKEY hKey; - PyObject *key; - wchar_t *sub_key; - int reserved = 0; HKEY retKey; long rc; - REGSAM access = KEY_READ; - - char *kwlist[] = {"key", "sub_key", "reserved", "access", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OZ|ii:OpenKey", kwlist, - &key, &sub_key, &reserved, &access)) - return NULL; - if (!PyHKEY_AsHKEY(key, &hKey, FALSE)) - return NULL; Py_BEGIN_ALLOW_THREADS - rc = RegOpenKeyExW(hKey, sub_key, reserved, access, &retKey); + rc = RegOpenKeyExW(key, sub_key, reserved, access, &retKey); Py_END_ALLOW_THREADS - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx"); - return PyHKEY_FromHKEY(retKey); + if (rc != ERROR_SUCCESS) { + PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx"); + return NULL; + } + return retKey; } +/*[clinic input] +winreg.OpenKeyEx = winreg.OpenKey + +Opens the specified key. + +The result is a new handle to the specified key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) +/*[clinic end generated code: output=f6f7cd4befb9585b input=c6c4972af8622959]*/ +{ + return winreg_OpenKey_impl(module, key, sub_key, reserved, access); +} + +/*[clinic input] +winreg.QueryInfoKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + / + +Returns information about a key. + +The result is a tuple of 3 items: +An integer that identifies the number of sub keys this key has. +An integer that identifies the number of values this key has. +An integer that identifies when the key was last modified (if available) +as 100's of nanoseconds since Jan 1, 1600. +[clinic start generated code]*/ static PyObject * -PyQueryInfoKey(PyObject *self, PyObject *args) +winreg_QueryInfoKey_impl(PyModuleDef *module, HKEY key) +/*[clinic end generated code: output=ae885222fe966a34 input=c3593802390cde1f]*/ { - HKEY hKey; - PyObject *obKey; long rc; DWORD nSubKeys, nValues; FILETIME ft; LARGE_INTEGER li; PyObject *l; PyObject *ret; - if (!PyArg_ParseTuple(args, "O:QueryInfoKey", &obKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - if ((rc = RegQueryInfoKey(hKey, NULL, NULL, 0, &nSubKeys, NULL, NULL, + + if ((rc = RegQueryInfoKey(key, NULL, NULL, 0, &nSubKeys, NULL, NULL, &nValues, NULL, NULL, NULL, &ft)) != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryInfoKey"); @@ -1390,12 +1350,31 @@ return ret; } +/*[clinic input] +winreg.QueryValue + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(nullable=True) + A string that holds the name of the subkey with which the value + is associated. If this parameter is None or empty, the function + retrieves the value set by the SetValue() method for the key + identified by key. + / + +Retrieves the unnamed value for a key. + +Values in the registry have name, type, and data components. This method +retrieves the data for a key's first value that has a NULL name. +But since the underlying API call doesn't return the type, you'll +probably be happier using QueryValueEx; this function is just here for +completeness. +[clinic start generated code]*/ + static PyObject * -PyQueryValue(PyObject *self, PyObject *args) +winreg_QueryValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key) +/*[clinic end generated code: output=f91cb6f623c3b65a input=e6ec57bb8d39aaa6]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; long rc; PyObject *retStr; wchar_t *retBuf; @@ -1403,13 +1382,7 @@ DWORD retSize = 0; wchar_t *tmp; - if (!PyArg_ParseTuple(args, "OZ:QueryValue", &obKey, &subKey)) - return NULL; - - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - - rc = RegQueryValueW(hKey, subKey, NULL, &retSize); + rc = RegQueryValueW(key, sub_key, NULL, &retSize); if (rc == ERROR_MORE_DATA) retSize = 256; else if (rc != ERROR_SUCCESS) @@ -1423,7 +1396,7 @@ while (1) { retSize = bufSize; - rc = RegQueryValueW(hKey, subKey, retBuf, &retSize); + rc = RegQueryValueW(key, sub_key, retBuf, &retSize); if (rc != ERROR_MORE_DATA) break; @@ -1447,13 +1420,28 @@ return retStr; } + +/*[clinic input] +winreg.QueryValueEx + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + name: Py_UNICODE(nullable=True) + A string indicating the value to query. + / + +Retrieves the type and value of a specified sub-key. + +Behaves mostly like QueryValue(), but also returns the type of the +specified value name associated with the given open registry key. + +The return value is a tuple of the value and the type_id. +[clinic start generated code]*/ + static PyObject * -PyQueryValueEx(PyObject *self, PyObject *args) +winreg_QueryValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *name) +/*[clinic end generated code: output=a4b07f7807194f23 input=4403ae868b44e563]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *valueName; - long rc; BYTE *retBuf, *tmp; DWORD bufSize = 0, retSize; @@ -1461,13 +1449,7 @@ PyObject *obData; PyObject *result; - if (!PyArg_ParseTuple(args, "OZ:QueryValueEx", &obKey, &valueName)) - return NULL; - - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - - rc = RegQueryValueExW(hKey, valueName, NULL, NULL, NULL, &bufSize); + rc = RegQueryValueExW(key, name, NULL, NULL, NULL, &bufSize); if (rc == ERROR_MORE_DATA) bufSize = 256; else if (rc != ERROR_SUCCESS) @@ -1479,7 +1461,7 @@ while (1) { retSize = bufSize; - rc = RegQueryValueExW(hKey, valueName, NULL, &typ, + rc = RegQueryValueExW(key, name, NULL, &typ, (BYTE *)retBuf, &retSize); if (rc != ERROR_MORE_DATA) break; @@ -1507,91 +1489,146 @@ return result; } +/*[clinic input] +winreg.SaveKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + file_name: Py_UNICODE + The name of the file to save registry data to. This file cannot + already exist. If this filename includes an extension, it cannot be + used on file allocation table (FAT) file systems by the LoadKey(), + ReplaceKey() or RestoreKey() methods. + / + +Saves the specified key, and all its subkeys to the specified file. + +If key represents a key on a remote computer, the path described by +file_name is relative to the remote computer. + +The caller of this method must possess the SeBackupPrivilege +security privilege. This function passes NULL for security_attributes +to the API. +[clinic start generated code]*/ static PyObject * -PySaveKey(PyObject *self, PyObject *args) +winreg_SaveKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *file_name) +/*[clinic end generated code: output=33109b96bfabef8f input=da735241f91ac7a2]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *fileName; LPSECURITY_ATTRIBUTES pSA = NULL; long rc; - if (!PyArg_ParseTuple(args, "Ou:SaveKey", &obKey, &fileName)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; /* One day we may get security into the core? if (!PyWinObject_AsSECURITY_ATTRIBUTES(obSA, &pSA, TRUE)) return NULL; */ Py_BEGIN_ALLOW_THREADS - rc = RegSaveKeyW(hKey, fileName, pSA ); + rc = RegSaveKeyW(key, file_name, pSA ); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegSaveKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.SetValue + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(nullable=True) + A string that names the subkey with which the value is associated. + type: DWORD + An integer that specifies the type of the data. Currently this must + be REG_SZ, meaning only strings are supported. + value: Py_UNICODE(length=True) + A string that specifies the new value. + / + +Associates a value with a specified key. + +If the key specified by the sub_key parameter does not exist, the +SetValue function creates it. + +Value lengths are limited by available memory. Long values (more than +2048 bytes) should be stored as files with the filenames stored in +the configuration registry to help the registry perform efficiently. + +The key identified by the key parameter must have been opened with +KEY_SET_VALUE access. +[clinic start generated code]*/ + static PyObject * -PySetValue(PyObject *self, PyObject *args) +winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, DWORD type, Py_UNICODE *value, Py_ssize_clean_t value_length) +/*[clinic end generated code: output=807274a1c01961b5 input=83ad2fae2ffbb941]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *subKey; - wchar_t *str; - DWORD typ; - DWORD len; long rc; - if (!PyArg_ParseTuple(args, "OZiu#:SetValue", - &obKey, - &subKey, - &typ, - &str, - &len)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - if (typ != REG_SZ) { + + if (type != REG_SZ) { PyErr_SetString(PyExc_TypeError, "Type must be winreg.REG_SZ"); return NULL; } Py_BEGIN_ALLOW_THREADS - rc = RegSetValueW(hKey, subKey, REG_SZ, str, len+1); + rc = RegSetValueW(key, sub_key, REG_SZ, value, value_length+1); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.SetValueEx + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + value_name: Py_UNICODE(nullable=True) + A string containing the name of the value to set, or None. + reserved: object + Can be anything - zero is always passed to the API. + type: DWORD + An integer that specifies the type of the data, one of: + REG_BINARY -- Binary data in any form. + REG_DWORD -- A 32-bit number. + REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format. + REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format. + REG_EXPAND_SZ -- A null-terminated string that contains unexpanded + references to environment variables (for example, + %PATH%). + REG_LINK -- A Unicode symbolic link. + REG_MULTI_SZ -- An sequence of null-terminated strings, terminated + by two null characters. Note that Python handles + this termination automatically. + REG_NONE -- No defined value type. + REG_RESOURCE_LIST -- A device-driver resource list. + REG_SZ -- A null-terminated string. + value: object + A string that specifies the new value. + / + +Stores data in the value field of an open registry key. + +This method can also set additional value and type information for the +specified key. The key identified by the key parameter must have been +opened with KEY_SET_VALUE access. + +To open the key, use the CreateKeyEx() or OpenKeyEx() methods. + +Value lengths are limited by available memory. Long values (more than +2048 bytes) should be stored as files with the filenames stored in +the configuration registry to help the registry perform efficiently. +[clinic start generated code]*/ + static PyObject * -PySetValueEx(PyObject *self, PyObject *args) +winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, PyObject *reserved, DWORD type, PyObject *value) +/*[clinic end generated code: output=a53ac3aecef9b977 input=8fe45d7ac381cf96]*/ { - HKEY hKey; - PyObject *obKey; - wchar_t *valueName; - PyObject *obRes; - PyObject *value; BYTE *data; DWORD len; - DWORD typ; LONG rc; - if (!PyArg_ParseTuple(args, "OZOiO:SetValueEx", - &obKey, - &valueName, - &obRes, - &typ, - &value)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - if (!Py2Reg(value, typ, &data, &len)) + if (!Py2Reg(value, type, &data, &len)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_ValueError, @@ -1599,31 +1636,40 @@ return NULL; } Py_BEGIN_ALLOW_THREADS - rc = RegSetValueExW(hKey, valueName, 0, typ, data, len); + rc = RegSetValueExW(key, value_name, 0, type, data, len); Py_END_ALLOW_THREADS PyMem_DEL(data); if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.DisableReflectionKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + / + +Disables registry reflection for 32bit processes running on a 64bit OS. + +Will generally raise NotImplemented if executed on a 32bit OS. + +If the key is not on the reflection list, the function succeeds but has +no effect. Disabling reflection for a key does not affect reflection +of any subkeys. +[clinic start generated code]*/ + static PyObject * -PyDisableReflectionKey(PyObject *self, PyObject *args) +winreg_DisableReflectionKey_impl(PyModuleDef *module, HKEY key) +/*[clinic end generated code: output=50fe6e2604324cdd input=a6c9e5ca5410193c]*/ { - HKEY hKey; - PyObject *obKey; HMODULE hMod; typedef LONG (WINAPI *RDRKFunc)(HKEY); RDRKFunc pfn = NULL; LONG rc; - if (!PyArg_ParseTuple(args, "O:DisableReflectionKey", &obKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - /* Only available on 64bit platforms, so we must load it dynamically.*/ hMod = GetModuleHandleW(L"advapi32.dll"); @@ -1636,30 +1682,37 @@ return NULL; } Py_BEGIN_ALLOW_THREADS - rc = (*pfn)(hKey); + rc = (*pfn)(key); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegDisableReflectionKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.EnableReflectionKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + / + +Restores registry reflection for the specified disabled key. + +Will generally raise NotImplemented if executed on a 32bit OS. +Restoring reflection for a key does not affect reflection of any +subkeys. +[clinic start generated code]*/ + static PyObject * -PyEnableReflectionKey(PyObject *self, PyObject *args) +winreg_EnableReflectionKey_impl(PyModuleDef *module, HKEY key) +/*[clinic end generated code: output=e3f23edb414f24a4 input=7748abbacd1e166a]*/ { - HKEY hKey; - PyObject *obKey; HMODULE hMod; typedef LONG (WINAPI *RERKFunc)(HKEY); RERKFunc pfn = NULL; LONG rc; - if (!PyArg_ParseTuple(args, "O:EnableReflectionKey", &obKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - /* Only available on 64bit platforms, so we must load it dynamically.*/ hMod = GetModuleHandleW(L"advapi32.dll"); @@ -1672,31 +1725,36 @@ return NULL; } Py_BEGIN_ALLOW_THREADS - rc = (*pfn)(hKey); + rc = (*pfn)(key); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnableReflectionKey"); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +winreg.QueryReflectionKey + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + / + +Returns the reflection state for the specified key as a bool. + +Will generally raise NotImplemented if executed on a 32bit OS. +[clinic start generated code]*/ + static PyObject * -PyQueryReflectionKey(PyObject *self, PyObject *args) +winreg_QueryReflectionKey_impl(PyModuleDef *module, HKEY key) +/*[clinic end generated code: output=2a49c564ca162e50 input=9f325eacb5a65d88]*/ { - HKEY hKey; - PyObject *obKey; HMODULE hMod; typedef LONG (WINAPI *RQRKFunc)(HKEY, BOOL *); RQRKFunc pfn = NULL; BOOL result; LONG rc; - if (!PyArg_ParseTuple(args, "O:QueryReflectionKey", &obKey)) - return NULL; - if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) - return NULL; - /* Only available on 64bit platforms, so we must load it dynamically.*/ hMod = GetModuleHandleW(L"advapi32.dll"); @@ -1709,7 +1767,7 @@ return NULL; } Py_BEGIN_ALLOW_THREADS - rc = (*pfn)(hKey, &result); + rc = (*pfn)(key, &result); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, @@ -1718,34 +1776,29 @@ } static struct PyMethodDef winreg_methods[] = { - {"CloseKey", PyCloseKey, METH_VARARGS, CloseKey_doc}, - {"ConnectRegistry", PyConnectRegistry, METH_VARARGS, ConnectRegistry_doc}, - {"CreateKey", PyCreateKey, METH_VARARGS, CreateKey_doc}, - {"CreateKeyEx", (PyCFunction)PyCreateKeyEx, - METH_VARARGS | METH_KEYWORDS, CreateKeyEx_doc}, - {"DeleteKey", PyDeleteKey, METH_VARARGS, DeleteKey_doc}, - {"DeleteKeyEx", (PyCFunction)PyDeleteKeyEx, - METH_VARARGS | METH_KEYWORDS, DeleteKeyEx_doc}, - {"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc}, - {"DisableReflectionKey", PyDisableReflectionKey, METH_VARARGS, DisableReflectionKey_doc}, - {"EnableReflectionKey", PyEnableReflectionKey, METH_VARARGS, EnableReflectionKey_doc}, - {"EnumKey", PyEnumKey, METH_VARARGS, EnumKey_doc}, - {"EnumValue", PyEnumValue, METH_VARARGS, EnumValue_doc}, - {"ExpandEnvironmentStrings", PyExpandEnvironmentStrings, METH_VARARGS, - ExpandEnvironmentStrings_doc }, - {"FlushKey", PyFlushKey, METH_VARARGS, FlushKey_doc}, - {"LoadKey", PyLoadKey, METH_VARARGS, LoadKey_doc}, - {"OpenKey", (PyCFunction)PyOpenKey, METH_VARARGS | METH_KEYWORDS, - OpenKey_doc}, - {"OpenKeyEx", (PyCFunction)PyOpenKey, METH_VARARGS | METH_KEYWORDS, - OpenKeyEx_doc}, - {"QueryValue", PyQueryValue, METH_VARARGS, QueryValue_doc}, - {"QueryValueEx", PyQueryValueEx, METH_VARARGS, QueryValueEx_doc}, - {"QueryInfoKey", PyQueryInfoKey, METH_VARARGS, QueryInfoKey_doc}, - {"QueryReflectionKey",PyQueryReflectionKey,METH_VARARGS, QueryReflectionKey_doc}, - {"SaveKey", PySaveKey, METH_VARARGS, SaveKey_doc}, - {"SetValue", PySetValue, METH_VARARGS, SetValue_doc}, - {"SetValueEx", PySetValueEx, METH_VARARGS, SetValueEx_doc}, + WINREG_CLOSEKEY_METHODDEF + WINREG_CONNECTREGISTRY_METHODDEF + WINREG_CREATEKEY_METHODDEF + WINREG_CREATEKEYEX_METHODDEF + WINREG_DELETEKEY_METHODDEF + WINREG_DELETEKEYEX_METHODDEF + WINREG_DELETEVALUE_METHODDEF + WINREG_DISABLEREFLECTIONKEY_METHODDEF + WINREG_ENABLEREFLECTIONKEY_METHODDEF + WINREG_ENUMKEY_METHODDEF + WINREG_ENUMVALUE_METHODDEF + WINREG_EXPANDENVIRONMENTSTRINGS_METHODDEF + WINREG_FLUSHKEY_METHODDEF + WINREG_LOADKEY_METHODDEF + WINREG_OPENKEY_METHODDEF + WINREG_OPENKEYEX_METHODDEF + WINREG_QUERYVALUE_METHODDEF + WINREG_QUERYVALUEEX_METHODDEF + WINREG_QUERYINFOKEY_METHODDEF + WINREG_QUERYREFLECTIONKEY_METHODDEF + WINREG_SAVEKEY_METHODDEF + WINREG_SETVALUE_METHODDEF + WINREG_SETVALUEEX_METHODDEF NULL, }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 08:32:28 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 06:32:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320172=3A_Convert_?= =?utf-8?q?the_msvcrt_module_to_Argument_Clinic=2E?= Message-ID: <20150513063228.122018.74878@psf.io> https://hg.python.org/cpython/rev/c190cf615eb2 changeset: 96008:c190cf615eb2 user: Zachary Ware date: Wed May 13 01:22:32 2015 -0500 summary: Issue #20172: Convert the msvcrt module to Argument Clinic. files: PC/clinic/msvcrtmodule.c.h | 604 +++++++++++++++++++++ PC/msvcrtmodule.c | 693 +++++++++++++----------- 2 files changed, 975 insertions(+), 322 deletions(-) diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h new file mode 100644 --- /dev/null +++ b/PC/clinic/msvcrtmodule.c.h @@ -0,0 +1,604 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(msvcrt_heapmin__doc__, +"heapmin($module, /)\n" +"--\n" +"\n" +"Minimize the malloc() heap.\n" +"\n" +"Force the malloc() heap to clean itself up and return unused blocks\n" +"to the operating system. On failure, this raises OSError."); + +#define MSVCRT_HEAPMIN_METHODDEF \ + {"heapmin", (PyCFunction)msvcrt_heapmin, METH_NOARGS, msvcrt_heapmin__doc__}, + +static PyObject * +msvcrt_heapmin_impl(PyModuleDef *module); + +static PyObject * +msvcrt_heapmin(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return msvcrt_heapmin_impl(module); +} + +PyDoc_STRVAR(msvcrt_locking__doc__, +"locking($module, fd, mode, nbytes, /)\n" +"--\n" +"\n" +"Lock part of a file based on file descriptor fd from the C runtime.\n" +"\n" +"Raises IOError on failure. The locked region of the file extends from\n" +"the current file position for nbytes bytes, and may continue beyond\n" +"the end of the file. mode must be one of the LK_* constants listed\n" +"below. Multiple regions in a file may be locked at the same time, but\n" +"may not overlap. Adjacent regions are not merged; they must be unlocked\n" +"individually."); + +#define MSVCRT_LOCKING_METHODDEF \ + {"locking", (PyCFunction)msvcrt_locking, METH_VARARGS, msvcrt_locking__doc__}, + +static PyObject * +msvcrt_locking_impl(PyModuleDef *module, int fd, int mode, long nbytes); + +static PyObject * +msvcrt_locking(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int mode; + long nbytes; + + if (!PyArg_ParseTuple(args, + "iil:locking", + &fd, &mode, &nbytes)) + goto exit; + return_value = msvcrt_locking_impl(module, fd, mode, nbytes); + +exit: + return return_value; +} + +PyDoc_STRVAR(msvcrt_setmode__doc__, +"setmode($module, fd, mode, /)\n" +"--\n" +"\n" +"Set the line-end translation mode for the file descriptor fd.\n" +"\n" +"To set it to text mode, flags should be os.O_TEXT; for binary, it\n" +"should be os.O_BINARY.\n" +"\n" +"Return value is the previous mode."); + +#define MSVCRT_SETMODE_METHODDEF \ + {"setmode", (PyCFunction)msvcrt_setmode, METH_VARARGS, msvcrt_setmode__doc__}, + +static long +msvcrt_setmode_impl(PyModuleDef *module, int fd, int flags); + +static PyObject * +msvcrt_setmode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int flags; + long _return_value; + + if (!PyArg_ParseTuple(args, + "ii:setmode", + &fd, &flags)) + goto exit; + _return_value = msvcrt_setmode_impl(module, fd, flags); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(msvcrt_open_osfhandle__doc__, +"open_osfhandle($module, handle, flags, /)\n" +"--\n" +"\n" +"Create a C runtime file descriptor from the file handle handle.\n" +"\n" +"The flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,\n" +"and os.O_TEXT. The returned file descriptor may be used as a parameter\n" +"to os.fdopen() to create a file object."); + +#define MSVCRT_OPEN_OSFHANDLE_METHODDEF \ + {"open_osfhandle", (PyCFunction)msvcrt_open_osfhandle, METH_VARARGS, msvcrt_open_osfhandle__doc__}, + +static long +msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, int flags); + +static PyObject * +msvcrt_open_osfhandle(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_intptr_t handle; + int flags; + long _return_value; + + if (!PyArg_ParseTuple(args, + ""_Py_PARSE_INTPTR"i:open_osfhandle", + &handle, &flags)) + goto exit; + _return_value = msvcrt_open_osfhandle_impl(module, handle, flags); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(msvcrt_get_osfhandle__doc__, +"get_osfhandle($module, fd, /)\n" +"--\n" +"\n" +"Return the file handle for the file descriptor fd.\n" +"\n" +"Raises IOError if fd is not recognized."); + +#define MSVCRT_GET_OSFHANDLE_METHODDEF \ + {"get_osfhandle", (PyCFunction)msvcrt_get_osfhandle, METH_O, msvcrt_get_osfhandle__doc__}, + +static Py_intptr_t +msvcrt_get_osfhandle_impl(PyModuleDef *module, int fd); + +static PyObject * +msvcrt_get_osfhandle(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + Py_intptr_t _return_value; + + if (!PyArg_Parse(arg, + "i:get_osfhandle", + &fd)) + goto exit; + _return_value = msvcrt_get_osfhandle_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromVoidPtr((void *)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(msvcrt_kbhit__doc__, +"kbhit($module, /)\n" +"--\n" +"\n" +"Return true if a keypress is waiting to be read."); + +#define MSVCRT_KBHIT_METHODDEF \ + {"kbhit", (PyCFunction)msvcrt_kbhit, METH_NOARGS, msvcrt_kbhit__doc__}, + +static long +msvcrt_kbhit_impl(PyModuleDef *module); + +static PyObject * +msvcrt_kbhit(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + long _return_value; + + _return_value = msvcrt_kbhit_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(msvcrt_getch__doc__, +"getch($module, /)\n" +"--\n" +"\n" +"Read a keypress and return the resulting character as a byte string.\n" +"\n" +"Nothing is echoed to the console. This call will block if a keypress is\n" +"not already available, but will not wait for Enter to be pressed. If the\n" +"pressed key was a special function key, this will return \'\\000\' or\n" +"\'\\xe0\'; the next call will return the keycode. The Control-C keypress\n" +"cannot be read with this function."); + +#define MSVCRT_GETCH_METHODDEF \ + {"getch", (PyCFunction)msvcrt_getch, METH_NOARGS, msvcrt_getch__doc__}, + +static int +msvcrt_getch_impl(PyModuleDef *module); + +static PyObject * +msvcrt_getch(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + char s[1]; + + s[0] = msvcrt_getch_impl(module); + return_value = PyBytes_FromStringAndSize(s, 1); + + return return_value; +} + +#if defined(_WCONIO_DEFINED) + +PyDoc_STRVAR(msvcrt_getwch__doc__, +"getwch($module, /)\n" +"--\n" +"\n" +"Wide char variant of getch(), returning a Unicode value."); + +#define MSVCRT_GETWCH_METHODDEF \ + {"getwch", (PyCFunction)msvcrt_getwch, METH_NOARGS, msvcrt_getwch__doc__}, + +static wchar_t +msvcrt_getwch_impl(PyModuleDef *module); + +static PyObject * +msvcrt_getwch(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + wchar_t _return_value; + + _return_value = msvcrt_getwch_impl(module); + return_value = PyUnicode_FromOrdinal(_return_value); + + return return_value; +} + +#endif /* defined(_WCONIO_DEFINED) */ + +PyDoc_STRVAR(msvcrt_getche__doc__, +"getche($module, /)\n" +"--\n" +"\n" +"Similar to getch(), but the keypress will be echoed if possible."); + +#define MSVCRT_GETCHE_METHODDEF \ + {"getche", (PyCFunction)msvcrt_getche, METH_NOARGS, msvcrt_getche__doc__}, + +static int +msvcrt_getche_impl(PyModuleDef *module); + +static PyObject * +msvcrt_getche(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + char s[1]; + + s[0] = msvcrt_getche_impl(module); + return_value = PyBytes_FromStringAndSize(s, 1); + + return return_value; +} + +#if defined(_WCONIO_DEFINED) + +PyDoc_STRVAR(msvcrt_getwche__doc__, +"getwche($module, /)\n" +"--\n" +"\n" +"Wide char variant of getche(), returning a Unicode value."); + +#define MSVCRT_GETWCHE_METHODDEF \ + {"getwche", (PyCFunction)msvcrt_getwche, METH_NOARGS, msvcrt_getwche__doc__}, + +static wchar_t +msvcrt_getwche_impl(PyModuleDef *module); + +static PyObject * +msvcrt_getwche(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + wchar_t _return_value; + + _return_value = msvcrt_getwche_impl(module); + return_value = PyUnicode_FromOrdinal(_return_value); + + return return_value; +} + +#endif /* defined(_WCONIO_DEFINED) */ + +PyDoc_STRVAR(msvcrt_putch__doc__, +"putch($module, char, /)\n" +"--\n" +"\n" +"Print the byte string char to the console without buffering."); + +#define MSVCRT_PUTCH_METHODDEF \ + {"putch", (PyCFunction)msvcrt_putch, METH_O, msvcrt_putch__doc__}, + +static PyObject * +msvcrt_putch_impl(PyModuleDef *module, char char_value); + +static PyObject * +msvcrt_putch(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + char char_value; + + if (!PyArg_Parse(arg, + "c:putch", + &char_value)) + goto exit; + return_value = msvcrt_putch_impl(module, char_value); + +exit: + return return_value; +} + +#if defined(_WCONIO_DEFINED) + +PyDoc_STRVAR(msvcrt_putwch__doc__, +"putwch($module, unicode_char, /)\n" +"--\n" +"\n" +"Wide char variant of putch(), accepting a Unicode value."); + +#define MSVCRT_PUTWCH_METHODDEF \ + {"putwch", (PyCFunction)msvcrt_putwch, METH_O, msvcrt_putwch__doc__}, + +static PyObject * +msvcrt_putwch_impl(PyModuleDef *module, int unicode_char); + +static PyObject * +msvcrt_putwch(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int unicode_char; + + if (!PyArg_Parse(arg, + "C:putwch", + &unicode_char)) + goto exit; + return_value = msvcrt_putwch_impl(module, unicode_char); + +exit: + return return_value; +} + +#endif /* defined(_WCONIO_DEFINED) */ + +PyDoc_STRVAR(msvcrt_ungetch__doc__, +"ungetch($module, char, /)\n" +"--\n" +"\n" +"Opposite of getch.\n" +"\n" +"Cause the byte string char to be \"pushed back\" into the\n" +"console buffer; it will be the next character read by\n" +"getch() or getche()."); + +#define MSVCRT_UNGETCH_METHODDEF \ + {"ungetch", (PyCFunction)msvcrt_ungetch, METH_O, msvcrt_ungetch__doc__}, + +static PyObject * +msvcrt_ungetch_impl(PyModuleDef *module, char char_value); + +static PyObject * +msvcrt_ungetch(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + char char_value; + + if (!PyArg_Parse(arg, + "c:ungetch", + &char_value)) + goto exit; + return_value = msvcrt_ungetch_impl(module, char_value); + +exit: + return return_value; +} + +#if defined(_WCONIO_DEFINED) + +PyDoc_STRVAR(msvcrt_ungetwch__doc__, +"ungetwch($module, unicode_char, /)\n" +"--\n" +"\n" +"Wide char variant of ungetch(), accepting a Unicode value."); + +#define MSVCRT_UNGETWCH_METHODDEF \ + {"ungetwch", (PyCFunction)msvcrt_ungetwch, METH_O, msvcrt_ungetwch__doc__}, + +static PyObject * +msvcrt_ungetwch_impl(PyModuleDef *module, int unicode_char); + +static PyObject * +msvcrt_ungetwch(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int unicode_char; + + if (!PyArg_Parse(arg, + "C:ungetwch", + &unicode_char)) + goto exit; + return_value = msvcrt_ungetwch_impl(module, unicode_char); + +exit: + return return_value; +} + +#endif /* defined(_WCONIO_DEFINED) */ + +#if defined(_DEBUG) + +PyDoc_STRVAR(msvcrt_CrtSetReportFile__doc__, +"CrtSetReportFile($module, type, file, /)\n" +"--\n" +"\n" +"Wrapper around _CrtSetReportFile.\n" +"\n" +"Only available on Debug builds."); + +#define MSVCRT_CRTSETREPORTFILE_METHODDEF \ + {"CrtSetReportFile", (PyCFunction)msvcrt_CrtSetReportFile, METH_VARARGS, msvcrt_CrtSetReportFile__doc__}, + +static long +msvcrt_CrtSetReportFile_impl(PyModuleDef *module, int type, int file); + +static PyObject * +msvcrt_CrtSetReportFile(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int type; + int file; + long _return_value; + + if (!PyArg_ParseTuple(args, + "ii:CrtSetReportFile", + &type, &file)) + goto exit; + _return_value = msvcrt_CrtSetReportFile_impl(module, type, file); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(_DEBUG) */ + +#if defined(_DEBUG) + +PyDoc_STRVAR(msvcrt_CrtSetReportMode__doc__, +"CrtSetReportMode($module, type, mode, /)\n" +"--\n" +"\n" +"Wrapper around _CrtSetReportMode.\n" +"\n" +"Only available on Debug builds."); + +#define MSVCRT_CRTSETREPORTMODE_METHODDEF \ + {"CrtSetReportMode", (PyCFunction)msvcrt_CrtSetReportMode, METH_VARARGS, msvcrt_CrtSetReportMode__doc__}, + +static long +msvcrt_CrtSetReportMode_impl(PyModuleDef *module, int type, int mode); + +static PyObject * +msvcrt_CrtSetReportMode(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int type; + int mode; + long _return_value; + + if (!PyArg_ParseTuple(args, + "ii:CrtSetReportMode", + &type, &mode)) + goto exit; + _return_value = msvcrt_CrtSetReportMode_impl(module, type, mode); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(_DEBUG) */ + +#if defined(_DEBUG) + +PyDoc_STRVAR(msvcrt_set_error_mode__doc__, +"set_error_mode($module, mode, /)\n" +"--\n" +"\n" +"Wrapper around _set_error_mode.\n" +"\n" +"Only available on Debug builds."); + +#define MSVCRT_SET_ERROR_MODE_METHODDEF \ + {"set_error_mode", (PyCFunction)msvcrt_set_error_mode, METH_O, msvcrt_set_error_mode__doc__}, + +static long +msvcrt_set_error_mode_impl(PyModuleDef *module, int mode); + +static PyObject * +msvcrt_set_error_mode(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int mode; + long _return_value; + + if (!PyArg_Parse(arg, + "i:set_error_mode", + &mode)) + goto exit; + _return_value = msvcrt_set_error_mode_impl(module, mode); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(_DEBUG) */ + +PyDoc_STRVAR(msvcrt_SetErrorMode__doc__, +"SetErrorMode($module, mode, /)\n" +"--\n" +"\n" +"Wrapper around SetErrorMode."); + +#define MSVCRT_SETERRORMODE_METHODDEF \ + {"SetErrorMode", (PyCFunction)msvcrt_SetErrorMode, METH_O, msvcrt_SetErrorMode__doc__}, + +static PyObject * +msvcrt_SetErrorMode_impl(PyModuleDef *module, unsigned int mode); + +static PyObject * +msvcrt_SetErrorMode(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned int mode; + + if (!PyArg_Parse(arg, + "I:SetErrorMode", + &mode)) + goto exit; + return_value = msvcrt_SetErrorMode_impl(module, mode); + +exit: + return return_value; +} + +#ifndef MSVCRT_GETWCH_METHODDEF + #define MSVCRT_GETWCH_METHODDEF +#endif /* !defined(MSVCRT_GETWCH_METHODDEF) */ + +#ifndef MSVCRT_GETWCHE_METHODDEF + #define MSVCRT_GETWCHE_METHODDEF +#endif /* !defined(MSVCRT_GETWCHE_METHODDEF) */ + +#ifndef MSVCRT_PUTWCH_METHODDEF + #define MSVCRT_PUTWCH_METHODDEF +#endif /* !defined(MSVCRT_PUTWCH_METHODDEF) */ + +#ifndef MSVCRT_UNGETWCH_METHODDEF + #define MSVCRT_UNGETWCH_METHODDEF +#endif /* !defined(MSVCRT_UNGETWCH_METHODDEF) */ + +#ifndef MSVCRT_CRTSETREPORTFILE_METHODDEF + #define MSVCRT_CRTSETREPORTFILE_METHODDEF +#endif /* !defined(MSVCRT_CRTSETREPORTFILE_METHODDEF) */ + +#ifndef MSVCRT_CRTSETREPORTMODE_METHODDEF + #define MSVCRT_CRTSETREPORTMODE_METHODDEF +#endif /* !defined(MSVCRT_CRTSETREPORTMODE_METHODDEF) */ + +#ifndef MSVCRT_SET_ERROR_MODE_METHODDEF + #define MSVCRT_SET_ERROR_MODE_METHODDEF +#endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ +/*[clinic end generated code: output=41dfb6ca722afa4f input=a9049054013a1b77]*/ diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c --- a/PC/msvcrtmodule.c +++ b/PC/msvcrtmodule.c @@ -32,329 +32,473 @@ #endif #endif -// Force the malloc heap to clean itself up, and free unused blocks -// back to the OS. (According to the docs, only works on NT.) +/*[python input] +class Py_intptr_t_converter(CConverter): + type = 'Py_intptr_t' + format_unit = '"_Py_PARSE_INTPTR"' + +class handle_return_converter(long_return_converter): + type = 'Py_intptr_t' + cast = '(void *)' + conversion_fn = 'PyLong_FromVoidPtr' + +class byte_char_return_converter(CReturnConverter): + type = 'int' + + def render(self, function, data): + data.declarations.append('char s[1];') + data.return_value = 's[0]' + data.return_conversion.append( + 'return_value = PyBytes_FromStringAndSize(s, 1);\n') + +class wchar_t_return_converter(CReturnConverter): + type = 'wchar_t' + + def render(self, function, data): + self.declare(data) + data.return_conversion.append( + 'return_value = PyUnicode_FromOrdinal(_return_value);\n') +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=6a54fc4e73d0b367]*/ + +/*[clinic input] +module msvcrt +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f31a87a783d036cd]*/ + +#include "clinic/msvcrtmodule.c.h" + +/*[clinic input] +msvcrt.heapmin + +Minimize the malloc() heap. + +Force the malloc() heap to clean itself up and return unused blocks +to the operating system. On failure, this raises OSError. +[clinic start generated code]*/ + static PyObject * -msvcrt_heapmin(PyObject *self, PyObject *args) +msvcrt_heapmin_impl(PyModuleDef *module) +/*[clinic end generated code: output=464f866feb57c436 input=82e1771d21bde2d8]*/ { - if (!PyArg_ParseTuple(args, ":heapmin")) - return NULL; - if (_heapmin() != 0) return PyErr_SetFromErrno(PyExc_IOError); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +msvcrt.locking -PyDoc_STRVAR(heapmin_doc, -"heapmin() -> None\n\ -\n\ -Force the malloc() heap to clean itself up and return unused blocks\n\ -to the operating system. On failure, this raises IOError."); + fd: int + mode: int + nbytes: long + / -// Perform locking operations on a C runtime file descriptor. +Lock part of a file based on file descriptor fd from the C runtime. + +Raises IOError on failure. The locked region of the file extends from +the current file position for nbytes bytes, and may continue beyond +the end of the file. mode must be one of the LK_* constants listed +below. Multiple regions in a file may be locked at the same time, but +may not overlap. Adjacent regions are not merged; they must be unlocked +individually. +[clinic start generated code]*/ + static PyObject * -msvcrt_locking(PyObject *self, PyObject *args) +msvcrt_locking_impl(PyModuleDef *module, int fd, int mode, long nbytes) +/*[clinic end generated code: output=dff41e5e76d544de input=d9f13f0f6a713ba7]*/ { - int fd; - int mode; - long nbytes; int err; - if (!PyArg_ParseTuple(args, "iil:locking", &fd, &mode, &nbytes)) - return NULL; - Py_BEGIN_ALLOW_THREADS err = _locking(fd, mode, nbytes); Py_END_ALLOW_THREADS if (err != 0) return PyErr_SetFromErrno(PyExc_IOError); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -PyDoc_STRVAR(locking_doc, -"locking(fd, mode, nbytes) -> None\n\ -\n\ -Lock part of a file based on file descriptor fd from the C runtime.\n\ -Raises IOError on failure. The locked region of the file extends from\n\ -the current file position for nbytes bytes, and may continue beyond\n\ -the end of the file. mode must be one of the LK_* constants listed\n\ -below. Multiple regions in a file may be locked at the same time, but\n\ -may not overlap. Adjacent regions are not merged; they must be unlocked\n\ -individually."); +/*[clinic input] +msvcrt.setmode -> long -// Set the file translation mode for a C runtime file descriptor. -static PyObject * -msvcrt_setmode(PyObject *self, PyObject *args) + fd: int + mode as flags: int + / + +Set the line-end translation mode for the file descriptor fd. + +To set it to text mode, flags should be os.O_TEXT; for binary, it +should be os.O_BINARY. + +Return value is the previous mode. +[clinic start generated code]*/ + +static long +msvcrt_setmode_impl(PyModuleDef *module, int fd, int flags) +/*[clinic end generated code: output=8c84e5b37c586d0d input=76e7c01f6b137f75]*/ +{ + flags = _setmode(fd, flags); + if (flags == -1) + PyErr_SetFromErrno(PyExc_IOError); + + return flags; +} + +/*[clinic input] +msvcrt.open_osfhandle -> long + + handle: Py_intptr_t + flags: int + / + +Create a C runtime file descriptor from the file handle handle. + +The flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY, +and os.O_TEXT. The returned file descriptor may be used as a parameter +to os.fdopen() to create a file object. +[clinic start generated code]*/ + +static long +msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, int flags) +/*[clinic end generated code: output=8cda35b8e4ea4178 input=4d8516ed32db8f65]*/ { int fd; - int flags; - if (!PyArg_ParseTuple(args,"ii:setmode", &fd, &flags)) - return NULL; - - flags = _setmode(fd, flags); - if (flags == -1) - return PyErr_SetFromErrno(PyExc_IOError); - - return PyLong_FromLong(flags); -} - -PyDoc_STRVAR(setmode_doc, -"setmode(fd, mode) -> Previous mode\n\ -\n\ -Set the line-end translation mode for the file descriptor fd. To set\n\ -it to text mode, flags should be os.O_TEXT; for binary, it should be\n\ -os.O_BINARY."); - -// Convert an OS file handle to a C runtime file descriptor. -static PyObject * -msvcrt_open_osfhandle(PyObject *self, PyObject *args) -{ - Py_intptr_t handle; - int flags; - int fd; - - if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR "i:open_osfhandle", - &handle, &flags)) - return NULL; fd = _open_osfhandle(handle, flags); if (fd == -1) - return PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_IOError); - return PyLong_FromLong(fd); + return fd; } -PyDoc_STRVAR(open_osfhandle_doc, -"open_osfhandle(handle, flags) -> file descriptor\n\ -\n\ -Create a C runtime file descriptor from the file handle handle. The\n\ -flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,\n\ -and os.O_TEXT. The returned file descriptor may be used as a parameter\n\ -to os.fdopen() to create a file object."); +/*[clinic input] +msvcrt.get_osfhandle -> handle -// Convert a C runtime file descriptor to an OS file handle. -static PyObject * -msvcrt_get_osfhandle(PyObject *self, PyObject *args) + fd: int + / + +Return the file handle for the file descriptor fd. + +Raises IOError if fd is not recognized. +[clinic start generated code]*/ + +static Py_intptr_t +msvcrt_get_osfhandle_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=376bff52586b55a6 input=c7d18d02c8017ec1]*/ { - int fd; - Py_intptr_t handle; + Py_intptr_t handle = -1; - if (!PyArg_ParseTuple(args,"i:get_osfhandle", &fd)) - return NULL; + if (!_PyVerify_fd(fd)) { + PyErr_SetFromErrno(PyExc_IOError); + } + else { + _Py_BEGIN_SUPPRESS_IPH + handle = _get_osfhandle(fd); + _Py_END_SUPPRESS_IPH + if (handle == -1) + PyErr_SetFromErrno(PyExc_IOError); + } - if (!_PyVerify_fd(fd)) - return PyErr_SetFromErrno(PyExc_IOError); - - _Py_BEGIN_SUPPRESS_IPH - handle = _get_osfhandle(fd); - _Py_END_SUPPRESS_IPH - if (handle == -1) - return PyErr_SetFromErrno(PyExc_IOError); - - /* technically 'handle' is not a pointer, but a integer as - large as a pointer, Python's *VoidPtr interface is the - most appropriate here */ - return PyLong_FromVoidPtr((void*)handle); + return handle; } -PyDoc_STRVAR(get_osfhandle_doc, -"get_osfhandle(fd) -> file handle\n\ -\n\ -Return the file handle for the file descriptor fd. Raises IOError\n\ -if fd is not recognized."); +/* Console I/O */ +/*[clinic input] +msvcrt.kbhit -> long -/* Console I/O */ +Return true if a keypress is waiting to be read. +[clinic start generated code]*/ -static PyObject * -msvcrt_kbhit(PyObject *self, PyObject *args) +static long +msvcrt_kbhit_impl(PyModuleDef *module) +/*[clinic end generated code: output=2b7293fcbe5cb24e input=e70d678a5c2f6acc]*/ { - int ok; - - if (!PyArg_ParseTuple(args, ":kbhit")) - return NULL; - - ok = _kbhit(); - return PyLong_FromLong(ok); + return _kbhit(); } -PyDoc_STRVAR(kbhit_doc, -"kbhit() -> bool\n\ -\n\ -Return true if a keypress is waiting to be read."); +/*[clinic input] +msvcrt.getch -> byte_char -static PyObject * -msvcrt_getch(PyObject *self, PyObject *args) +Read a keypress and return the resulting character as a byte string. + +Nothing is echoed to the console. This call will block if a keypress is +not already available, but will not wait for Enter to be pressed. If the +pressed key was a special function key, this will return '\000' or +'\xe0'; the next call will return the keycode. The Control-C keypress +cannot be read with this function. +[clinic start generated code]*/ + +static int +msvcrt_getch_impl(PyModuleDef *module) +/*[clinic end generated code: output=199e3d89f49c166a input=37a40cf0ed0d1153]*/ { int ch; - char s[1]; - - if (!PyArg_ParseTuple(args, ":getch")) - return NULL; Py_BEGIN_ALLOW_THREADS ch = _getch(); Py_END_ALLOW_THREADS - s[0] = ch; - return PyBytes_FromStringAndSize(s, 1); + return ch; } -PyDoc_STRVAR(getch_doc, -"getch() -> key character\n\ -\n\ -Read a keypress and return the resulting character as a byte string.\n\ -Nothing is echoed to the console. This call will block if a keypress is\n\ -not already available, but will not wait for Enter to be pressed. If the\n\ -pressed key was a special function key, this will return '\\000' or\n\ -'\\xe0'; the next call will return the keycode. The Control-C keypress\n\ -cannot be read with this function."); +#ifdef _WCONIO_DEFINED +/*[clinic input] +msvcrt.getwch -> wchar_t -#ifdef _WCONIO_DEFINED -static PyObject * -msvcrt_getwch(PyObject *self, PyObject *args) +Wide char variant of getch(), returning a Unicode value. +[clinic start generated code]*/ + +static wchar_t +msvcrt_getwch_impl(PyModuleDef *module) +/*[clinic end generated code: output=9d3762861328b1fe input=27b3dec8ad823d7c]*/ { wchar_t ch; - if (!PyArg_ParseTuple(args, ":getwch")) - return NULL; - Py_BEGIN_ALLOW_THREADS ch = _getwch(); Py_END_ALLOW_THREADS - return PyUnicode_FromOrdinal(ch); + return ch; } +#endif /* _WCONIO_DEFINED */ -PyDoc_STRVAR(getwch_doc, -"getwch() -> Unicode key character\n\ -\n\ -Wide char variant of getch(), returning a Unicode value."); -#endif +/*[clinic input] +msvcrt.getche -> byte_char -static PyObject * -msvcrt_getche(PyObject *self, PyObject *args) +Similar to getch(), but the keypress will be echoed if possible. +[clinic start generated code]*/ + +static int +msvcrt_getche_impl(PyModuleDef *module) +/*[clinic end generated code: output=8aa369be6550068e input=43311ade9ed4a9c0]*/ { int ch; - char s[1]; - - if (!PyArg_ParseTuple(args, ":getche")) - return NULL; Py_BEGIN_ALLOW_THREADS ch = _getche(); Py_END_ALLOW_THREADS - s[0] = ch; - return PyBytes_FromStringAndSize(s, 1); + return ch; } -PyDoc_STRVAR(getche_doc, -"getche() -> key character\n\ -\n\ -Similar to getch(), but the keypress will be echoed if it represents\n\ -a printable character."); +#ifdef _WCONIO_DEFINED +/*[clinic input] +msvcrt.getwche -> wchar_t -#ifdef _WCONIO_DEFINED -static PyObject * -msvcrt_getwche(PyObject *self, PyObject *args) +Wide char variant of getche(), returning a Unicode value. +[clinic start generated code]*/ + +static wchar_t +msvcrt_getwche_impl(PyModuleDef *module) +/*[clinic end generated code: output=3693cf78e3ea0cf6 input=49337d59d1a591f8]*/ { wchar_t ch; - if (!PyArg_ParseTuple(args, ":getwche")) - return NULL; - Py_BEGIN_ALLOW_THREADS ch = _getwche(); Py_END_ALLOW_THREADS - return PyUnicode_FromOrdinal(ch); + return ch; +} +#endif /* _WCONIO_DEFINED */ + +/*[clinic input] +msvcrt.putch + + char: char + / + +Print the byte string char to the console without buffering. +[clinic start generated code]*/ + +static PyObject * +msvcrt_putch_impl(PyModuleDef *module, char char_value) +/*[clinic end generated code: output=c05548b11554f36f input=ec078dd10cb054d6]*/ +{ + _putch(char_value); + Py_RETURN_NONE; } -PyDoc_STRVAR(getwche_doc, -"getwche() -> Unicode key character\n\ -\n\ -Wide char variant of getche(), returning a Unicode value."); -#endif +#ifdef _WCONIO_DEFINED +/*[clinic input] +msvcrt.putwch + + unicode_char: int(types='str') + / + +Wide char variant of putch(), accepting a Unicode value. +[clinic start generated code]*/ static PyObject * -msvcrt_putch(PyObject *self, PyObject *args) +msvcrt_putwch_impl(PyModuleDef *module, int unicode_char) +/*[clinic end generated code: output=c216a73694ca73dd input=74377c932af728a4]*/ { - char ch; - - if (!PyArg_ParseTuple(args, "c:putch", &ch)) - return NULL; - - _putch(ch); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(putch_doc, -"putch(char) -> None\n\ -\n\ -Print the byte string char to the console without buffering."); - -#ifdef _WCONIO_DEFINED -static PyObject * -msvcrt_putwch(PyObject *self, PyObject *args) -{ - int ch; - - if (!PyArg_ParseTuple(args, "C:putwch", &ch)) - return NULL; - - _putwch(ch); + _putwch(unicode_char); Py_RETURN_NONE; } +#endif /* _WCONIO_DEFINED */ -PyDoc_STRVAR(putwch_doc, -"putwch(unicode_char) -> None\n\ -\n\ -Wide char variant of putch(), accepting a Unicode value."); -#endif +/*[clinic input] +msvcrt.ungetch + + char: char + / + +Opposite of getch. + +Cause the byte string char to be "pushed back" into the +console buffer; it will be the next character read by +getch() or getche(). +[clinic start generated code]*/ static PyObject * -msvcrt_ungetch(PyObject *self, PyObject *args) +msvcrt_ungetch_impl(PyModuleDef *module, char char_value) +/*[clinic end generated code: output=19a4cd3249709ec9 input=22f07ee9001bbf0f]*/ { - char ch; - - if (!PyArg_ParseTuple(args, "c:ungetch", &ch)) - return NULL; - - if (_ungetch(ch) == EOF) + if (_ungetch(char_value) == EOF) return PyErr_SetFromErrno(PyExc_IOError); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -PyDoc_STRVAR(ungetch_doc, -"ungetch(char) -> None\n\ -\n\ -Cause the byte string char to be \"pushed back\" into the\n\ -console buffer; it will be the next character read by\n\ -getch() or getche()."); +#ifdef _WCONIO_DEFINED +/*[clinic input] +msvcrt.ungetwch -#ifdef _WCONIO_DEFINED + unicode_char: int(types='str') + / + +Wide char variant of ungetch(), accepting a Unicode value. +[clinic start generated code]*/ + static PyObject * -msvcrt_ungetwch(PyObject *self, PyObject *args) +msvcrt_ungetwch_impl(PyModuleDef *module, int unicode_char) +/*[clinic end generated code: output=1ee7674710322bd1 input=6bcd16276e035902]*/ { - int ch; + if (_ungetwch(unicode_char) == WEOF) + return PyErr_SetFromErrno(PyExc_IOError); + Py_RETURN_NONE; +} +#endif /* _WCONIO_DEFINED */ - if (!PyArg_ParseTuple(args, "C:ungetwch", &ch)) - return NULL; +#ifdef _DEBUG +/*[clinic input] +msvcrt.CrtSetReportFile -> long - if (_ungetwch(ch) == WEOF) - return PyErr_SetFromErrno(PyExc_IOError); - Py_INCREF(Py_None); - return Py_None; + type: int + file: int + / + +Wrapper around _CrtSetReportFile. + +Only available on Debug builds. +[clinic start generated code]*/ + +static long +msvcrt_CrtSetReportFile_impl(PyModuleDef *module, int type, int file) +/*[clinic end generated code: output=8c3644fb2edfa808 input=bb8f721a604fcc45]*/ +{ + return (long)_CrtSetReportFile(type, (_HFILE)file); } -PyDoc_STRVAR(ungetwch_doc, -"ungetwch(unicode_char) -> None\n\ -\n\ -Wide char variant of ungetch(), accepting a Unicode value."); -#endif +/*[clinic input] +msvcrt.CrtSetReportMode -> long + + type: int + mode: int + / + +Wrapper around _CrtSetReportMode. + +Only available on Debug builds. +[clinic start generated code]*/ + +static long +msvcrt_CrtSetReportMode_impl(PyModuleDef *module, int type, int mode) +/*[clinic end generated code: output=b407fbf8716a52b9 input=9319d29b4319426b]*/ +{ + int res; + + res = _CrtSetReportMode(type, mode); + if (res == -1) + PyErr_SetFromErrno(PyExc_IOError); + return res; +} + +/*[clinic input] +msvcrt.set_error_mode -> long + + mode: int + / + +Wrapper around _set_error_mode. + +Only available on Debug builds. +[clinic start generated code]*/ + +static long +msvcrt_set_error_mode_impl(PyModuleDef *module, int mode) +/*[clinic end generated code: output=62148adffa90867d input=046fca59c0f20872]*/ +{ + return _set_error_mode(mode); +} +#endif /* _DEBUG */ + +/*[clinic input] +msvcrt.SetErrorMode + + mode: unsigned_int(bitwise=True) + / + +Wrapper around SetErrorMode. +[clinic start generated code]*/ + +static PyObject * +msvcrt_SetErrorMode_impl(PyModuleDef *module, unsigned int mode) +/*[clinic end generated code: output=544c60b085be79c6 input=d8b167258d32d907]*/ +{ + unsigned int res; + + res = SetErrorMode(mode); + return PyLong_FromUnsignedLong(res); +} + +/*[clinic input] +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/ + +/* List of functions exported by this module */ +static struct PyMethodDef msvcrt_functions[] = { + MSVCRT_HEAPMIN_METHODDEF + MSVCRT_LOCKING_METHODDEF + MSVCRT_SETMODE_METHODDEF + MSVCRT_OPEN_OSFHANDLE_METHODDEF + MSVCRT_GET_OSFHANDLE_METHODDEF + MSVCRT_KBHIT_METHODDEF + MSVCRT_GETCH_METHODDEF + MSVCRT_GETCHE_METHODDEF + MSVCRT_PUTCH_METHODDEF + MSVCRT_UNGETCH_METHODDEF + MSVCRT_SETERRORMODE_METHODDEF + MSVCRT_CRTSETREPORTFILE_METHODDEF + MSVCRT_CRTSETREPORTMODE_METHODDEF + MSVCRT_SET_ERROR_MODE_METHODDEF + MSVCRT_GETWCH_METHODDEF + MSVCRT_GETWCHE_METHODDEF + MSVCRT_PUTWCH_METHODDEF + MSVCRT_UNGETWCH_METHODDEF + {NULL, NULL} +}; + + +static struct PyModuleDef msvcrtmodule = { + PyModuleDef_HEAD_INIT, + "msvcrt", + NULL, + -1, + msvcrt_functions, + NULL, + NULL, + NULL, + NULL +}; static void insertint(PyObject *d, char *name, int value) @@ -370,101 +514,6 @@ } } -#ifdef _DEBUG - -static PyObject* -msvcrt_setreportfile(PyObject *self, PyObject *args) -{ - int type, file; - _HFILE res; - - if (!PyArg_ParseTuple(args, "ii", &type, &file)) - return NULL; - res = _CrtSetReportFile(type, (_HFILE)file); - return PyLong_FromLong((long)res); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -msvcrt_setreportmode(PyObject *self, PyObject *args) -{ - int type, mode; - int res; - - if (!PyArg_ParseTuple(args, "ii", &type, &mode)) - return NULL; - res = _CrtSetReportMode(type, mode); - if (res == -1) - return PyErr_SetFromErrno(PyExc_IOError); - return PyLong_FromLong(res); -} - -static PyObject* -msvcrt_seterrormode(PyObject *self, PyObject *args) -{ - int mode, res; - - if (!PyArg_ParseTuple(args, "i", &mode)) - return NULL; - res = _set_error_mode(mode); - return PyLong_FromLong(res); -} - -#endif - -static PyObject* -seterrormode(PyObject *self, PyObject *args) -{ - unsigned int mode, res; - - if (!PyArg_ParseTuple(args, "I", &mode)) - return NULL; - res = SetErrorMode(mode); - return PyLong_FromUnsignedLong(res); -} - - -/* List of functions exported by this module */ -static struct PyMethodDef msvcrt_functions[] = { - {"heapmin", msvcrt_heapmin, METH_VARARGS, heapmin_doc}, - {"locking", msvcrt_locking, METH_VARARGS, locking_doc}, - {"setmode", msvcrt_setmode, METH_VARARGS, setmode_doc}, - {"open_osfhandle", msvcrt_open_osfhandle, METH_VARARGS, open_osfhandle_doc}, - {"get_osfhandle", msvcrt_get_osfhandle, METH_VARARGS, get_osfhandle_doc}, - {"kbhit", msvcrt_kbhit, METH_VARARGS, kbhit_doc}, - {"getch", msvcrt_getch, METH_VARARGS, getch_doc}, - {"getche", msvcrt_getche, METH_VARARGS, getche_doc}, - {"putch", msvcrt_putch, METH_VARARGS, putch_doc}, - {"ungetch", msvcrt_ungetch, METH_VARARGS, ungetch_doc}, - {"SetErrorMode", seterrormode, METH_VARARGS}, -#ifdef _DEBUG - {"CrtSetReportFile", msvcrt_setreportfile, METH_VARARGS}, - {"CrtSetReportMode", msvcrt_setreportmode, METH_VARARGS}, - {"set_error_mode", msvcrt_seterrormode, METH_VARARGS}, -#endif -#ifdef _WCONIO_DEFINED - {"getwch", msvcrt_getwch, METH_VARARGS, getwch_doc}, - {"getwche", msvcrt_getwche, METH_VARARGS, getwche_doc}, - {"putwch", msvcrt_putwch, METH_VARARGS, putwch_doc}, - {"ungetwch", msvcrt_ungetwch, METH_VARARGS, ungetwch_doc}, -#endif - {NULL, NULL} -}; - - -static struct PyModuleDef msvcrtmodule = { - PyModuleDef_HEAD_INIT, - "msvcrt", - NULL, - -1, - msvcrt_functions, - NULL, - NULL, - NULL, - NULL -}; - PyMODINIT_FUNC PyInit_msvcrt(void) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 08:32:28 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 06:32:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320172=3A_Convert_?= =?utf-8?q?the_=5Fwinapi_module_to_Argument_Clinic=2E?= Message-ID: <20150513063228.11948.61060@psf.io> https://hg.python.org/cpython/rev/4cf37a50d91a changeset: 96009:4cf37a50d91a user: Zachary Ware date: Wed May 13 01:22:54 2015 -0500 summary: Issue #20172: Convert the _winapi module to Argument Clinic. files: Modules/_winapi.c | 837 ++++++++++++----------- Modules/clinic/_winapi.c.h | 851 +++++++++++++++++++++++++ 2 files changed, 1292 insertions(+), 396 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -58,8 +58,6 @@ #define F_HANDLE F_POINTER #define F_DWORD "k" -#define F_BOOL "i" -#define F_UINT "I" #define T_HANDLE T_POINTER @@ -147,17 +145,68 @@ PyObject_Del(self); } +/*[clinic input] +module _winapi +class _winapi.Overlapped "OverlappedObject *" "&OverlappedType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/ + +/*[python input] +def create_converter(type_, format_unit): + name = type_ + '_converter' + # registered upon creation by CConverter's metaclass + type(name, (CConverter,), {'type': type_, 'format_unit': format_unit}) + +# format unit differs between platforms for these +create_converter('HANDLE', '" F_HANDLE "') +create_converter('HMODULE', '" F_HANDLE "') +create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "') + +create_converter('BOOL', 'i') # F_BOOL used previously (always 'i') +create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter) +create_converter('LPCTSTR', 's') +create_converter('LPWSTR', 'u') +create_converter('UINT', 'I') # F_UINT used previously (always 'I') + +class HANDLE_return_converter(CReturnConverter): + type = 'HANDLE' + + def render(self, function, data): + self.declare(data) + self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data) + data.return_conversion.append( + 'if (_return_value == NULL)\n Py_RETURN_NONE;\n') + data.return_conversion.append( + 'return_value = HANDLE_TO_PYNUM(_return_value);\n') + +class DWORD_return_converter(CReturnConverter): + type = 'DWORD' + + def render(self, function, data): + self.declare(data) + self.err_occurred_if("_return_value == DWORD_MAX", data) + data.return_conversion.append( + 'return_value = Py_BuildValue("k", _return_value);\n') +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=374076979596ebba]*/ + +#include "clinic/_winapi.c.h" + +/*[clinic input] +_winapi.Overlapped.GetOverlappedResult + + wait: bool + / +[clinic start generated code]*/ + static PyObject * -overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj) +_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait) +/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/ { - int wait; BOOL res; DWORD transferred = 0; DWORD err; - wait = PyObject_IsTrue(waitobj); - if (wait < 0) - return NULL; Py_BEGIN_ALLOW_THREADS res = GetOverlappedResult(self->handle, &self->overlapped, &transferred, wait != 0); @@ -186,8 +235,13 @@ return Py_BuildValue("II", (unsigned) transferred, (unsigned) err); } +/*[clinic input] +_winapi.Overlapped.getbuffer +[clinic start generated code]*/ + static PyObject * -overlapped_getbuffer(OverlappedObject *self) +_winapi_Overlapped_getbuffer_impl(OverlappedObject *self) +/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/ { PyObject *res; if (!self->completed) { @@ -201,8 +255,13 @@ return res; } +/*[clinic input] +_winapi.Overlapped.cancel +[clinic start generated code]*/ + static PyObject * -overlapped_cancel(OverlappedObject *self) +_winapi_Overlapped_cancel_impl(OverlappedObject *self) +/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/ { BOOL res = TRUE; @@ -223,10 +282,9 @@ } static PyMethodDef overlapped_methods[] = { - {"GetOverlappedResult", (PyCFunction) overlapped_GetOverlappedResult, - METH_O, NULL}, - {"getbuffer", (PyCFunction) overlapped_getbuffer, METH_NOARGS, NULL}, - {"cancel", (PyCFunction) overlapped_cancel, METH_NOARGS, NULL}, + _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF + _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF + _WINAPI_OVERLAPPED_CANCEL_METHODDEF {NULL} }; @@ -300,22 +358,23 @@ /* -------------------------------------------------------------------- */ /* windows API functions */ -PyDoc_STRVAR(CloseHandle_doc, -"CloseHandle(handle) -> None\n\ -\n\ -Close handle."); +/*[clinic input] +_winapi.CloseHandle + + handle: HANDLE + / + +Close handle. +[clinic start generated code]*/ static PyObject * -winapi_CloseHandle(PyObject *self, PyObject *args) +_winapi_CloseHandle_impl(PyModuleDef *module, HANDLE handle) +/*[clinic end generated code: output=0548595c71cb4bf7 input=7f0e4ac36e0352b8]*/ { - HANDLE hObject; BOOL success; - if (!PyArg_ParseTuple(args, F_HANDLE ":CloseHandle", &hObject)) - return NULL; - Py_BEGIN_ALLOW_THREADS - success = CloseHandle(hObject); + success = CloseHandle(handle); Py_END_ALLOW_THREADS if (!success) @@ -324,28 +383,28 @@ Py_RETURN_NONE; } +/*[clinic input] +_winapi.ConnectNamedPipe + + handle: HANDLE + overlapped as use_overlapped: int(c_default='0') = False +[clinic start generated code]*/ + static PyObject * -winapi_ConnectNamedPipe(PyObject *self, PyObject *args, PyObject *kwds) +_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, int use_overlapped) +/*[clinic end generated code: output=d9a64e59c27e10f6 input=edc83da007ebf3be]*/ { - HANDLE hNamedPipe; - int use_overlapped = 0; BOOL success; OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "overlapped", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "|" F_BOOL, kwlist, - &hNamedPipe, &use_overlapped)) - return NULL; if (use_overlapped) { - overlapped = new_overlapped(hNamedPipe); + overlapped = new_overlapped(handle); if (!overlapped) return NULL; } Py_BEGIN_ALLOW_THREADS - success = ConnectNamedPipe(hNamedPipe, + success = ConnectNamedPipe(handle, overlapped ? &overlapped->overlapped : NULL); Py_END_ALLOW_THREADS @@ -369,45 +428,50 @@ Py_RETURN_NONE; } -static PyObject * -winapi_CreateFile(PyObject *self, PyObject *args) +/*[clinic input] +_winapi.CreateFile -> HANDLE + + file_name: LPCTSTR + desired_access: DWORD + share_mode: DWORD + security_attributes: LPSECURITY_ATTRIBUTES + creation_disposition: DWORD + flags_and_attributes: DWORD + template_file: HANDLE + / +[clinic start generated code]*/ + +static HANDLE +_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, DWORD desired_access, DWORD share_mode, LPSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD flags_and_attributes, HANDLE template_file) +/*[clinic end generated code: output=f8649129a4959288 input=6423c3e40372dbd5]*/ { - LPCTSTR lpFileName; - DWORD dwDesiredAccess; - DWORD dwShareMode; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes; - HANDLE hTemplateFile; HANDLE handle; - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER - F_DWORD F_DWORD F_HANDLE, - &lpFileName, &dwDesiredAccess, &dwShareMode, - &lpSecurityAttributes, &dwCreationDisposition, - &dwFlagsAndAttributes, &hTemplateFile)) - return NULL; - Py_BEGIN_ALLOW_THREADS - handle = CreateFile(lpFileName, dwDesiredAccess, - dwShareMode, lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile); + handle = CreateFile(file_name, desired_access, + share_mode, security_attributes, + creation_disposition, + flags_and_attributes, template_file); Py_END_ALLOW_THREADS if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); + PyErr_SetFromWindowsErr(0); - return Py_BuildValue(F_HANDLE, handle); + return handle; } +/*[clinic input] +_winapi.CreateJunction + + src_path: LPWSTR + dst_path: LPWSTR + / +[clinic start generated code]*/ + static PyObject * -winapi_CreateJunction(PyObject *self, PyObject *args) +_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, LPWSTR dst_path) +/*[clinic end generated code: output=df22af7be7045584 input=8cd1f9964b6e3d36]*/ { - /* Input arguments */ - LPWSTR src_path = NULL; - LPWSTR dst_path = NULL; - /* Privilege adjustment */ HANDLE token = NULL; TOKEN_PRIVILEGES tp; @@ -422,9 +486,6 @@ HANDLE junction = NULL; DWORD ret = 0; - if (!PyArg_ParseTuple(args, "uu", &src_path, &dst_path)) - return NULL; - if (src_path == NULL || dst_path == NULL) return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER); @@ -535,62 +596,60 @@ Py_RETURN_NONE; } -static PyObject * -winapi_CreateNamedPipe(PyObject *self, PyObject *args) +/*[clinic input] +_winapi.CreateNamedPipe -> HANDLE + + name: LPCTSTR + open_mode: DWORD + pipe_mode: DWORD + max_instances: DWORD + out_buffer_size: DWORD + in_buffer_size: DWORD + default_timeout: DWORD + security_attributes: LPSECURITY_ATTRIBUTES + / +[clinic start generated code]*/ + +static HANDLE +_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD open_mode, DWORD pipe_mode, DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, LPSECURITY_ATTRIBUTES security_attributes) +/*[clinic end generated code: output=711e231639c25c24 input=5a73530b84d8bc37]*/ { - LPCTSTR lpName; - DWORD dwOpenMode; - DWORD dwPipeMode; - DWORD nMaxInstances; - DWORD nOutBufferSize; - DWORD nInBufferSize; - DWORD nDefaultTimeOut; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; HANDLE handle; - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD - F_DWORD F_DWORD F_DWORD F_POINTER, - &lpName, &dwOpenMode, &dwPipeMode, - &nMaxInstances, &nOutBufferSize, - &nInBufferSize, &nDefaultTimeOut, - &lpSecurityAttributes)) - return NULL; - Py_BEGIN_ALLOW_THREADS - handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, - nMaxInstances, nOutBufferSize, - nInBufferSize, nDefaultTimeOut, - lpSecurityAttributes); + handle = CreateNamedPipe(name, open_mode, pipe_mode, + max_instances, out_buffer_size, + in_buffer_size, default_timeout, + security_attributes); Py_END_ALLOW_THREADS if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); + PyErr_SetFromWindowsErr(0); - return Py_BuildValue(F_HANDLE, handle); + return handle; } -PyDoc_STRVAR(CreatePipe_doc, -"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\ -\n\ -Create an anonymous pipe, and return handles to the read and\n\ -write ends of the pipe.\n\ -\n\ -pipe_attrs is ignored internally and can be None."); +/*[clinic input] +_winapi.CreatePipe + + pipe_attrs: object + Ignored internally, can be None. + size: DWORD + / + +Create an anonymous pipe. + +Returns a 2-tuple of handles, to the read and write ends of the pipe. +[clinic start generated code]*/ static PyObject * -winapi_CreatePipe(PyObject* self, PyObject* args) +_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, DWORD size) +/*[clinic end generated code: output=ed09baf1d43086df input=c4f2cfa56ef68d90]*/ { HANDLE read_pipe; HANDLE write_pipe; BOOL result; - PyObject* pipe_attributes; /* ignored */ - DWORD size; - - if (! PyArg_ParseTuple(args, "O" F_DWORD ":CreatePipe", - &pipe_attributes, &size)) - return NULL; - Py_BEGIN_ALLOW_THREADS result = CreatePipe(&read_pipe, &write_pipe, NULL, size); Py_END_ALLOW_THREADS @@ -721,20 +780,31 @@ return NULL; } -PyDoc_STRVAR(CreateProcess_doc, -"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\ - inherit, flags, env_mapping, curdir,\n\ - startup_info) -> (proc_handle, thread_handle,\n\ - pid, tid)\n\ -\n\ -Create a new process and its primary thread. The return\n\ -value is a tuple of the process handle, thread handle,\n\ -process ID, and thread ID.\n\ -\n\ -proc_attrs and thread_attrs are ignored internally and can be None."); +/*[clinic input] +_winapi.CreateProcess + + application_name: Py_UNICODE(nullable=True) + command_line: Py_UNICODE(nullable=True) + proc_attrs: object + Ignored internally, can be None. + thread_attrs: object + Ignored internally, can be None. + inherit_handles: BOOL + creation_flags: DWORD + env_mapping: object + current_directory: Py_UNICODE(nullable=True) + startup_info: object + / + +Create a new process and its primary thread. + +The return value is a tuple of the process handle, thread handle, +process ID, and thread ID. +[clinic start generated code]*/ static PyObject * -winapi_CreateProcess(PyObject* self, PyObject* args) +_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, Py_UNICODE *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, Py_UNICODE *current_directory, PyObject *startup_info) +/*[clinic end generated code: output=c279c1271b4c45cf input=6667ea0bc7036472]*/ { BOOL result; PROCESS_INFORMATION pi; @@ -742,28 +812,6 @@ PyObject* environment; wchar_t *wenvironment; - wchar_t* application_name; - wchar_t* command_line; - PyObject* process_attributes; /* ignored */ - PyObject* thread_attributes; /* ignored */ - BOOL inherit_handles; - DWORD creation_flags; - PyObject* env_mapping; - wchar_t* current_directory; - PyObject* startup_info; - - if (! PyArg_ParseTuple(args, "ZZOO" F_BOOL F_DWORD "OZO:CreateProcess", - &application_name, - &command_line, - &process_attributes, - &thread_attributes, - &inherit_handles, - &creation_flags, - &env_mapping, - ¤t_directory, - &startup_info)) - return NULL; - ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); @@ -817,41 +865,31 @@ pi.dwThreadId); } -PyDoc_STRVAR(DuplicateHandle_doc, -"DuplicateHandle(source_proc_handle, source_handle,\n\ - target_proc_handle, target_handle, access,\n\ - inherit[, options]) -> handle\n\ -\n\ -Return a duplicate handle object.\n\ -\n\ -The duplicate handle refers to the same object as the original\n\ -handle. Therefore, any changes to the object are reflected\n\ -through both handles."); +/*[clinic input] +_winapi.DuplicateHandle -> HANDLE -static PyObject * -winapi_DuplicateHandle(PyObject* self, PyObject* args) + source_process_handle: HANDLE + source_handle: HANDLE + target_process_handle: HANDLE + desired_access: DWORD + inherit_handle: BOOL + options: DWORD = 0 + / + +Return a duplicate handle object. + +The duplicate handle refers to the same object as the original +handle. Therefore, any changes to the object are reflected +through both handles. +[clinic start generated code]*/ + +static HANDLE +_winapi_DuplicateHandle_impl(PyModuleDef *module, HANDLE source_process_handle, HANDLE source_handle, HANDLE target_process_handle, DWORD desired_access, BOOL inherit_handle, DWORD options) +/*[clinic end generated code: output=24a7836ca4d94aba input=b933e3f2356a8c12]*/ { HANDLE target_handle; BOOL result; - HANDLE source_process_handle; - HANDLE source_handle; - HANDLE target_process_handle; - DWORD desired_access; - BOOL inherit_handle; - DWORD options = 0; - - if (! PyArg_ParseTuple(args, - F_HANDLE F_HANDLE F_HANDLE F_DWORD F_BOOL F_DWORD - ":DuplicateHandle", - &source_process_handle, - &source_handle, - &target_process_handle, - &desired_access, - &inherit_handle, - &options)) - return NULL; - Py_BEGIN_ALLOW_THREADS result = DuplicateHandle( source_process_handle, @@ -864,98 +902,111 @@ ); Py_END_ALLOW_THREADS - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); + if (! result) { + PyErr_SetFromWindowsErr(GetLastError()); + return INVALID_HANDLE_VALUE; + } - return HANDLE_TO_PYNUM(target_handle); + return target_handle; } +/*[clinic input] +_winapi.ExitProcess + + ExitCode: UINT + / + +[clinic start generated code]*/ + static PyObject * -winapi_ExitProcess(PyObject *self, PyObject *args) +_winapi_ExitProcess_impl(PyModuleDef *module, UINT ExitCode) +/*[clinic end generated code: output=25f3b499c24cedc8 input=4f05466a9406c558]*/ { - UINT uExitCode; - - if (!PyArg_ParseTuple(args, F_UINT, &uExitCode)) - return NULL; - #if defined(Py_DEBUG) SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT| SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); #endif - ExitProcess(uExitCode); + ExitProcess(ExitCode); return NULL; } -PyDoc_STRVAR(GetCurrentProcess_doc, -"GetCurrentProcess() -> handle\n\ -\n\ -Return a handle object for the current process."); +/*[clinic input] +_winapi.GetCurrentProcess -> HANDLE -static PyObject * -winapi_GetCurrentProcess(PyObject* self, PyObject* args) +Return a handle object for the current process. +[clinic start generated code]*/ + +static HANDLE +_winapi_GetCurrentProcess_impl(PyModuleDef *module) +/*[clinic end generated code: output=be29ac3ad5f8291e input=b213403fd4b96b41]*/ { - if (! PyArg_ParseTuple(args, ":GetCurrentProcess")) - return NULL; - - return HANDLE_TO_PYNUM(GetCurrentProcess()); + return GetCurrentProcess(); } -PyDoc_STRVAR(GetExitCodeProcess_doc, -"GetExitCodeProcess(handle) -> Exit code\n\ -\n\ -Return the termination status of the specified process."); +/*[clinic input] +_winapi.GetExitCodeProcess -> DWORD -static PyObject * -winapi_GetExitCodeProcess(PyObject* self, PyObject* args) + process: HANDLE + / + +Return the termination status of the specified process. +[clinic start generated code]*/ + +static DWORD +_winapi_GetExitCodeProcess_impl(PyModuleDef *module, HANDLE process) +/*[clinic end generated code: output=0b10f0848a410f65 input=61b6bfc7dc2ee374]*/ { DWORD exit_code; BOOL result; - HANDLE process; - if (! PyArg_ParseTuple(args, F_HANDLE ":GetExitCodeProcess", &process)) - return NULL; - result = GetExitCodeProcess(process, &exit_code); - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); + if (! result) { + PyErr_SetFromWindowsErr(GetLastError()); + exit_code = DWORD_MAX; + } - return PyLong_FromUnsignedLong(exit_code); + return exit_code; } -static PyObject * -winapi_GetLastError(PyObject *self, PyObject *args) +/*[clinic input] +_winapi.GetLastError -> DWORD +[clinic start generated code]*/ + +static DWORD +_winapi_GetLastError_impl(PyModuleDef *module) +/*[clinic end generated code: output=0ea00d8e67bdd056 input=62d47fb9bce038ba]*/ { - return Py_BuildValue(F_DWORD, GetLastError()); + return GetLastError(); } -PyDoc_STRVAR(GetModuleFileName_doc, -"GetModuleFileName(module) -> path\n\ -\n\ -Return the fully-qualified path for the file that contains\n\ -the specified module. The module must have been loaded by the\n\ -current process.\n\ -\n\ -The module parameter should be a handle to the loaded module\n\ -whose path is being requested. If this parameter is 0, \n\ -GetModuleFileName retrieves the path of the executable file\n\ -of the current process."); +/*[clinic input] +_winapi.GetModuleFileName + + module_handle: HMODULE + / + +Return the fully-qualified path for the file that contains module. + +The module must have been loaded by the current process. + +The module parameter should be a handle to the loaded module +whose path is being requested. If this parameter is 0, +GetModuleFileName retrieves the path of the executable file +of the current process. +[clinic start generated code]*/ static PyObject * -winapi_GetModuleFileName(PyObject* self, PyObject* args) +_winapi_GetModuleFileName_impl(PyModuleDef *module, HMODULE module_handle) +/*[clinic end generated code: output=90063dc63bdbfa18 input=6d66ff7deca5d11f]*/ { BOOL result; - HMODULE module; WCHAR filename[MAX_PATH]; - if (! PyArg_ParseTuple(args, F_HANDLE ":GetModuleFileName", - &module)) - return NULL; - - result = GetModuleFileNameW(module, filename, MAX_PATH); + result = GetModuleFileNameW(module_handle, filename, MAX_PATH); filename[MAX_PATH-1] = '\0'; if (! result) @@ -964,91 +1015,95 @@ return PyUnicode_FromWideChar(filename, wcslen(filename)); } -PyDoc_STRVAR(GetStdHandle_doc, -"GetStdHandle(handle) -> integer\n\ -\n\ -Return a handle to the specified standard device\n\ -(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\ -The integer associated with the handle object is returned."); +/*[clinic input] +_winapi.GetStdHandle -> HANDLE -static PyObject * -winapi_GetStdHandle(PyObject* self, PyObject* args) + std_handle: DWORD + One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE. + / + +Return a handle to the specified standard device. + +The integer associated with the handle object is returned. +[clinic start generated code]*/ + +static HANDLE +_winapi_GetStdHandle_impl(PyModuleDef *module, DWORD std_handle) +/*[clinic end generated code: output=5f5ca28b28c6fad2 input=07016b06a2fc8826]*/ { HANDLE handle; - DWORD std_handle; - - if (! PyArg_ParseTuple(args, F_DWORD ":GetStdHandle", &std_handle)) - return NULL; Py_BEGIN_ALLOW_THREADS handle = GetStdHandle(std_handle); Py_END_ALLOW_THREADS if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); + PyErr_SetFromWindowsErr(GetLastError()); - if (! handle) { - Py_INCREF(Py_None); - return Py_None; - } - - /* note: returns integer, not handle object */ - return HANDLE_TO_PYNUM(handle); + return handle; } -PyDoc_STRVAR(GetVersion_doc, -"GetVersion() -> version\n\ -\n\ -Return the version number of the current operating system."); +/*[clinic input] +_winapi.GetVersion -> long +Return the version number of the current operating system. +[clinic start generated code]*/ + +static long +_winapi_GetVersion_impl(PyModuleDef *module) +/*[clinic end generated code: output=95a2f8ad3b948ca8 input=e21dff8d0baeded2]*/ /* Disable deprecation warnings about GetVersionEx as the result is being passed straight through to the caller, who is responsible for using it correctly. */ #pragma warning(push) #pragma warning(disable:4996) -static PyObject * -winapi_GetVersion(PyObject* self, PyObject* args) { - if (! PyArg_ParseTuple(args, ":GetVersion")) - return NULL; - - return PyLong_FromUnsignedLong(GetVersion()); + return GetVersion(); } #pragma warning(pop) -static PyObject * -winapi_OpenProcess(PyObject *self, PyObject *args) +/*[clinic input] +_winapi.OpenProcess -> HANDLE + + desired_access: DWORD + inherit_handle: BOOL + process_id: DWORD + / +[clinic start generated code]*/ + +static HANDLE +_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id) +/*[clinic end generated code: output=2a7be5336f16f63c input=ec98c4cf4ea2ec36]*/ { - DWORD dwDesiredAccess; - BOOL bInheritHandle; - DWORD dwProcessId; HANDLE handle; - if (!PyArg_ParseTuple(args, F_DWORD F_BOOL F_DWORD, - &dwDesiredAccess, &bInheritHandle, &dwProcessId)) - return NULL; + handle = OpenProcess(desired_access, inherit_handle, process_id); + if (handle == NULL) { + PyErr_SetFromWindowsErr(0); + handle = INVALID_HANDLE_VALUE; + } - handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); - if (handle == NULL) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); + return handle; } +/*[clinic input] +_winapi.PeekNamedPipe + + handle: HANDLE + size: int = 0 + / +[clinic start generated code]*/ + static PyObject * -winapi_PeekNamedPipe(PyObject *self, PyObject *args) +_winapi_PeekNamedPipe_impl(PyModuleDef *module, HANDLE handle, int size) +/*[clinic end generated code: output=e6c908e2fb63c798 input=c7aa53bfbce69d70]*/ { - HANDLE handle; - int size = 0; PyObject *buf = NULL; DWORD nread, navail, nleft; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE "|i:PeekNamedPipe" , &handle, &size)) - return NULL; - if (size < 0) { PyErr_SetString(PyExc_ValueError, "negative size"); return NULL; @@ -1081,23 +1136,23 @@ } } +/*[clinic input] +_winapi.ReadFile + + handle: HANDLE + size: int + overlapped as use_overlapped: int(c_default='0') = False +[clinic start generated code]*/ + static PyObject * -winapi_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) +_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, int use_overlapped) +/*[clinic end generated code: output=5a087be0ff44479a input=8dd810194e86ac7d]*/ { - HANDLE handle; - int size; DWORD nread; PyObject *buf; BOOL ret; - int use_overlapped = 0; DWORD err; OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "size", "overlapped", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "i|i:ReadFile", kwlist, - &handle, &size, &use_overlapped)) - return NULL; buf = PyBytes_FromStringAndSize(NULL, size); if (!buf) @@ -1140,18 +1195,24 @@ return Py_BuildValue("NI", buf, err); } +/*[clinic input] +_winapi.SetNamedPipeHandleState + + named_pipe: HANDLE + mode: object + max_collection_count: object + collect_data_timeout: object + / +[clinic start generated code]*/ + static PyObject * -winapi_SetNamedPipeHandleState(PyObject *self, PyObject *args) +_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, PyObject *mode, PyObject *max_collection_count, PyObject *collect_data_timeout) +/*[clinic end generated code: output=327efd18ff0c30ec input=9142d72163d0faa6]*/ { - HANDLE hNamedPipe; - PyObject *oArgs[3]; + PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout}; DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; int i; - if (!PyArg_ParseTuple(args, F_HANDLE "OOO", - &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) - return NULL; - PyErr_Clear(); for (i = 0 ; i < 3 ; i++) { @@ -1163,49 +1224,53 @@ } } - if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) + if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2])) return PyErr_SetFromWindowsErr(0); Py_RETURN_NONE; } -PyDoc_STRVAR(TerminateProcess_doc, -"TerminateProcess(handle, exit_code) -> None\n\ -\n\ -Terminate the specified process and all of its threads."); + +/*[clinic input] +_winapi.TerminateProcess + + handle: HANDLE + exit_code: UINT + / + +Terminate the specified process and all of its threads. +[clinic start generated code]*/ static PyObject * -winapi_TerminateProcess(PyObject* self, PyObject* args) +_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, UINT exit_code) +/*[clinic end generated code: output=1559f0f6500c2283 input=d6bc0aa1ee3bb4df]*/ { BOOL result; - HANDLE process; - UINT exit_code; - if (! PyArg_ParseTuple(args, F_HANDLE F_UINT ":TerminateProcess", - &process, &exit_code)) - return NULL; - - result = TerminateProcess(process, exit_code); + result = TerminateProcess(handle, exit_code); if (! result) return PyErr_SetFromWindowsErr(GetLastError()); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } +/*[clinic input] +_winapi.WaitNamedPipe + + name: LPCTSTR + timeout: DWORD + / +[clinic start generated code]*/ + static PyObject * -winapi_WaitNamedPipe(PyObject *self, PyObject *args) +_winapi_WaitNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD timeout) +/*[clinic end generated code: output=5bca5e02f448c9d7 input=36fc781291b1862c]*/ { - LPCTSTR lpNamedPipeName; - DWORD nTimeOut; BOOL success; - if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut)) - return NULL; - Py_BEGIN_ALLOW_THREADS - success = WaitNamedPipe(lpNamedPipeName, nTimeOut); + success = WaitNamedPipe(name, timeout); Py_END_ALLOW_THREADS if (!success) @@ -1214,21 +1279,23 @@ Py_RETURN_NONE; } +/*[clinic input] +_winapi.WaitForMultipleObjects + + handle_seq: object + wait_flag: BOOL + milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE + / +[clinic start generated code]*/ + static PyObject * -winapi_WaitForMultipleObjects(PyObject* self, PyObject* args) +_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds) +/*[clinic end generated code: output=e3efee6b505dd48e input=36f76ca057cd28a0]*/ { DWORD result; - PyObject *handle_seq; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; HANDLE sigint_event = NULL; Py_ssize_t nhandles, i; - BOOL wait_flag; - DWORD milliseconds = INFINITE; - - if (!PyArg_ParseTuple(args, "O" F_BOOL "|" F_DWORD - ":WaitForMultipleObjects", - &handle_seq, &wait_flag, &milliseconds)) - return NULL; if (!PySequence_Check(handle_seq)) { PyErr_Format(PyExc_TypeError, @@ -1282,53 +1349,55 @@ return PyLong_FromLong((int) result); } -PyDoc_STRVAR(WaitForSingleObject_doc, -"WaitForSingleObject(handle, timeout) -> result\n\ -\n\ -Wait until the specified object is in the signaled state or\n\ -the time-out interval elapses. The timeout value is specified\n\ -in milliseconds."); +/*[clinic input] +_winapi.WaitForSingleObject -> long -static PyObject * -winapi_WaitForSingleObject(PyObject* self, PyObject* args) + handle: HANDLE + milliseconds: DWORD + / + +Wait for a single object. + +Wait until the specified object is in the signaled state or +the time-out interval elapses. The timeout value is specified +in milliseconds. +[clinic start generated code]*/ + +static long +_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, DWORD milliseconds) +/*[clinic end generated code: output=0c75bcc6eec6b973 input=443d1ab076edc7b1]*/ { DWORD result; - HANDLE handle; - DWORD milliseconds; - if (! PyArg_ParseTuple(args, F_HANDLE F_DWORD ":WaitForSingleObject", - &handle, - &milliseconds)) - return NULL; - Py_BEGIN_ALLOW_THREADS result = WaitForSingleObject(handle, milliseconds); Py_END_ALLOW_THREADS - if (result == WAIT_FAILED) - return PyErr_SetFromWindowsErr(GetLastError()); + if (result == WAIT_FAILED) { + PyErr_SetFromWindowsErr(GetLastError()); + return -1; + } - return PyLong_FromUnsignedLong(result); + return result; } +/*[clinic input] +_winapi.WriteFile + + handle: HANDLE + buffer: object + overlapped as use_overlapped: int(c_default='0') = False +[clinic start generated code]*/ + static PyObject * -winapi_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) +_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, int use_overlapped) +/*[clinic end generated code: output=37bd88e293079b2c input=51846a5af52053fd]*/ { - HANDLE handle; Py_buffer _buf, *buf; - PyObject *bufobj; DWORD len, written; BOOL ret; - int use_overlapped = 0; DWORD err; OverlappedObject *overlapped = NULL; - static char *kwlist[] = {"handle", "buffer", "overlapped", NULL}; - - /* First get handle and use_overlapped to know which Py_buffer to use */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, - F_HANDLE "O|i:WriteFile", kwlist, - &handle, &bufobj, &use_overlapped)) - return NULL; if (use_overlapped) { overlapped = new_overlapped(handle); @@ -1339,7 +1408,7 @@ else buf = &_buf; - if (!PyArg_Parse(bufobj, "y*", buf)) { + if (!PyArg_Parse(buffer, "y*", buf)) { Py_XDECREF(overlapped); return NULL; } @@ -1372,54 +1441,30 @@ static PyMethodDef winapi_functions[] = { - {"CloseHandle", winapi_CloseHandle, METH_VARARGS, - CloseHandle_doc}, - {"ConnectNamedPipe", (PyCFunction)winapi_ConnectNamedPipe, - METH_VARARGS | METH_KEYWORDS, ""}, - {"CreateFile", winapi_CreateFile, METH_VARARGS, - ""}, - {"CreateJunction", winapi_CreateJunction, METH_VARARGS, - ""}, - {"CreateNamedPipe", winapi_CreateNamedPipe, METH_VARARGS, - ""}, - {"CreatePipe", winapi_CreatePipe, METH_VARARGS, - CreatePipe_doc}, - {"CreateProcess", winapi_CreateProcess, METH_VARARGS, - CreateProcess_doc}, - {"DuplicateHandle", winapi_DuplicateHandle, METH_VARARGS, - DuplicateHandle_doc}, - {"ExitProcess", winapi_ExitProcess, METH_VARARGS, - ""}, - {"GetCurrentProcess", winapi_GetCurrentProcess, METH_VARARGS, - GetCurrentProcess_doc}, - {"GetExitCodeProcess", winapi_GetExitCodeProcess, METH_VARARGS, - GetExitCodeProcess_doc}, - {"GetLastError", winapi_GetLastError, METH_NOARGS, - GetCurrentProcess_doc}, - {"GetModuleFileName", winapi_GetModuleFileName, METH_VARARGS, - GetModuleFileName_doc}, - {"GetStdHandle", winapi_GetStdHandle, METH_VARARGS, - GetStdHandle_doc}, - {"GetVersion", winapi_GetVersion, METH_VARARGS, - GetVersion_doc}, - {"OpenProcess", winapi_OpenProcess, METH_VARARGS, - ""}, - {"PeekNamedPipe", winapi_PeekNamedPipe, METH_VARARGS, - ""}, - {"ReadFile", (PyCFunction)winapi_ReadFile, METH_VARARGS | METH_KEYWORDS, - ""}, - {"SetNamedPipeHandleState", winapi_SetNamedPipeHandleState, METH_VARARGS, - ""}, - {"TerminateProcess", winapi_TerminateProcess, METH_VARARGS, - TerminateProcess_doc}, - {"WaitNamedPipe", winapi_WaitNamedPipe, METH_VARARGS, - ""}, - {"WaitForMultipleObjects", winapi_WaitForMultipleObjects, METH_VARARGS, - ""}, - {"WaitForSingleObject", winapi_WaitForSingleObject, METH_VARARGS, - WaitForSingleObject_doc}, - {"WriteFile", (PyCFunction)winapi_WriteFile, METH_VARARGS | METH_KEYWORDS, - ""}, + _WINAPI_CLOSEHANDLE_METHODDEF + _WINAPI_CONNECTNAMEDPIPE_METHODDEF + _WINAPI_CREATEFILE_METHODDEF + _WINAPI_CREATENAMEDPIPE_METHODDEF + _WINAPI_CREATEPIPE_METHODDEF + _WINAPI_CREATEPROCESS_METHODDEF + _WINAPI_CREATEJUNCTION_METHODDEF + _WINAPI_DUPLICATEHANDLE_METHODDEF + _WINAPI_EXITPROCESS_METHODDEF + _WINAPI_GETCURRENTPROCESS_METHODDEF + _WINAPI_GETEXITCODEPROCESS_METHODDEF + _WINAPI_GETLASTERROR_METHODDEF + _WINAPI_GETMODULEFILENAME_METHODDEF + _WINAPI_GETSTDHANDLE_METHODDEF + _WINAPI_GETVERSION_METHODDEF + _WINAPI_OPENPROCESS_METHODDEF + _WINAPI_PEEKNAMEDPIPE_METHODDEF + _WINAPI_READFILE_METHODDEF + _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF + _WINAPI_TERMINATEPROCESS_METHODDEF + _WINAPI_WAITNAMEDPIPE_METHODDEF + _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF + _WINAPI_WAITFORSINGLEOBJECT_METHODDEF + _WINAPI_WRITEFILE_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h new file mode 100644 --- /dev/null +++ b/Modules/clinic/_winapi.c.h @@ -0,0 +1,851 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_winapi_Overlapped_GetOverlappedResult__doc__, +"GetOverlappedResult($self, wait, /)\n" +"--\n" +"\n"); + +#define _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF \ + {"GetOverlappedResult", (PyCFunction)_winapi_Overlapped_GetOverlappedResult, METH_O, _winapi_Overlapped_GetOverlappedResult__doc__}, + +static PyObject * +_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait); + +static PyObject * +_winapi_Overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int wait; + + if (!PyArg_Parse(arg, + "p:GetOverlappedResult", + &wait)) + goto exit; + return_value = _winapi_Overlapped_GetOverlappedResult_impl(self, wait); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_Overlapped_getbuffer__doc__, +"getbuffer($self, /)\n" +"--\n" +"\n"); + +#define _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF \ + {"getbuffer", (PyCFunction)_winapi_Overlapped_getbuffer, METH_NOARGS, _winapi_Overlapped_getbuffer__doc__}, + +static PyObject * +_winapi_Overlapped_getbuffer_impl(OverlappedObject *self); + +static PyObject * +_winapi_Overlapped_getbuffer(OverlappedObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _winapi_Overlapped_getbuffer_impl(self); +} + +PyDoc_STRVAR(_winapi_Overlapped_cancel__doc__, +"cancel($self, /)\n" +"--\n" +"\n"); + +#define _WINAPI_OVERLAPPED_CANCEL_METHODDEF \ + {"cancel", (PyCFunction)_winapi_Overlapped_cancel, METH_NOARGS, _winapi_Overlapped_cancel__doc__}, + +static PyObject * +_winapi_Overlapped_cancel_impl(OverlappedObject *self); + +static PyObject * +_winapi_Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _winapi_Overlapped_cancel_impl(self); +} + +PyDoc_STRVAR(_winapi_CloseHandle__doc__, +"CloseHandle($module, handle, /)\n" +"--\n" +"\n" +"Close handle."); + +#define _WINAPI_CLOSEHANDLE_METHODDEF \ + {"CloseHandle", (PyCFunction)_winapi_CloseHandle, METH_O, _winapi_CloseHandle__doc__}, + +static PyObject * +_winapi_CloseHandle_impl(PyModuleDef *module, HANDLE handle); + +static PyObject * +_winapi_CloseHandle(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE handle; + + if (!PyArg_Parse(arg, + "" F_HANDLE ":CloseHandle", + &handle)) + goto exit; + return_value = _winapi_CloseHandle_impl(module, handle); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_ConnectNamedPipe__doc__, +"ConnectNamedPipe($module, /, handle, overlapped=False)\n" +"--\n" +"\n"); + +#define _WINAPI_CONNECTNAMEDPIPE_METHODDEF \ + {"ConnectNamedPipe", (PyCFunction)_winapi_ConnectNamedPipe, METH_VARARGS|METH_KEYWORDS, _winapi_ConnectNamedPipe__doc__}, + +static PyObject * +_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, int use_overlapped); + +static PyObject * +_winapi_ConnectNamedPipe(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"handle", "overlapped", NULL}; + HANDLE handle; + int use_overlapped = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "" F_HANDLE "|i:ConnectNamedPipe", _keywords, + &handle, &use_overlapped)) + goto exit; + return_value = _winapi_ConnectNamedPipe_impl(module, handle, use_overlapped); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_CreateFile__doc__, +"CreateFile($module, file_name, desired_access, share_mode,\n" +" security_attributes, creation_disposition,\n" +" flags_and_attributes, template_file, /)\n" +"--\n" +"\n"); + +#define _WINAPI_CREATEFILE_METHODDEF \ + {"CreateFile", (PyCFunction)_winapi_CreateFile, METH_VARARGS, _winapi_CreateFile__doc__}, + +static HANDLE +_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, DWORD desired_access, DWORD share_mode, LPSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD flags_and_attributes, HANDLE template_file); + +static PyObject * +_winapi_CreateFile(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + LPCTSTR file_name; + DWORD desired_access; + DWORD share_mode; + LPSECURITY_ATTRIBUTES security_attributes; + DWORD creation_disposition; + DWORD flags_and_attributes; + HANDLE template_file; + HANDLE _return_value; + + if (!PyArg_ParseTuple(args, + "skk" F_POINTER "kk" F_HANDLE ":CreateFile", + &file_name, &desired_access, &share_mode, &security_attributes, &creation_disposition, &flags_and_attributes, &template_file)) + goto exit; + _return_value = _winapi_CreateFile_impl(module, file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_CreateJunction__doc__, +"CreateJunction($module, src_path, dst_path, /)\n" +"--\n" +"\n"); + +#define _WINAPI_CREATEJUNCTION_METHODDEF \ + {"CreateJunction", (PyCFunction)_winapi_CreateJunction, METH_VARARGS, _winapi_CreateJunction__doc__}, + +static PyObject * +_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, LPWSTR dst_path); + +static PyObject * +_winapi_CreateJunction(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + LPWSTR src_path; + LPWSTR dst_path; + + if (!PyArg_ParseTuple(args, + "uu:CreateJunction", + &src_path, &dst_path)) + goto exit; + return_value = _winapi_CreateJunction_impl(module, src_path, dst_path); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_CreateNamedPipe__doc__, +"CreateNamedPipe($module, name, open_mode, pipe_mode, max_instances,\n" +" out_buffer_size, in_buffer_size, default_timeout,\n" +" security_attributes, /)\n" +"--\n" +"\n"); + +#define _WINAPI_CREATENAMEDPIPE_METHODDEF \ + {"CreateNamedPipe", (PyCFunction)_winapi_CreateNamedPipe, METH_VARARGS, _winapi_CreateNamedPipe__doc__}, + +static HANDLE +_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD open_mode, DWORD pipe_mode, DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, LPSECURITY_ATTRIBUTES security_attributes); + +static PyObject * +_winapi_CreateNamedPipe(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + LPCTSTR name; + DWORD open_mode; + DWORD pipe_mode; + DWORD max_instances; + DWORD out_buffer_size; + DWORD in_buffer_size; + DWORD default_timeout; + LPSECURITY_ATTRIBUTES security_attributes; + HANDLE _return_value; + + if (!PyArg_ParseTuple(args, + "skkkkkk" F_POINTER ":CreateNamedPipe", + &name, &open_mode, &pipe_mode, &max_instances, &out_buffer_size, &in_buffer_size, &default_timeout, &security_attributes)) + goto exit; + _return_value = _winapi_CreateNamedPipe_impl(module, name, open_mode, pipe_mode, max_instances, out_buffer_size, in_buffer_size, default_timeout, security_attributes); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_CreatePipe__doc__, +"CreatePipe($module, pipe_attrs, size, /)\n" +"--\n" +"\n" +"Create an anonymous pipe.\n" +"\n" +" pipe_attrs\n" +" Ignored internally, can be None.\n" +"\n" +"Returns a 2-tuple of handles, to the read and write ends of the pipe."); + +#define _WINAPI_CREATEPIPE_METHODDEF \ + {"CreatePipe", (PyCFunction)_winapi_CreatePipe, METH_VARARGS, _winapi_CreatePipe__doc__}, + +static PyObject * +_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, DWORD size); + +static PyObject * +_winapi_CreatePipe(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *pipe_attrs; + DWORD size; + + if (!PyArg_ParseTuple(args, + "Ok:CreatePipe", + &pipe_attrs, &size)) + goto exit; + return_value = _winapi_CreatePipe_impl(module, pipe_attrs, size); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_CreateProcess__doc__, +"CreateProcess($module, application_name, command_line, proc_attrs,\n" +" thread_attrs, inherit_handles, creation_flags,\n" +" env_mapping, current_directory, startup_info, /)\n" +"--\n" +"\n" +"Create a new process and its primary thread.\n" +"\n" +" proc_attrs\n" +" Ignored internally, can be None.\n" +" thread_attrs\n" +" Ignored internally, can be None.\n" +"\n" +"The return value is a tuple of the process handle, thread handle,\n" +"process ID, and thread ID."); + +#define _WINAPI_CREATEPROCESS_METHODDEF \ + {"CreateProcess", (PyCFunction)_winapi_CreateProcess, METH_VARARGS, _winapi_CreateProcess__doc__}, + +static PyObject * +_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, Py_UNICODE *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, Py_UNICODE *current_directory, PyObject *startup_info); + +static PyObject * +_winapi_CreateProcess(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_UNICODE *application_name; + Py_UNICODE *command_line; + PyObject *proc_attrs; + PyObject *thread_attrs; + BOOL inherit_handles; + DWORD creation_flags; + PyObject *env_mapping; + Py_UNICODE *current_directory; + PyObject *startup_info; + + if (!PyArg_ParseTuple(args, + "ZZOOikOZO:CreateProcess", + &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, ¤t_directory, &startup_info)) + goto exit; + return_value = _winapi_CreateProcess_impl(module, application_name, command_line, proc_attrs, thread_attrs, inherit_handles, creation_flags, env_mapping, current_directory, startup_info); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_DuplicateHandle__doc__, +"DuplicateHandle($module, source_process_handle, source_handle,\n" +" target_process_handle, desired_access, inherit_handle,\n" +" options=0, /)\n" +"--\n" +"\n" +"Return a duplicate handle object.\n" +"\n" +"The duplicate handle refers to the same object as the original\n" +"handle. Therefore, any changes to the object are reflected\n" +"through both handles."); + +#define _WINAPI_DUPLICATEHANDLE_METHODDEF \ + {"DuplicateHandle", (PyCFunction)_winapi_DuplicateHandle, METH_VARARGS, _winapi_DuplicateHandle__doc__}, + +static HANDLE +_winapi_DuplicateHandle_impl(PyModuleDef *module, HANDLE source_process_handle, HANDLE source_handle, HANDLE target_process_handle, DWORD desired_access, BOOL inherit_handle, DWORD options); + +static PyObject * +_winapi_DuplicateHandle(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HANDLE source_process_handle; + HANDLE source_handle; + HANDLE target_process_handle; + DWORD desired_access; + BOOL inherit_handle; + DWORD options = 0; + HANDLE _return_value; + + if (!PyArg_ParseTuple(args, + "" F_HANDLE "" F_HANDLE "" F_HANDLE "ki|k:DuplicateHandle", + &source_process_handle, &source_handle, &target_process_handle, &desired_access, &inherit_handle, &options)) + goto exit; + _return_value = _winapi_DuplicateHandle_impl(module, source_process_handle, source_handle, target_process_handle, desired_access, inherit_handle, options); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_ExitProcess__doc__, +"ExitProcess($module, ExitCode, /)\n" +"--\n" +"\n"); + +#define _WINAPI_EXITPROCESS_METHODDEF \ + {"ExitProcess", (PyCFunction)_winapi_ExitProcess, METH_O, _winapi_ExitProcess__doc__}, + +static PyObject * +_winapi_ExitProcess_impl(PyModuleDef *module, UINT ExitCode); + +static PyObject * +_winapi_ExitProcess(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + UINT ExitCode; + + if (!PyArg_Parse(arg, + "I:ExitProcess", + &ExitCode)) + goto exit; + return_value = _winapi_ExitProcess_impl(module, ExitCode); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetCurrentProcess__doc__, +"GetCurrentProcess($module, /)\n" +"--\n" +"\n" +"Return a handle object for the current process."); + +#define _WINAPI_GETCURRENTPROCESS_METHODDEF \ + {"GetCurrentProcess", (PyCFunction)_winapi_GetCurrentProcess, METH_NOARGS, _winapi_GetCurrentProcess__doc__}, + +static HANDLE +_winapi_GetCurrentProcess_impl(PyModuleDef *module); + +static PyObject * +_winapi_GetCurrentProcess(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + HANDLE _return_value; + + _return_value = _winapi_GetCurrentProcess_impl(module); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetExitCodeProcess__doc__, +"GetExitCodeProcess($module, process, /)\n" +"--\n" +"\n" +"Return the termination status of the specified process."); + +#define _WINAPI_GETEXITCODEPROCESS_METHODDEF \ + {"GetExitCodeProcess", (PyCFunction)_winapi_GetExitCodeProcess, METH_O, _winapi_GetExitCodeProcess__doc__}, + +static DWORD +_winapi_GetExitCodeProcess_impl(PyModuleDef *module, HANDLE process); + +static PyObject * +_winapi_GetExitCodeProcess(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE process; + DWORD _return_value; + + if (!PyArg_Parse(arg, + "" F_HANDLE ":GetExitCodeProcess", + &process)) + goto exit; + _return_value = _winapi_GetExitCodeProcess_impl(module, process); + if ((_return_value == DWORD_MAX) && PyErr_Occurred()) + goto exit; + return_value = Py_BuildValue("k", _return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetLastError__doc__, +"GetLastError($module, /)\n" +"--\n" +"\n"); + +#define _WINAPI_GETLASTERROR_METHODDEF \ + {"GetLastError", (PyCFunction)_winapi_GetLastError, METH_NOARGS, _winapi_GetLastError__doc__}, + +static DWORD +_winapi_GetLastError_impl(PyModuleDef *module); + +static PyObject * +_winapi_GetLastError(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + DWORD _return_value; + + _return_value = _winapi_GetLastError_impl(module); + if ((_return_value == DWORD_MAX) && PyErr_Occurred()) + goto exit; + return_value = Py_BuildValue("k", _return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetModuleFileName__doc__, +"GetModuleFileName($module, module_handle, /)\n" +"--\n" +"\n" +"Return the fully-qualified path for the file that contains module.\n" +"\n" +"The module must have been loaded by the current process.\n" +"\n" +"The module parameter should be a handle to the loaded module\n" +"whose path is being requested. If this parameter is 0,\n" +"GetModuleFileName retrieves the path of the executable file\n" +"of the current process."); + +#define _WINAPI_GETMODULEFILENAME_METHODDEF \ + {"GetModuleFileName", (PyCFunction)_winapi_GetModuleFileName, METH_O, _winapi_GetModuleFileName__doc__}, + +static PyObject * +_winapi_GetModuleFileName_impl(PyModuleDef *module, HMODULE module_handle); + +static PyObject * +_winapi_GetModuleFileName(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HMODULE module_handle; + + if (!PyArg_Parse(arg, + "" F_HANDLE ":GetModuleFileName", + &module_handle)) + goto exit; + return_value = _winapi_GetModuleFileName_impl(module, module_handle); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetStdHandle__doc__, +"GetStdHandle($module, std_handle, /)\n" +"--\n" +"\n" +"Return a handle to the specified standard device.\n" +"\n" +" std_handle\n" +" One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.\n" +"\n" +"The integer associated with the handle object is returned."); + +#define _WINAPI_GETSTDHANDLE_METHODDEF \ + {"GetStdHandle", (PyCFunction)_winapi_GetStdHandle, METH_O, _winapi_GetStdHandle__doc__}, + +static HANDLE +_winapi_GetStdHandle_impl(PyModuleDef *module, DWORD std_handle); + +static PyObject * +_winapi_GetStdHandle(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + DWORD std_handle; + HANDLE _return_value; + + if (!PyArg_Parse(arg, + "k:GetStdHandle", + &std_handle)) + goto exit; + _return_value = _winapi_GetStdHandle_impl(module, std_handle); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_GetVersion__doc__, +"GetVersion($module, /)\n" +"--\n" +"\n" +"Return the version number of the current operating system."); + +#define _WINAPI_GETVERSION_METHODDEF \ + {"GetVersion", (PyCFunction)_winapi_GetVersion, METH_NOARGS, _winapi_GetVersion__doc__}, + +static long +_winapi_GetVersion_impl(PyModuleDef *module); + +static PyObject * +_winapi_GetVersion(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + long _return_value; + + _return_value = _winapi_GetVersion_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_OpenProcess__doc__, +"OpenProcess($module, desired_access, inherit_handle, process_id, /)\n" +"--\n" +"\n"); + +#define _WINAPI_OPENPROCESS_METHODDEF \ + {"OpenProcess", (PyCFunction)_winapi_OpenProcess, METH_VARARGS, _winapi_OpenProcess__doc__}, + +static HANDLE +_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id); + +static PyObject * +_winapi_OpenProcess(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + DWORD desired_access; + BOOL inherit_handle; + DWORD process_id; + HANDLE _return_value; + + if (!PyArg_ParseTuple(args, + "kik:OpenProcess", + &desired_access, &inherit_handle, &process_id)) + goto exit; + _return_value = _winapi_OpenProcess_impl(module, desired_access, inherit_handle, process_id); + if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) + goto exit; + if (_return_value == NULL) + Py_RETURN_NONE; + return_value = HANDLE_TO_PYNUM(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_PeekNamedPipe__doc__, +"PeekNamedPipe($module, handle, size=0, /)\n" +"--\n" +"\n"); + +#define _WINAPI_PEEKNAMEDPIPE_METHODDEF \ + {"PeekNamedPipe", (PyCFunction)_winapi_PeekNamedPipe, METH_VARARGS, _winapi_PeekNamedPipe__doc__}, + +static PyObject * +_winapi_PeekNamedPipe_impl(PyModuleDef *module, HANDLE handle, int size); + +static PyObject * +_winapi_PeekNamedPipe(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HANDLE handle; + int size = 0; + + if (!PyArg_ParseTuple(args, + "" F_HANDLE "|i:PeekNamedPipe", + &handle, &size)) + goto exit; + return_value = _winapi_PeekNamedPipe_impl(module, handle, size); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_ReadFile__doc__, +"ReadFile($module, /, handle, size, overlapped=False)\n" +"--\n" +"\n"); + +#define _WINAPI_READFILE_METHODDEF \ + {"ReadFile", (PyCFunction)_winapi_ReadFile, METH_VARARGS|METH_KEYWORDS, _winapi_ReadFile__doc__}, + +static PyObject * +_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, int use_overlapped); + +static PyObject * +_winapi_ReadFile(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"handle", "size", "overlapped", NULL}; + HANDLE handle; + int size; + int use_overlapped = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "" F_HANDLE "i|i:ReadFile", _keywords, + &handle, &size, &use_overlapped)) + goto exit; + return_value = _winapi_ReadFile_impl(module, handle, size, use_overlapped); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_SetNamedPipeHandleState__doc__, +"SetNamedPipeHandleState($module, named_pipe, mode,\n" +" max_collection_count, collect_data_timeout, /)\n" +"--\n" +"\n"); + +#define _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF \ + {"SetNamedPipeHandleState", (PyCFunction)_winapi_SetNamedPipeHandleState, METH_VARARGS, _winapi_SetNamedPipeHandleState__doc__}, + +static PyObject * +_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, PyObject *mode, PyObject *max_collection_count, PyObject *collect_data_timeout); + +static PyObject * +_winapi_SetNamedPipeHandleState(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HANDLE named_pipe; + PyObject *mode; + PyObject *max_collection_count; + PyObject *collect_data_timeout; + + if (!PyArg_ParseTuple(args, + "" F_HANDLE "OOO:SetNamedPipeHandleState", + &named_pipe, &mode, &max_collection_count, &collect_data_timeout)) + goto exit; + return_value = _winapi_SetNamedPipeHandleState_impl(module, named_pipe, mode, max_collection_count, collect_data_timeout); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_TerminateProcess__doc__, +"TerminateProcess($module, handle, exit_code, /)\n" +"--\n" +"\n" +"Terminate the specified process and all of its threads."); + +#define _WINAPI_TERMINATEPROCESS_METHODDEF \ + {"TerminateProcess", (PyCFunction)_winapi_TerminateProcess, METH_VARARGS, _winapi_TerminateProcess__doc__}, + +static PyObject * +_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, UINT exit_code); + +static PyObject * +_winapi_TerminateProcess(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HANDLE handle; + UINT exit_code; + + if (!PyArg_ParseTuple(args, + "" F_HANDLE "I:TerminateProcess", + &handle, &exit_code)) + goto exit; + return_value = _winapi_TerminateProcess_impl(module, handle, exit_code); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_WaitNamedPipe__doc__, +"WaitNamedPipe($module, name, timeout, /)\n" +"--\n" +"\n"); + +#define _WINAPI_WAITNAMEDPIPE_METHODDEF \ + {"WaitNamedPipe", (PyCFunction)_winapi_WaitNamedPipe, METH_VARARGS, _winapi_WaitNamedPipe__doc__}, + +static PyObject * +_winapi_WaitNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD timeout); + +static PyObject * +_winapi_WaitNamedPipe(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + LPCTSTR name; + DWORD timeout; + + if (!PyArg_ParseTuple(args, + "sk:WaitNamedPipe", + &name, &timeout)) + goto exit; + return_value = _winapi_WaitNamedPipe_impl(module, name, timeout); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_WaitForMultipleObjects__doc__, +"WaitForMultipleObjects($module, handle_seq, wait_flag,\n" +" milliseconds=_winapi.INFINITE, /)\n" +"--\n" +"\n"); + +#define _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF \ + {"WaitForMultipleObjects", (PyCFunction)_winapi_WaitForMultipleObjects, METH_VARARGS, _winapi_WaitForMultipleObjects__doc__}, + +static PyObject * +_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds); + +static PyObject * +_winapi_WaitForMultipleObjects(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *handle_seq; + BOOL wait_flag; + DWORD milliseconds = INFINITE; + + if (!PyArg_ParseTuple(args, + "Oi|k:WaitForMultipleObjects", + &handle_seq, &wait_flag, &milliseconds)) + goto exit; + return_value = _winapi_WaitForMultipleObjects_impl(module, handle_seq, wait_flag, milliseconds); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_WaitForSingleObject__doc__, +"WaitForSingleObject($module, handle, milliseconds, /)\n" +"--\n" +"\n" +"Wait for a single object.\n" +"\n" +"Wait until the specified object is in the signaled state or\n" +"the time-out interval elapses. The timeout value is specified\n" +"in milliseconds."); + +#define _WINAPI_WAITFORSINGLEOBJECT_METHODDEF \ + {"WaitForSingleObject", (PyCFunction)_winapi_WaitForSingleObject, METH_VARARGS, _winapi_WaitForSingleObject__doc__}, + +static long +_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, DWORD milliseconds); + +static PyObject * +_winapi_WaitForSingleObject(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + HANDLE handle; + DWORD milliseconds; + long _return_value; + + if (!PyArg_ParseTuple(args, + "" F_HANDLE "k:WaitForSingleObject", + &handle, &milliseconds)) + goto exit; + _return_value = _winapi_WaitForSingleObject_impl(module, handle, milliseconds); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_winapi_WriteFile__doc__, +"WriteFile($module, /, handle, buffer, overlapped=False)\n" +"--\n" +"\n"); + +#define _WINAPI_WRITEFILE_METHODDEF \ + {"WriteFile", (PyCFunction)_winapi_WriteFile, METH_VARARGS|METH_KEYWORDS, _winapi_WriteFile__doc__}, + +static PyObject * +_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, int use_overlapped); + +static PyObject * +_winapi_WriteFile(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"handle", "buffer", "overlapped", NULL}; + HANDLE handle; + PyObject *buffer; + int use_overlapped = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "" F_HANDLE "O|i:WriteFile", _keywords, + &handle, &buffer, &use_overlapped)) + goto exit; + return_value = _winapi_WriteFile_impl(module, handle, buffer, use_overlapped); + +exit: + return return_value; +} +/*[clinic end generated code: output=107b73892f62ff3c input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 10:10:22 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 08:10:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324064=3A_Property?= =?utf-8?q?=28=29_docstrings_are_now_writeable=2E?= Message-ID: <20150513081022.11936.7286@psf.io> https://hg.python.org/cpython/rev/1e8a768fa0a5 changeset: 96010:1e8a768fa0a5 user: Raymond Hettinger date: Wed May 13 01:09:59 2015 -0700 summary: Issue #24064: Property() docstrings are now writeable. (Patch by Berker Peksag.) files: Doc/library/collections.rst | 9 +++++++++ Doc/whatsnew/3.5.rst | 16 ++++++++++++++++ Lib/test/test_collections.py | 8 ++++++++ Lib/test/test_descr.py | 5 ++++- Lib/test/test_property.py | 22 ++++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/descrobject.c | 2 +- 7 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -924,6 +924,15 @@ >>> Point3D = namedtuple('Point3D', Point._fields + ('z',)) +Docstrings can be customized by making direct assignments to the ``__doc__`` +fields: + + >>> Book = namedtuple('Book', ['id', 'title', 'authors']) + >>> Book.__doc__ = 'Hardcover book in active collection' + >>> Book.id = '13-digit ISBN' + >>> Book.title = 'Title of first printing' + >>> Book.author = 'List of authors sorted by last name' + Default values can be implemented by using :meth:`_replace` to customize a prototype instance: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -234,6 +234,10 @@ * New Kazakh :ref:`codec ` ``kz1048``. (Contributed by Serhiy Storchaka in :issue:`22682`.) +* Property docstrings are now writable. This is especially useful for + :func:`collections.namedtuple` docstrings. + (Contributed by Berker Peksag in :issue:`24064`.) + * New Tajik :ref:`codec ` ``koi8_t``. (Contributed by Serhiy Storchaka in :issue:`22681`.) @@ -283,6 +287,18 @@ the full chained traceback, just like the interactive interpreter. (Contributed by Claudiu Popa in :issue:`17442`.) +collections +----------- + +* You can now update docstrings produced by :func:`collections.namedtuple`:: + + Point = namedtuple('Point', ['x', 'y']) + Point.__doc__ = 'ordered pair' + Point.x.__doc__ = 'abscissa' + Point.y.__doc__ = 'ordinate' + + (Contributed by Berker Peksag in :issue:`24064`.) + compileall ---------- diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -199,6 +199,14 @@ Point = namedtuple('Point', 'x y') self.assertEqual(Point.__doc__, 'Point(x, y)') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_doc_writable(self): + Point = namedtuple('Point', 'x y') + self.assertEqual(Point.x.__doc__, 'Alias for field number 0') + Point.x.__doc__ = 'docstring for Point.x' + self.assertEqual(Point.x.__doc__, 'docstring for Point.x') + def test_name_fixer(self): for spec, renamed in [ [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2022,7 +2022,7 @@ self.assertIs(raw.fset, C.__dict__['setx']) self.assertIs(raw.fdel, C.__dict__['delx']) - for attr in "__doc__", "fget", "fset", "fdel": + for attr in "fget", "fset", "fdel": try: setattr(raw, attr, 42) except AttributeError as msg: @@ -2033,6 +2033,9 @@ self.fail("expected AttributeError from trying to set readonly %r " "attr on a property" % attr) + raw.__doc__ = 42 + self.assertEqual(raw.__doc__, 42) + class D(object): __getitem__ = property(lambda s: 1/0) diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -76,6 +76,13 @@ """new docstring""" return 8 +class PropertyWritableDoc(object): + + @property + def spam(self): + """Eggs""" + return "eggs" + class PropertyTests(unittest.TestCase): def test_property_decorator_baseclass(self): # see #1620 @@ -150,6 +157,21 @@ foo = property(foo) C.foo.__isabstractmethod__ + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_property_builtin_doc_writable(self): + p = property(doc='basic') + self.assertEqual(p.__doc__, 'basic') + p.__doc__ = 'extended' + self.assertEqual(p.__doc__, 'extended') + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_property_decorator_doc_writable(self): + sub = PropertyWritableDoc() + self.assertEqual(sub.__class__.spam.__doc__, 'Eggs') + sub.__class__.spam.__doc__ = 'Spam' + self.assertEqual(sub.__class__.spam.__doc__, 'Spam') # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ - Issue #22486: Added the math.gcd() function. The fractions.gcd() function now is deprecated. Based on patch by Mark Dickinson. +- Issue #24064: Property() docstrings are now writeable. + (Patch by Berker Peksag.) + - Issue #22681: Added support for the koi8_t encoding. - Issue #22682: Added support for the kz1048 encoding. diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1313,7 +1313,7 @@ {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY}, {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY}, {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY}, - {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY}, + {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0}, {0} }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 10:26:19 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 08:26:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323290=3A__Optimiz?= =?utf-8?q?e_set=5Fmerge=28=29_for_cases_where_the_target_is_empty=2E?= Message-ID: <20150513082619.82445.76633@psf.io> https://hg.python.org/cpython/rev/79c884cc9625 changeset: 96011:79c884cc9625 user: Raymond Hettinger date: Wed May 13 01:26:14 2015 -0700 summary: Issue #23290: Optimize set_merge() for cases where the target is empty. (Contributed by Serhiy Storchaka.) files: Misc/NEWS | 3 + Objects/setobject.c | 50 ++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ - Issue #15027: The UTF-32 encoder is now 3x to 7x faster. +- Issue #23290: Optimize set_merge() for cases where the target is empty. + (Contributed by Serhiy Storchaka.) + - Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -548,16 +548,16 @@ { PySetObject *other; PyObject *key; - Py_hash_t hash; Py_ssize_t i; - setentry *entry; + setentry *so_entry; + setentry *other_entry; assert (PyAnySet_Check(so)); assert (PyAnySet_Check(otherset)); other = (PySetObject*)otherset; if (other == so || other->used == 0) - /* a.update(a) or a.update({}); nothing to do */ + /* a.update(a) or a.update(set()); nothing to do */ return 0; /* Do one big resize at the start, rather than * incrementally resizing as we insert new keys. Expect @@ -567,14 +567,44 @@ if (set_table_resize(so, (so->used + other->used)*2) != 0) return -1; } - for (i = 0; i <= other->mask; i++) { - entry = &other->table[i]; - key = entry->key; - hash = entry->hash; - if (key != NULL && - key != dummy) { + so_entry = so->table; + other_entry = other->table; + + /* If our table is empty, and both tables have the same size, and + there are no dummies to eliminate, then just copy the pointers. */ + if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) { + for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) { + key = other_entry->key; + if (key != NULL) { + assert(so_entry->key == NULL); + Py_INCREF(key); + so_entry->key = key; + so_entry->hash = other_entry->hash; + } + } + so->fill = other->fill; + so->used = other->used; + return 0; + } + + /* If our table is empty, we can use set_insert_clean() */ + if (so->fill == 0) { + for (i = 0; i <= other->mask; i++, other_entry++) { + key = other_entry->key; + if (key != NULL && key != dummy) { + Py_INCREF(key); + set_insert_clean(so, key, other_entry->hash); + } + } + return 0; + } + + /* We can't assure there are no duplicates, so do normal insertions */ + for (i = 0; i <= other->mask; i++, other_entry++) { + key = other_entry->key; + if (key != NULL && key != dummy) { Py_INCREF(key); - if (set_insert_key(so, key, hash) == -1) { + if (set_insert_key(so, key, other_entry->hash)) { Py_DECREF(key); return -1; } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed May 13 10:40:13 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 13 May 2015 08:40:13 +0000 Subject: [Python-checkins] Daily reference leaks (cc2e52878393): sum=5 Message-ID: <20150513084013.25443.26134@psf.io> results for cc2e52878393 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [2, 0, 0] references, sum=2 test_coroutines leaked [-1, -1, -1] references, sum=-3 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogJkg3EI', '--timeout', '7200'] From python-checkins at python.org Wed May 13 10:44:41 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 08:44:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_stylistic_and_consis?= =?utf-8?q?tency_cleanup=2E?= Message-ID: <20150513084441.17011.15612@psf.io> https://hg.python.org/cpython/rev/ed0d847f61d7 changeset: 96012:ed0d847f61d7 user: Raymond Hettinger date: Wed May 13 01:44:36 2015 -0700 summary: Minor stylistic and consistency cleanup. files: Objects/setobject.c | 38 ++++++++++++++++---------------- 1 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -307,7 +307,7 @@ assert(so->fill <= so->mask); /* at least one empty slot */ n_used = so->used; Py_INCREF(key); - if (set_insert_key(so, key, hash) == -1) { + if (set_insert_key(so, key, hash)) { Py_DECREF(key); return -1; } @@ -923,7 +923,7 @@ an_entry.hash = hash; an_entry.key = key; - if (set_add_entry(so, &an_entry) == -1) + if (set_add_entry(so, &an_entry)) return -1; } return 0; @@ -934,7 +934,7 @@ return -1; while ((key = PyIter_Next(it)) != NULL) { - if (set_add_key(so, key) == -1) { + if (set_add_key(so, key)) { Py_DECREF(it); Py_DECREF(key); return -1; @@ -954,7 +954,7 @@ for (i=0 ; iweakreflist = NULL; if (iterable != NULL) { - if (set_update_internal(so, iterable) == -1) { + if (set_update_internal(so, iterable)) { Py_DECREF(so); return NULL; } @@ -1153,7 +1153,7 @@ other = PyTuple_GET_ITEM(args, i); if ((PyObject *)so == other) continue; - if (set_update_internal(result, other) == -1) { + if (set_update_internal(result, other)) { Py_DECREF(result); return NULL; } @@ -1179,7 +1179,7 @@ return NULL; if ((PyObject *)so == other) return (PyObject *)result; - if (set_update_internal(result, other) == -1) { + if (set_update_internal(result, other)) { Py_DECREF(result); return NULL; } @@ -1192,7 +1192,7 @@ if (!PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; - if (set_update_internal(so, other) == -1) + if (set_update_internal(so, other)) return NULL; Py_INCREF(so); return (PyObject *)so; @@ -1228,7 +1228,7 @@ return NULL; } if (rv) { - if (set_add_entry(result, entry) == -1) { + if (set_add_entry(result, entry)) { Py_DECREF(result); return NULL; } @@ -1264,7 +1264,7 @@ return NULL; } if (rv) { - if (set_add_entry(result, &entry) == -1) { + if (set_add_entry(result, &entry)) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(key); @@ -1472,7 +1472,7 @@ for (i=0 ; ihash; entrycopy.key = entry->key; if (!_PyDict_Contains(other, entry->key, entry->hash)) { - if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { + if (set_add_entry((PySetObject *)result, &entrycopy)) { Py_DECREF(result); return NULL; } @@ -1539,7 +1539,7 @@ return NULL; } if (!rv) { - if (set_add_entry((PySetObject *)result, entry) == -1) { + if (set_add_entry((PySetObject *)result, entry)) { Py_DECREF(result); return NULL; } @@ -1564,7 +1564,7 @@ for (i=1 ; i https://hg.python.org/cpython/rev/bde652ae05fd changeset: 96013:bde652ae05fd user: Berker Peksag date: Wed May 13 12:16:27 2015 +0300 summary: Issue #24064: Add __doc__ to the example in collections.rst. files: Doc/library/collections.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -929,9 +929,9 @@ >>> Book = namedtuple('Book', ['id', 'title', 'authors']) >>> Book.__doc__ = 'Hardcover book in active collection' - >>> Book.id = '13-digit ISBN' - >>> Book.title = 'Title of first printing' - >>> Book.author = 'List of authors sorted by last name' + >>> Book.id.__doc__ = '13-digit ISBN' + >>> Book.title.__doc__ = 'Title of first printing' + >>> Book.author.__doc__ = 'List of authors sorted by last name' Default values can be implemented by using :meth:`_replace` to customize a prototype instance: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 11:32:02 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 13 May 2015 09:32:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=231322=3A_platform?= =?utf-8?q?=2Edist=28=29_and_platform=2Elinux=5Fdistribution=28=29_functio?= =?utf-8?q?ns_are?= Message-ID: <20150513093202.25435.3121@psf.io> https://hg.python.org/cpython/rev/9c606c573ec0 changeset: 96014:9c606c573ec0 user: Berker Peksag date: Wed May 13 12:32:20 2015 +0300 summary: Issue #1322: platform.dist() and platform.linux_distribution() functions are now deprecated. Initial patch by Vajrasky Kok. files: Doc/library/platform.rst | 4 ++++ Doc/whatsnew/3.5.rst | 5 +++++ Lib/platform.py | 19 ++++++++++++++++--- Lib/test/test_platform.py | 24 +++++++++++++++++++----- Misc/NEWS | 3 +++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -247,6 +247,8 @@ This is another name for :func:`linux_distribution`. + .. deprecated-removed:: 3.5 3.7 + .. function:: linux_distribution(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...), full_distribution_name=1) Tries to determine the name of the Linux OS distribution name. @@ -263,6 +265,8 @@ parameters. ``id`` is the item in parentheses after the version number. It is usually the version codename. + .. deprecated-removed:: 3.5 3.7 + .. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048) Tries to determine the libc version against which the file executable (defaults diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -700,6 +700,11 @@ :meth:`~string.Formatter.format` method of the :class:`string.Formatter` class has been deprecated. +* :func:`platform.dist` and :func:`platform.linux_distribution` functions are + now deprecated and will be removed in Python 3.7. Linux distributions use + too many different ways of describing themselves, so the functionality is + left to a package. + (Contributed by Vajrasky Kok and Berker Peksag in :issue:`1322`.) Deprecated functions and types of the C API ------------------------------------------- diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -297,6 +297,15 @@ supported_dists=_supported_dists, full_distribution_name=1): + import warnings + warnings.warn("dist() and linux_distribution() functions are deprecated " + "in Python 3.5 and will be removed in Python 3.7", + PendingDeprecationWarning, stacklevel=2) + return _linux_distribution(distname, version, id, supported_dists, + full_distribution_name) + +def _linux_distribution(distname, version, id, supported_dists, + full_distribution_name): """ Tries to determine the name of the Linux OS distribution name. @@ -363,9 +372,13 @@ args given as parameters. """ - return linux_distribution(distname, version, id, - supported_dists=supported_dists, - full_distribution_name=0) + import warnings + warnings.warn("dist() and linux_distribution() functions are deprecated " + "in Python 3.5 and will be removed in Python 3.7", + PendingDeprecationWarning, stacklevel=2) + return _linux_distribution(distname, version, id, + supported_dists=supported_dists, + full_distribution_name=0) def popen(cmd, mode='r', bufsize=-1): diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -311,10 +311,24 @@ self.assertEqual(version, '19') self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat') -def test_main(): - support.run_unittest( - PlatformTest - ) + +class DeprecationTest(unittest.TestCase): + + def test_dist_deprecation(self): + with self.assertWarns(PendingDeprecationWarning) as cm: + platform.dist() + self.assertEqual(str(cm.warning), + 'dist() and linux_distribution() functions are ' + 'deprecated in Python 3.5 and will be removed in ' + 'Python 3.7') + + def test_linux_distribution_deprecation(self): + with self.assertWarns(PendingDeprecationWarning) as cm: + platform.linux_distribution() + self.assertEqual(str(cm.warning), + 'dist() and linux_distribution() functions are ' + 'deprecated in Python 3.5 and will be removed in ' + 'Python 3.7') if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #1322: platform.dist() and platform.linux_distribution() functions are + now deprecated. Initial patch by Vajrasky Kok. + - Issue #22486: Added the math.gcd() function. The fractions.gcd() function now is deprecated. Based on patch by Mark Dickinson. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 11:34:44 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 09:34:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323695=3A__Explain?= =?utf-8?q?_the__zip=28=29_example_for_clustering_a_data_series_into?= Message-ID: <20150513093444.7794.91910@psf.io> https://hg.python.org/cpython/rev/f7d82e40e472 changeset: 96015:f7d82e40e472 user: Raymond Hettinger date: Wed May 13 02:34:38 2015 -0700 summary: Issue #23695: Explain the zip() example for clustering a data series into n-length groups. files: Doc/library/functions.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1492,7 +1492,9 @@ The left-to-right evaluation order of the iterables is guaranteed. This makes possible an idiom for clustering a data series into n-length groups - using ``zip(*[iter(s)]*n)``. + using ``zip(*[iter(s)]*n)``. This repeats the *same* iterator ``n`` times + so that each output tuple has the result of ``n`` calls to the iterator. + This has the effect of dividing the input into n-length chunks. :func:`zip` should only be used with unequal length inputs when you don't care about trailing, unmatched values from the longer iterables. If those -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 11:48:27 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 09:48:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE5OTM0?= =?utf-8?q?=3A__Document_*None*_as_an_acceptable_input_to?= Message-ID: <20150513094827.8129.65417@psf.io> https://hg.python.org/cpython/rev/8440dda28ffe changeset: 96016:8440dda28ffe branch: 3.4 parent: 95996:4e62311e1eb1 user: Raymond Hettinger date: Wed May 13 02:47:57 2015 -0700 summary: Issue #19934: Document *None* as an acceptable input to Counter.most_common([n]) files: Doc/library/collections.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -268,9 +268,9 @@ .. method:: most_common([n]) Return a list of the *n* most common elements and their counts from the - most common to the least. If *n* is not specified, :func:`most_common` - returns *all* elements in the counter. Elements with equal counts are - ordered arbitrarily: + most common to the least. If *n* is omitted or ``None``, + :func:`most_common` returns *all* elements in the counter. Elements + with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 11:48:27 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 09:48:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150513094827.82437.4662@psf.io> https://hg.python.org/cpython/rev/13c37b6f75f2 changeset: 96017:13c37b6f75f2 parent: 96015:f7d82e40e472 parent: 96016:8440dda28ffe user: Raymond Hettinger date: Wed May 13 02:48:21 2015 -0700 summary: merge files: Doc/library/collections.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -268,9 +268,9 @@ .. method:: most_common([n]) Return a list of the *n* most common elements and their counts from the - most common to the least. If *n* is not specified, :func:`most_common` - returns *all* elements in the counter. Elements with equal counts are - ordered arbitrarily: + most common to the least. If *n* is omitted or ``None``, + :func:`most_common` returns *all* elements in the counter. Elements + with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 11:51:04 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 09:51:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5OTM0?= =?utf-8?q?=3A__Document_*None*_as_an_acceptable_input_to?= Message-ID: <20150513095104.8131.70024@psf.io> https://hg.python.org/cpython/rev/df708898f27b changeset: 96018:df708898f27b branch: 2.7 parent: 95995:19c5fb692b39 user: Raymond Hettinger date: Wed May 13 02:50:57 2015 -0700 summary: Issue #19934: Document *None* as an acceptable input to Counter.most_common([n]) files: Doc/library/collections.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -104,9 +104,9 @@ .. method:: most_common([n]) Return a list of the *n* most common elements and their counts from the - most common to the least. If *n* is not specified, :func:`most_common` - returns *all* elements in the counter. Elements with equal counts are - ordered arbitrarily: + most common to the least. If *n* is omitted or ``None` + :func:`most_common` returns *all* elements in the count + with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 12:13:34 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 10:13:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzOTcx?= =?utf-8?q?=3A__Fix_underestimated_presizing_in_dict=2Efromkeys=28=29?= Message-ID: <20150513101334.7794.54672@psf.io> https://hg.python.org/cpython/rev/cd0706499812 changeset: 96019:cd0706499812 branch: 2.7 user: Raymond Hettinger date: Wed May 13 03:13:28 2015 -0700 summary: Issue #23971: Fix underestimated presizing in dict.fromkeys() files: Misc/NEWS | 2 ++ Objects/dictobject.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,8 @@ - Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. +- Issue #23971: Fix underestimated presizing in dict.fromkeys(). + - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1361,7 +1361,7 @@ PyObject *key; long hash; - if (dictresize(mp, Py_SIZE(seq))) { + if (dictresize(mp, Py_SIZE(seq) / 2 * 3)) { Py_DECREF(d); return NULL; } @@ -1382,7 +1382,7 @@ PyObject *key; long hash; - if (dictresize(mp, PySet_GET_SIZE(seq))) { + if (dictresize(mp, PySet_GET_SIZE(seq) / 2 * 3)) { Py_DECREF(d); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 12:39:55 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 13 May 2015 10:39:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMDY0?= =?utf-8?q?=3A_Improve_the_misleading_message_from_2to3_when_skipping_opti?= =?utf-8?q?onal?= Message-ID: <20150513103955.108350.79445@psf.io> https://hg.python.org/cpython/rev/571c82d8f4c9 changeset: 96020:571c82d8f4c9 branch: 3.4 parent: 96016:8440dda28ffe user: Berker Peksag date: Wed May 13 13:39:51 2015 +0300 summary: Issue #22064: Improve the misleading message from 2to3 when skipping optional fixers. Patch by Vinod Kurup. files: Lib/lib2to3/refactor.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/lib2to3/refactor.py b/Lib/lib2to3/refactor.py --- a/Lib/lib2to3/refactor.py +++ b/Lib/lib2to3/refactor.py @@ -255,7 +255,7 @@ fixer = fix_class(self.options, self.fixer_log) if fixer.explicit and self.explicit is not True and \ fix_mod_path not in self.explicit: - self.log_message("Skipping implicit fixer: %s", fix_name) + self.log_message("Skipping optional fixer: %s", fix_name) continue self.log_debug("Adding transformation: %s", fix_name) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 12:39:55 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 13 May 2015 10:39:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322064=3A_Improve_the_misleading_message_from_2t?= =?utf-8?q?o3_when_skipping_optional?= Message-ID: <20150513103955.1943.24147@psf.io> https://hg.python.org/cpython/rev/11fefeb7e941 changeset: 96021:11fefeb7e941 parent: 96017:13c37b6f75f2 parent: 96020:571c82d8f4c9 user: Berker Peksag date: Wed May 13 13:40:12 2015 +0300 summary: Issue #22064: Improve the misleading message from 2to3 when skipping optional fixers. Patch by Vinod Kurup. files: Lib/lib2to3/refactor.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/lib2to3/refactor.py b/Lib/lib2to3/refactor.py --- a/Lib/lib2to3/refactor.py +++ b/Lib/lib2to3/refactor.py @@ -255,7 +255,7 @@ fixer = fix_class(self.options, self.fixer_log) if fixer.explicit and self.explicit is not True and \ fix_mod_path not in self.explicit: - self.log_message("Skipping implicit fixer: %s", fix_name) + self.log_message("Skipping optional fixer: %s", fix_name) continue self.log_debug("Adding transformation: %s", fix_name) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 12:42:11 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 13 May 2015 10:42:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMDY0?= =?utf-8?q?=3A_Improve_the_misleading_message_from_2to3_when_skipping_opti?= =?utf-8?q?onal?= Message-ID: <20150513104211.25429.38312@psf.io> https://hg.python.org/cpython/rev/f6e297e698ff changeset: 96022:f6e297e698ff branch: 2.7 parent: 96019:cd0706499812 user: Berker Peksag date: Wed May 13 13:42:26 2015 +0300 summary: Issue #22064: Improve the misleading message from 2to3 when skipping optional fixers. Patch by Vinod Kurup. files: Lib/lib2to3/refactor.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/lib2to3/refactor.py b/Lib/lib2to3/refactor.py --- a/Lib/lib2to3/refactor.py +++ b/Lib/lib2to3/refactor.py @@ -255,7 +255,7 @@ fixer = fix_class(self.options, self.fixer_log) if fixer.explicit and self.explicit is not True and \ fix_mod_path not in self.explicit: - self.log_message("Skipping implicit fixer: %s", fix_name) + self.log_message("Skipping optional fixer: %s", fix_name) continue self.log_debug("Adding transformation: %s", fix_name) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 14:04:48 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 13 May 2015 12:04:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323488=3A_Random_g?= =?utf-8?q?enerator_objects_now_consume_2x_less_memory_on_64-bit=2E?= Message-ID: <20150513120448.11942.98870@psf.io> https://hg.python.org/cpython/rev/4b5461dcd190 changeset: 96023:4b5461dcd190 parent: 96021:11fefeb7e941 user: Serhiy Storchaka date: Wed May 13 15:02:12 2015 +0300 summary: Issue #23488: Random generator objects now consume 2x less memory on 64-bit. files: Misc/NEWS | 2 + Modules/_randommodule.c | 138 +++++++++++++-------------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,8 @@ Library ------- +- Issue #23488: Random generator objects now consume 2x less memory on 64-bit. + - Issue #1322: platform.dist() and platform.linux_distribution() functions are now deprecated. Initial patch by Vajrasky Kok. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -69,17 +69,21 @@ #include "Python.h" #include /* for seeding to current time */ +#ifndef PY_UINT32_T +# error "Failed to find an exact-width 32-bit integer type" +#endif + /* Period parameters -- These are all magic. Don't change. */ #define N 624 #define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ +#define MATRIX_A 0x9908b0dfU /* constant vector a */ +#define UPPER_MASK 0x80000000U /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffU /* least significant r bits */ typedef struct { PyObject_HEAD int index; - unsigned long state[N]; + PY_UINT32_T state[N]; } RandomObject; static PyTypeObject Random_Type; @@ -91,13 +95,13 @@ /* generates a random number on [0,0xffffffff]-interval */ -static unsigned long +static PY_UINT32_T genrand_int32(RandomObject *self) { - unsigned long y; - static unsigned long mag01[2]={0x0UL, MATRIX_A}; + PY_UINT32_T y; + static PY_UINT32_T mag01[2]={0x0U, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ - unsigned long *mt; + PY_UINT32_T *mt; mt = self->state; if (self->index >= N) { /* generate N words at one time */ @@ -105,22 +109,22 @@ for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U]; } for (;kk> 1) ^ mag01[y & 0x1UL]; + mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; self->index = 0; } y = mt[self->index++]; y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; + y ^= (y << 7) & 0x9d2c5680U; + y ^= (y << 15) & 0xefc60000U; y ^= (y >> 18); return y; } @@ -137,28 +141,26 @@ static PyObject * random_random(RandomObject *self) { - unsigned long a=genrand_int32(self)>>5, b=genrand_int32(self)>>6; + PY_UINT32_T a=genrand_int32(self)>>5, b=genrand_int32(self)>>6; return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0)); } /* initializes mt[N] with a seed */ static void -init_genrand(RandomObject *self, unsigned long s) +init_genrand(RandomObject *self, PY_UINT32_T s) { int mti; - unsigned long *mt; + PY_UINT32_T *mt; mt = self->state; - mt[0]= s & 0xffffffffUL; + mt[0]= s; for (mti=1; mti> 30)) + mti); + (1812433253U * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ } self->index = mti; return; @@ -168,32 +170,30 @@ /* init_key is the array for initializing keys */ /* key_length is its length */ static PyObject * -init_by_array(RandomObject *self, unsigned long init_key[], size_t key_length) +init_by_array(RandomObject *self, PY_UINT32_T init_key[], size_t key_length) { size_t i, j, k; /* was signed in the original code. RDH 12/16/2002 */ - unsigned long *mt; + PY_UINT32_T *mt; mt = self->state; - init_genrand(self, 19650218UL); + init_genrand(self, 19650218U); i=1; j=0; k = (N>key_length ? N : key_length); for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) - + init_key[j] + (unsigned long)j; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) + + init_key[j] + (PY_UINT32_T)j; /* non linear */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=key_length) j=0; } for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - - (unsigned long)i; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) + - (PY_UINT32_T)i; /* non linear */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } } - mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ + mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ Py_INCREF(Py_None); return Py_None; } @@ -208,9 +208,8 @@ { PyObject *result = NULL; /* guilty until proved innocent */ PyObject *n = NULL; - unsigned long *key = NULL; - unsigned char *key_as_bytes = NULL; - size_t bits, keyused, i; + PY_UINT32_T *key = NULL; + size_t bits, keyused; int res; PyObject *arg = NULL; @@ -221,7 +220,7 @@ time_t now; time(&now); - init_genrand(self, (unsigned long)now); + init_genrand(self, (PY_UINT32_T)now); Py_INCREF(Py_None); return Py_None; } @@ -249,35 +248,31 @@ keyused = bits == 0 ? 1 : (bits - 1) / 32 + 1; /* Convert seed to byte sequence. */ - key_as_bytes = (unsigned char *)PyMem_Malloc((size_t)4 * keyused); - if (key_as_bytes == NULL) { + key = (PY_UINT32_T *)PyMem_Malloc((size_t)4 * keyused); + if (key == NULL) { PyErr_NoMemory(); goto Done; } res = _PyLong_AsByteArray((PyLongObject *)n, - key_as_bytes, keyused * 4, - 1, /* little-endian */ + (unsigned char *)key, keyused * 4, + PY_LITTLE_ENDIAN, 0); /* unsigned */ if (res == -1) { - PyMem_Free(key_as_bytes); + PyMem_Free(key); goto Done; } - /* Fill array of unsigned longs from byte sequence. */ - key = (unsigned long *)PyMem_Malloc(sizeof(unsigned long) * keyused); - if (key == NULL) { - PyErr_NoMemory(); - PyMem_Free(key_as_bytes); - goto Done; +#if PY_BIG_ENDIAN + { + size_t i, j; + /* Reverse an array. */ + for (i = 0; j = keyused - 1; i < j; i++, j--) { + PY_UINT32_T tmp = key[i]; + key[i] = key[j]; + key[j] = tmp; + } } - for (i = 0; i < keyused; i++) { - key[i] = - ((unsigned long)key_as_bytes[4*i + 0] << 0) + - ((unsigned long)key_as_bytes[4*i + 1] << 8) + - ((unsigned long)key_as_bytes[4*i + 2] << 16) + - ((unsigned long)key_as_bytes[4*i + 3] << 24); - } - PyMem_Free(key_as_bytes); +#endif result = init_by_array(self, key, keyused); Done: Py_XDECREF(n); @@ -334,7 +329,7 @@ element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i)); if (element == (unsigned long)-1 && PyErr_Occurred()) return NULL; - self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */ + self->state[i] = (PY_UINT32_T)element; } index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); @@ -349,9 +344,9 @@ static PyObject * random_getrandbits(RandomObject *self, PyObject *args) { - int k, i, bytes; - unsigned long r; - unsigned char *bytearray; + int k, i, words; + PY_UINT32_T r; + PY_UINT32_T *wordarray; PyObject *result; if (!PyArg_ParseTuple(args, "i:getrandbits", &k)) @@ -366,27 +361,30 @@ if (k <= 32) /* Fast path */ return PyLong_FromUnsignedLong(genrand_int32(self) >> (32 - k)); - bytes = ((k - 1) / 32 + 1) * 4; - bytearray = (unsigned char *)PyMem_Malloc(bytes); - if (bytearray == NULL) { + words = (k - 1) / 32 + 1; + wordarray = (PY_UINT32_T *)PyMem_Malloc(words * 4); + if (wordarray == NULL) { PyErr_NoMemory(); return NULL; } - /* Fill-out whole words, byte-by-byte to avoid endianness issues */ - for (i=0 ; i= 0; i--, k -= 32) +#endif + { r = genrand_int32(self); if (k < 32) - r >>= (32 - k); - bytearray[i+0] = (unsigned char)r; - bytearray[i+1] = (unsigned char)(r >> 8); - bytearray[i+2] = (unsigned char)(r >> 16); - bytearray[i+3] = (unsigned char)(r >> 24); + r >>= (32 - k); /* Drop least significant bits */ + wordarray[i] = r; } - /* little endian order to match bytearray assignment order */ - result = _PyLong_FromByteArray(bytearray, bytes, 1, 0); - PyMem_Free(bytearray); + result = _PyLong_FromByteArray((unsigned char *)wordarray, words * 4, + PY_LITTLE_ENDIAN, 0 /* unsigned */); + PyMem_Free(wordarray); return result; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 16:35:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 14:35:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Add_PEP_489?= Message-ID: <20150513143551.108354.72984@psf.io> https://hg.python.org/peps/rev/f89cdbdb34ff changeset: 5845:f89cdbdb34ff user: Yury Selivanov date: Wed May 13 10:35:47 2015 -0400 summary: pep-0478: Add PEP 489 files: pep-0478.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -73,6 +73,7 @@ Proposed changes for 3.5: +* PEP 489, redesigning extension module loading * PEP 431, improved support for time zone databases * PEP 432, simplifying Python's startup sequence * PEP 436, a build tool generating boilerplate for extension modules -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 13 17:04:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 15:04:13 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Add_PEP_468?= Message-ID: <20150513150413.25425.78072@psf.io> https://hg.python.org/peps/rev/fa60d05ac87e changeset: 5846:fa60d05ac87e user: Yury Selivanov date: Wed May 13 11:04:11 2015 -0400 summary: pep-0478: Add PEP 468 files: pep-0478.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -79,6 +79,7 @@ * PEP 436, a build tool generating boilerplate for extension modules * PEP 447, support for __locallookup__ metaclass method * PEP 455, key transforming dictionary +* PEP 468, preserving the order of **kwargs in a function -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 13 17:19:33 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 13 May 2015 15:19:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_=25_from_title=2C_s?= =?utf-8?q?ince_it_makes_latex_barf?= Message-ID: <20150513151933.122024.37250@psf.io> https://hg.python.org/cpython/rev/647fad777cff changeset: 96024:647fad777cff user: Benjamin Peterson date: Wed May 13 11:19:06 2015 -0400 summary: remove % from title, since it makes latex barf files: Doc/whatsnew/3.5.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -121,8 +121,8 @@ PEP written by Carl Meyer -PEP 461 - Adding % formatting to bytes and bytearray ----------------------------------------------------- +PEP 461 - Adding formatting to bytes and bytearray +-------------------------------------------------- This PEP proposes adding % formatting operations similar to Python 2's ``str`` type to :class:`bytes` and :class:`bytearray`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 17:19:33 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 13 May 2015 15:19:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_extra_space?= Message-ID: <20150513151933.82457.95908@psf.io> https://hg.python.org/cpython/rev/8c6eb462b3b4 changeset: 96025:8c6eb462b3b4 user: Benjamin Peterson date: Wed May 13 11:19:27 2015 -0400 summary: remove extra space files: Doc/whatsnew/3.5.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -69,8 +69,8 @@ New syntax features: -* :pep:`465`, a new matrix multiplication operator: ``a @ b``. -* :pep:`492`, coroutines with async and await syntax. +* :pep:`465`, a new matrix multiplication operator: ``a @ b``. +* :pep:`492`, coroutines with async and await syntax. New library modules: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 17:25:48 2015 From: python-checkins at python.org (andrew.kuchling) Date: Wed, 13 May 2015 15:25:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE5OTM0OiBmaXgg?= =?utf-8?q?mangled_wording?= Message-ID: <20150513152548.11926.26777@psf.io> https://hg.python.org/cpython/rev/68d653f9a2c9 changeset: 96026:68d653f9a2c9 branch: 2.7 parent: 96022:f6e297e698ff user: Andrew Kuchling date: Wed May 13 11:25:40 2015 -0400 summary: #19934: fix mangled wording files: Doc/library/collections.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -104,9 +104,9 @@ .. method:: most_common([n]) Return a list of the *n* most common elements and their counts from the - most common to the least. If *n* is omitted or ``None` - :func:`most_common` returns *all* elements in the count - with equal counts are ordered arbitrarily: + most common to the least. If *n* is omitted or ``None``, + :func:`most_common` returns *all* elements in the counter. + Elements with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 17:38:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 15:38:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Fix_markup?= Message-ID: <20150513153834.11920.40032@psf.io> https://hg.python.org/peps/rev/2f88b96215b6 changeset: 5847:2f88b96215b6 user: Yury Selivanov date: Wed May 13 11:38:31 2015 -0400 summary: pep-0478: Fix markup files: pep-0478.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -79,7 +79,7 @@ * PEP 436, a build tool generating boilerplate for extension modules * PEP 447, support for __locallookup__ metaclass method * PEP 455, key transforming dictionary -* PEP 468, preserving the order of **kwargs in a function +* PEP 468, preserving the order of ``**kwargs`` in a function -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 13 17:58:49 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 13 May 2015 15:58:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320172=3A_Update_c?= =?utf-8?q?linicizations_to_current_clinic=2E?= Message-ID: <20150513155849.11940.51945@psf.io> https://hg.python.org/cpython/rev/c8adc2c13c8b changeset: 96027:c8adc2c13c8b parent: 96025:8c6eb462b3b4 user: Zachary Ware date: Wed May 13 10:58:35 2015 -0500 summary: Issue #20172: Update clinicizations to current clinic. files: Modules/_winapi.c | 93 +++++++++++----- Modules/clinic/_winapi.c.h | 133 ++++++++++++------------ PC/clinic/msvcrtmodule.c.h | 48 ++------ PC/clinic/winreg.c.h | 105 ++++++++----------- PC/clinic/winsound.c.h | 11 +- PC/msvcrtmodule.c | 13 +- PC/winreg.c | 74 +++++++------ PC/winsound.c | 4 +- 8 files changed, 243 insertions(+), 238 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -391,8 +391,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, int use_overlapped) -/*[clinic end generated code: output=d9a64e59c27e10f6 input=edc83da007ebf3be]*/ +_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, + int use_overlapped) +/*[clinic end generated code: output=fed3b165d1bca95a input=edc83da007ebf3be]*/ { BOOL success; OverlappedObject *overlapped = NULL; @@ -442,8 +443,12 @@ [clinic start generated code]*/ static HANDLE -_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, DWORD desired_access, DWORD share_mode, LPSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD flags_and_attributes, HANDLE template_file) -/*[clinic end generated code: output=f8649129a4959288 input=6423c3e40372dbd5]*/ +_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, + DWORD desired_access, DWORD share_mode, + LPSECURITY_ATTRIBUTES security_attributes, + DWORD creation_disposition, + DWORD flags_and_attributes, HANDLE template_file) +/*[clinic end generated code: output=c6e1d78f8affd10c input=6423c3e40372dbd5]*/ { HANDLE handle; @@ -469,8 +474,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, LPWSTR dst_path) -/*[clinic end generated code: output=df22af7be7045584 input=8cd1f9964b6e3d36]*/ +_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, + LPWSTR dst_path) +/*[clinic end generated code: output=eccae9364e46f6da input=8cd1f9964b6e3d36]*/ { /* Privilege adjustment */ HANDLE token = NULL; @@ -611,8 +617,12 @@ [clinic start generated code]*/ static HANDLE -_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD open_mode, DWORD pipe_mode, DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, LPSECURITY_ATTRIBUTES security_attributes) -/*[clinic end generated code: output=711e231639c25c24 input=5a73530b84d8bc37]*/ +_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, + DWORD open_mode, DWORD pipe_mode, + DWORD max_instances, DWORD out_buffer_size, + DWORD in_buffer_size, DWORD default_timeout, + LPSECURITY_ATTRIBUTES security_attributes) +/*[clinic end generated code: output=44ca2a06a219b523 input=5a73530b84d8bc37]*/ { HANDLE handle; @@ -643,8 +653,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, DWORD size) -/*[clinic end generated code: output=ed09baf1d43086df input=c4f2cfa56ef68d90]*/ +_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, + DWORD size) +/*[clinic end generated code: output=fef99f3b4222bc78 input=c4f2cfa56ef68d90]*/ { HANDLE read_pipe; HANDLE write_pipe; @@ -783,8 +794,8 @@ /*[clinic input] _winapi.CreateProcess - application_name: Py_UNICODE(nullable=True) - command_line: Py_UNICODE(nullable=True) + application_name: Py_UNICODE(accept={str, NoneType}) + command_line: Py_UNICODE(accept={str, NoneType}) proc_attrs: object Ignored internally, can be None. thread_attrs: object @@ -792,7 +803,7 @@ inherit_handles: BOOL creation_flags: DWORD env_mapping: object - current_directory: Py_UNICODE(nullable=True) + current_directory: Py_UNICODE(accept={str, NoneType}) startup_info: object / @@ -803,8 +814,13 @@ [clinic start generated code]*/ static PyObject * -_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, Py_UNICODE *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, Py_UNICODE *current_directory, PyObject *startup_info) -/*[clinic end generated code: output=c279c1271b4c45cf input=6667ea0bc7036472]*/ +_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, + Py_UNICODE *command_line, PyObject *proc_attrs, + PyObject *thread_attrs, BOOL inherit_handles, + DWORD creation_flags, PyObject *env_mapping, + Py_UNICODE *current_directory, + PyObject *startup_info) +/*[clinic end generated code: output=874bb350ff9ed4ef input=4a43b05038d639bb]*/ { BOOL result; PROCESS_INFORMATION pi; @@ -884,8 +900,13 @@ [clinic start generated code]*/ static HANDLE -_winapi_DuplicateHandle_impl(PyModuleDef *module, HANDLE source_process_handle, HANDLE source_handle, HANDLE target_process_handle, DWORD desired_access, BOOL inherit_handle, DWORD options) -/*[clinic end generated code: output=24a7836ca4d94aba input=b933e3f2356a8c12]*/ +_winapi_DuplicateHandle_impl(PyModuleDef *module, + HANDLE source_process_handle, + HANDLE source_handle, + HANDLE target_process_handle, + DWORD desired_access, BOOL inherit_handle, + DWORD options) +/*[clinic end generated code: output=0799515b68b5237b input=b933e3f2356a8c12]*/ { HANDLE target_handle; BOOL result; @@ -1074,8 +1095,9 @@ [clinic start generated code]*/ static HANDLE -_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id) -/*[clinic end generated code: output=2a7be5336f16f63c input=ec98c4cf4ea2ec36]*/ +_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, + BOOL inherit_handle, DWORD process_id) +/*[clinic end generated code: output=6bc52eda82a3d226 input=ec98c4cf4ea2ec36]*/ { HANDLE handle; @@ -1145,8 +1167,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, int use_overlapped) -/*[clinic end generated code: output=5a087be0ff44479a input=8dd810194e86ac7d]*/ +_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, + int use_overlapped) +/*[clinic end generated code: output=d7695db4db97b135 input=8dd810194e86ac7d]*/ { DWORD nread; PyObject *buf; @@ -1206,8 +1229,11 @@ [clinic start generated code]*/ static PyObject * -_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, PyObject *mode, PyObject *max_collection_count, PyObject *collect_data_timeout) -/*[clinic end generated code: output=327efd18ff0c30ec input=9142d72163d0faa6]*/ +_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, + PyObject *mode, + PyObject *max_collection_count, + PyObject *collect_data_timeout) +/*[clinic end generated code: output=25aa3c28dee223ce input=9142d72163d0faa6]*/ { PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout}; DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; @@ -1242,8 +1268,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, UINT exit_code) -/*[clinic end generated code: output=1559f0f6500c2283 input=d6bc0aa1ee3bb4df]*/ +_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, + UINT exit_code) +/*[clinic end generated code: output=937c1bb6219aca8b input=d6bc0aa1ee3bb4df]*/ { BOOL result; @@ -1289,8 +1316,10 @@ [clinic start generated code]*/ static PyObject * -_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds) -/*[clinic end generated code: output=e3efee6b505dd48e input=36f76ca057cd28a0]*/ +_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, + PyObject *handle_seq, BOOL wait_flag, + DWORD milliseconds) +/*[clinic end generated code: output=acb440728d06d130 input=36f76ca057cd28a0]*/ { DWORD result; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; @@ -1364,8 +1393,9 @@ [clinic start generated code]*/ static long -_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, DWORD milliseconds) -/*[clinic end generated code: output=0c75bcc6eec6b973 input=443d1ab076edc7b1]*/ +_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, + DWORD milliseconds) +/*[clinic end generated code: output=34ae40c269749c48 input=443d1ab076edc7b1]*/ { DWORD result; @@ -1390,8 +1420,9 @@ [clinic start generated code]*/ static PyObject * -_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, int use_overlapped) -/*[clinic end generated code: output=37bd88e293079b2c input=51846a5af52053fd]*/ +_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, + int use_overlapped) +/*[clinic end generated code: output=65e70ea41f4d2a1d input=51846a5af52053fd]*/ { Py_buffer _buf, *buf; DWORD len, written; diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -19,9 +19,7 @@ PyObject *return_value = NULL; int wait; - if (!PyArg_Parse(arg, - "p:GetOverlappedResult", - &wait)) + if (!PyArg_Parse(arg, "p:GetOverlappedResult", &wait)) goto exit; return_value = _winapi_Overlapped_GetOverlappedResult_impl(self, wait); @@ -81,9 +79,7 @@ PyObject *return_value = NULL; HANDLE handle; - if (!PyArg_Parse(arg, - "" F_HANDLE ":CloseHandle", - &handle)) + if (!PyArg_Parse(arg, "" F_HANDLE ":CloseHandle", &handle)) goto exit; return_value = _winapi_CloseHandle_impl(module, handle); @@ -100,7 +96,8 @@ {"ConnectNamedPipe", (PyCFunction)_winapi_ConnectNamedPipe, METH_VARARGS|METH_KEYWORDS, _winapi_ConnectNamedPipe__doc__}, static PyObject * -_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, int use_overlapped); +_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, + int use_overlapped); static PyObject * _winapi_ConnectNamedPipe(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -110,8 +107,7 @@ HANDLE handle; int use_overlapped = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" F_HANDLE "|i:ConnectNamedPipe", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "|i:ConnectNamedPipe", _keywords, &handle, &use_overlapped)) goto exit; return_value = _winapi_ConnectNamedPipe_impl(module, handle, use_overlapped); @@ -131,7 +127,11 @@ {"CreateFile", (PyCFunction)_winapi_CreateFile, METH_VARARGS, _winapi_CreateFile__doc__}, static HANDLE -_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, DWORD desired_access, DWORD share_mode, LPSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD flags_and_attributes, HANDLE template_file); +_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, + DWORD desired_access, DWORD share_mode, + LPSECURITY_ATTRIBUTES security_attributes, + DWORD creation_disposition, + DWORD flags_and_attributes, HANDLE template_file); static PyObject * _winapi_CreateFile(PyModuleDef *module, PyObject *args) @@ -146,8 +146,7 @@ HANDLE template_file; HANDLE _return_value; - if (!PyArg_ParseTuple(args, - "skk" F_POINTER "kk" F_HANDLE ":CreateFile", + if (!PyArg_ParseTuple(args, "skk" F_POINTER "kk" F_HANDLE ":CreateFile", &file_name, &desired_access, &share_mode, &security_attributes, &creation_disposition, &flags_and_attributes, &template_file)) goto exit; _return_value = _winapi_CreateFile_impl(module, file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file); @@ -170,7 +169,8 @@ {"CreateJunction", (PyCFunction)_winapi_CreateJunction, METH_VARARGS, _winapi_CreateJunction__doc__}, static PyObject * -_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, LPWSTR dst_path); +_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, + LPWSTR dst_path); static PyObject * _winapi_CreateJunction(PyModuleDef *module, PyObject *args) @@ -179,8 +179,7 @@ LPWSTR src_path; LPWSTR dst_path; - if (!PyArg_ParseTuple(args, - "uu:CreateJunction", + if (!PyArg_ParseTuple(args, "uu:CreateJunction", &src_path, &dst_path)) goto exit; return_value = _winapi_CreateJunction_impl(module, src_path, dst_path); @@ -200,7 +199,11 @@ {"CreateNamedPipe", (PyCFunction)_winapi_CreateNamedPipe, METH_VARARGS, _winapi_CreateNamedPipe__doc__}, static HANDLE -_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD open_mode, DWORD pipe_mode, DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, LPSECURITY_ATTRIBUTES security_attributes); +_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, + DWORD open_mode, DWORD pipe_mode, + DWORD max_instances, DWORD out_buffer_size, + DWORD in_buffer_size, DWORD default_timeout, + LPSECURITY_ATTRIBUTES security_attributes); static PyObject * _winapi_CreateNamedPipe(PyModuleDef *module, PyObject *args) @@ -216,8 +219,7 @@ LPSECURITY_ATTRIBUTES security_attributes; HANDLE _return_value; - if (!PyArg_ParseTuple(args, - "skkkkkk" F_POINTER ":CreateNamedPipe", + if (!PyArg_ParseTuple(args, "skkkkkk" F_POINTER ":CreateNamedPipe", &name, &open_mode, &pipe_mode, &max_instances, &out_buffer_size, &in_buffer_size, &default_timeout, &security_attributes)) goto exit; _return_value = _winapi_CreateNamedPipe_impl(module, name, open_mode, pipe_mode, max_instances, out_buffer_size, in_buffer_size, default_timeout, security_attributes); @@ -246,7 +248,8 @@ {"CreatePipe", (PyCFunction)_winapi_CreatePipe, METH_VARARGS, _winapi_CreatePipe__doc__}, static PyObject * -_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, DWORD size); +_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, + DWORD size); static PyObject * _winapi_CreatePipe(PyModuleDef *module, PyObject *args) @@ -255,8 +258,7 @@ PyObject *pipe_attrs; DWORD size; - if (!PyArg_ParseTuple(args, - "Ok:CreatePipe", + if (!PyArg_ParseTuple(args, "Ok:CreatePipe", &pipe_attrs, &size)) goto exit; return_value = _winapi_CreatePipe_impl(module, pipe_attrs, size); @@ -285,7 +287,12 @@ {"CreateProcess", (PyCFunction)_winapi_CreateProcess, METH_VARARGS, _winapi_CreateProcess__doc__}, static PyObject * -_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, Py_UNICODE *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, Py_UNICODE *current_directory, PyObject *startup_info); +_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, + Py_UNICODE *command_line, PyObject *proc_attrs, + PyObject *thread_attrs, BOOL inherit_handles, + DWORD creation_flags, PyObject *env_mapping, + Py_UNICODE *current_directory, + PyObject *startup_info); static PyObject * _winapi_CreateProcess(PyModuleDef *module, PyObject *args) @@ -301,8 +308,7 @@ Py_UNICODE *current_directory; PyObject *startup_info; - if (!PyArg_ParseTuple(args, - "ZZOOikOZO:CreateProcess", + if (!PyArg_ParseTuple(args, "ZZOOikOZO:CreateProcess", &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, ¤t_directory, &startup_info)) goto exit; return_value = _winapi_CreateProcess_impl(module, application_name, command_line, proc_attrs, thread_attrs, inherit_handles, creation_flags, env_mapping, current_directory, startup_info); @@ -327,7 +333,12 @@ {"DuplicateHandle", (PyCFunction)_winapi_DuplicateHandle, METH_VARARGS, _winapi_DuplicateHandle__doc__}, static HANDLE -_winapi_DuplicateHandle_impl(PyModuleDef *module, HANDLE source_process_handle, HANDLE source_handle, HANDLE target_process_handle, DWORD desired_access, BOOL inherit_handle, DWORD options); +_winapi_DuplicateHandle_impl(PyModuleDef *module, + HANDLE source_process_handle, + HANDLE source_handle, + HANDLE target_process_handle, + DWORD desired_access, BOOL inherit_handle, + DWORD options); static PyObject * _winapi_DuplicateHandle(PyModuleDef *module, PyObject *args) @@ -341,8 +352,7 @@ DWORD options = 0; HANDLE _return_value; - if (!PyArg_ParseTuple(args, - "" F_HANDLE "" F_HANDLE "" F_HANDLE "ki|k:DuplicateHandle", + if (!PyArg_ParseTuple(args, "" F_HANDLE "" F_HANDLE "" F_HANDLE "ki|k:DuplicateHandle", &source_process_handle, &source_handle, &target_process_handle, &desired_access, &inherit_handle, &options)) goto exit; _return_value = _winapi_DuplicateHandle_impl(module, source_process_handle, source_handle, target_process_handle, desired_access, inherit_handle, options); @@ -373,9 +383,7 @@ PyObject *return_value = NULL; UINT ExitCode; - if (!PyArg_Parse(arg, - "I:ExitProcess", - &ExitCode)) + if (!PyArg_Parse(arg, "I:ExitProcess", &ExitCode)) goto exit; return_value = _winapi_ExitProcess_impl(module, ExitCode); @@ -431,9 +439,7 @@ HANDLE process; DWORD _return_value; - if (!PyArg_Parse(arg, - "" F_HANDLE ":GetExitCodeProcess", - &process)) + if (!PyArg_Parse(arg, "" F_HANDLE ":GetExitCodeProcess", &process)) goto exit; _return_value = _winapi_GetExitCodeProcess_impl(module, process); if ((_return_value == DWORD_MAX) && PyErr_Occurred()) @@ -495,9 +501,7 @@ PyObject *return_value = NULL; HMODULE module_handle; - if (!PyArg_Parse(arg, - "" F_HANDLE ":GetModuleFileName", - &module_handle)) + if (!PyArg_Parse(arg, "" F_HANDLE ":GetModuleFileName", &module_handle)) goto exit; return_value = _winapi_GetModuleFileName_impl(module, module_handle); @@ -529,9 +533,7 @@ DWORD std_handle; HANDLE _return_value; - if (!PyArg_Parse(arg, - "k:GetStdHandle", - &std_handle)) + if (!PyArg_Parse(arg, "k:GetStdHandle", &std_handle)) goto exit; _return_value = _winapi_GetStdHandle_impl(module, std_handle); if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) @@ -580,7 +582,8 @@ {"OpenProcess", (PyCFunction)_winapi_OpenProcess, METH_VARARGS, _winapi_OpenProcess__doc__}, static HANDLE -_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id); +_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, + BOOL inherit_handle, DWORD process_id); static PyObject * _winapi_OpenProcess(PyModuleDef *module, PyObject *args) @@ -591,8 +594,7 @@ DWORD process_id; HANDLE _return_value; - if (!PyArg_ParseTuple(args, - "kik:OpenProcess", + if (!PyArg_ParseTuple(args, "kik:OpenProcess", &desired_access, &inherit_handle, &process_id)) goto exit; _return_value = _winapi_OpenProcess_impl(module, desired_access, inherit_handle, process_id); @@ -624,8 +626,7 @@ HANDLE handle; int size = 0; - if (!PyArg_ParseTuple(args, - "" F_HANDLE "|i:PeekNamedPipe", + if (!PyArg_ParseTuple(args, "" F_HANDLE "|i:PeekNamedPipe", &handle, &size)) goto exit; return_value = _winapi_PeekNamedPipe_impl(module, handle, size); @@ -643,7 +644,8 @@ {"ReadFile", (PyCFunction)_winapi_ReadFile, METH_VARARGS|METH_KEYWORDS, _winapi_ReadFile__doc__}, static PyObject * -_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, int use_overlapped); +_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, + int use_overlapped); static PyObject * _winapi_ReadFile(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -654,8 +656,7 @@ int size; int use_overlapped = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" F_HANDLE "i|i:ReadFile", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "i|i:ReadFile", _keywords, &handle, &size, &use_overlapped)) goto exit; return_value = _winapi_ReadFile_impl(module, handle, size, use_overlapped); @@ -674,7 +675,10 @@ {"SetNamedPipeHandleState", (PyCFunction)_winapi_SetNamedPipeHandleState, METH_VARARGS, _winapi_SetNamedPipeHandleState__doc__}, static PyObject * -_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, PyObject *mode, PyObject *max_collection_count, PyObject *collect_data_timeout); +_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, + PyObject *mode, + PyObject *max_collection_count, + PyObject *collect_data_timeout); static PyObject * _winapi_SetNamedPipeHandleState(PyModuleDef *module, PyObject *args) @@ -685,8 +689,7 @@ PyObject *max_collection_count; PyObject *collect_data_timeout; - if (!PyArg_ParseTuple(args, - "" F_HANDLE "OOO:SetNamedPipeHandleState", + if (!PyArg_ParseTuple(args, "" F_HANDLE "OOO:SetNamedPipeHandleState", &named_pipe, &mode, &max_collection_count, &collect_data_timeout)) goto exit; return_value = _winapi_SetNamedPipeHandleState_impl(module, named_pipe, mode, max_collection_count, collect_data_timeout); @@ -705,7 +708,8 @@ {"TerminateProcess", (PyCFunction)_winapi_TerminateProcess, METH_VARARGS, _winapi_TerminateProcess__doc__}, static PyObject * -_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, UINT exit_code); +_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, + UINT exit_code); static PyObject * _winapi_TerminateProcess(PyModuleDef *module, PyObject *args) @@ -714,8 +718,7 @@ HANDLE handle; UINT exit_code; - if (!PyArg_ParseTuple(args, - "" F_HANDLE "I:TerminateProcess", + if (!PyArg_ParseTuple(args, "" F_HANDLE "I:TerminateProcess", &handle, &exit_code)) goto exit; return_value = _winapi_TerminateProcess_impl(module, handle, exit_code); @@ -742,8 +745,7 @@ LPCTSTR name; DWORD timeout; - if (!PyArg_ParseTuple(args, - "sk:WaitNamedPipe", + if (!PyArg_ParseTuple(args, "sk:WaitNamedPipe", &name, &timeout)) goto exit; return_value = _winapi_WaitNamedPipe_impl(module, name, timeout); @@ -762,7 +764,9 @@ {"WaitForMultipleObjects", (PyCFunction)_winapi_WaitForMultipleObjects, METH_VARARGS, _winapi_WaitForMultipleObjects__doc__}, static PyObject * -_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds); +_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, + PyObject *handle_seq, BOOL wait_flag, + DWORD milliseconds); static PyObject * _winapi_WaitForMultipleObjects(PyModuleDef *module, PyObject *args) @@ -772,8 +776,7 @@ BOOL wait_flag; DWORD milliseconds = INFINITE; - if (!PyArg_ParseTuple(args, - "Oi|k:WaitForMultipleObjects", + if (!PyArg_ParseTuple(args, "Oi|k:WaitForMultipleObjects", &handle_seq, &wait_flag, &milliseconds)) goto exit; return_value = _winapi_WaitForMultipleObjects_impl(module, handle_seq, wait_flag, milliseconds); @@ -796,7 +799,8 @@ {"WaitForSingleObject", (PyCFunction)_winapi_WaitForSingleObject, METH_VARARGS, _winapi_WaitForSingleObject__doc__}, static long -_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, DWORD milliseconds); +_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, + DWORD milliseconds); static PyObject * _winapi_WaitForSingleObject(PyModuleDef *module, PyObject *args) @@ -806,8 +810,7 @@ DWORD milliseconds; long _return_value; - if (!PyArg_ParseTuple(args, - "" F_HANDLE "k:WaitForSingleObject", + if (!PyArg_ParseTuple(args, "" F_HANDLE "k:WaitForSingleObject", &handle, &milliseconds)) goto exit; _return_value = _winapi_WaitForSingleObject_impl(module, handle, milliseconds); @@ -828,7 +831,8 @@ {"WriteFile", (PyCFunction)_winapi_WriteFile, METH_VARARGS|METH_KEYWORDS, _winapi_WriteFile__doc__}, static PyObject * -_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, int use_overlapped); +_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, + int use_overlapped); static PyObject * _winapi_WriteFile(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -839,8 +843,7 @@ PyObject *buffer; int use_overlapped = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" F_HANDLE "O|i:WriteFile", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "O|i:WriteFile", _keywords, &handle, &buffer, &use_overlapped)) goto exit; return_value = _winapi_WriteFile_impl(module, handle, buffer, use_overlapped); @@ -848,4 +851,4 @@ exit: return return_value; } -/*[clinic end generated code: output=107b73892f62ff3c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=98771c6584056d19 input=a9049054013a1b77]*/ diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -50,8 +50,7 @@ int mode; long nbytes; - if (!PyArg_ParseTuple(args, - "iil:locking", + if (!PyArg_ParseTuple(args, "iil:locking", &fd, &mode, &nbytes)) goto exit; return_value = msvcrt_locking_impl(module, fd, mode, nbytes); @@ -85,8 +84,7 @@ int flags; long _return_value; - if (!PyArg_ParseTuple(args, - "ii:setmode", + if (!PyArg_ParseTuple(args, "ii:setmode", &fd, &flags)) goto exit; _return_value = msvcrt_setmode_impl(module, fd, flags); @@ -112,7 +110,8 @@ {"open_osfhandle", (PyCFunction)msvcrt_open_osfhandle, METH_VARARGS, msvcrt_open_osfhandle__doc__}, static long -msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, int flags); +msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, + int flags); static PyObject * msvcrt_open_osfhandle(PyModuleDef *module, PyObject *args) @@ -122,8 +121,7 @@ int flags; long _return_value; - if (!PyArg_ParseTuple(args, - ""_Py_PARSE_INTPTR"i:open_osfhandle", + if (!PyArg_ParseTuple(args, ""_Py_PARSE_INTPTR"i:open_osfhandle", &handle, &flags)) goto exit; _return_value = msvcrt_open_osfhandle_impl(module, handle, flags); @@ -156,9 +154,7 @@ int fd; Py_intptr_t _return_value; - if (!PyArg_Parse(arg, - "i:get_osfhandle", - &fd)) + if (!PyArg_Parse(arg, "i:get_osfhandle", &fd)) goto exit; _return_value = msvcrt_get_osfhandle_impl(module, fd); if ((_return_value == -1) && PyErr_Occurred()) @@ -324,9 +320,7 @@ PyObject *return_value = NULL; char char_value; - if (!PyArg_Parse(arg, - "c:putch", - &char_value)) + if (!PyArg_Parse(arg, "c:putch", &char_value)) goto exit; return_value = msvcrt_putch_impl(module, char_value); @@ -354,9 +348,7 @@ PyObject *return_value = NULL; int unicode_char; - if (!PyArg_Parse(arg, - "C:putwch", - &unicode_char)) + if (!PyArg_Parse(arg, "C:putwch", &unicode_char)) goto exit; return_value = msvcrt_putwch_impl(module, unicode_char); @@ -388,9 +380,7 @@ PyObject *return_value = NULL; char char_value; - if (!PyArg_Parse(arg, - "c:ungetch", - &char_value)) + if (!PyArg_Parse(arg, "c:ungetch", &char_value)) goto exit; return_value = msvcrt_ungetch_impl(module, char_value); @@ -418,9 +408,7 @@ PyObject *return_value = NULL; int unicode_char; - if (!PyArg_Parse(arg, - "C:ungetwch", - &unicode_char)) + if (!PyArg_Parse(arg, "C:ungetwch", &unicode_char)) goto exit; return_value = msvcrt_ungetwch_impl(module, unicode_char); @@ -454,8 +442,7 @@ int file; long _return_value; - if (!PyArg_ParseTuple(args, - "ii:CrtSetReportFile", + if (!PyArg_ParseTuple(args, "ii:CrtSetReportFile", &type, &file)) goto exit; _return_value = msvcrt_CrtSetReportFile_impl(module, type, file); @@ -493,8 +480,7 @@ int mode; long _return_value; - if (!PyArg_ParseTuple(args, - "ii:CrtSetReportMode", + if (!PyArg_ParseTuple(args, "ii:CrtSetReportMode", &type, &mode)) goto exit; _return_value = msvcrt_CrtSetReportMode_impl(module, type, mode); @@ -531,9 +517,7 @@ int mode; long _return_value; - if (!PyArg_Parse(arg, - "i:set_error_mode", - &mode)) + if (!PyArg_Parse(arg, "i:set_error_mode", &mode)) goto exit; _return_value = msvcrt_set_error_mode_impl(module, mode); if ((_return_value == -1) && PyErr_Occurred()) @@ -564,9 +548,7 @@ PyObject *return_value = NULL; unsigned int mode; - if (!PyArg_Parse(arg, - "I:SetErrorMode", - &mode)) + if (!PyArg_Parse(arg, "I:SetErrorMode", &mode)) goto exit; return_value = msvcrt_SetErrorMode_impl(module, mode); @@ -601,4 +583,4 @@ #ifndef MSVCRT_SET_ERROR_MODE_METHODDEF #define MSVCRT_SET_ERROR_MODE_METHODDEF #endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ -/*[clinic end generated code: output=41dfb6ca722afa4f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=72468bb32006a11b input=a9049054013a1b77]*/ diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -80,7 +80,8 @@ {"__exit__", (PyCFunction)winreg_HKEYType___exit__, METH_VARARGS|METH_KEYWORDS, winreg_HKEYType___exit____doc__}, static PyObject * -winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback); +winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, + PyObject *exc_value, PyObject *traceback); static PyObject * winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *args, PyObject *kwargs) @@ -91,8 +92,7 @@ PyObject *exc_value; PyObject *traceback; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OOO:__exit__", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO:__exit__", _keywords, &exc_type, &exc_value, &traceback)) goto exit; return_value = winreg_HKEYType___exit___impl(self, exc_type, exc_value, traceback); @@ -135,7 +135,8 @@ {"ConnectRegistry", (PyCFunction)winreg_ConnectRegistry, METH_VARARGS, winreg_ConnectRegistry__doc__}, static HKEY -winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, HKEY key); +winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, + HKEY key); static PyObject * winreg_ConnectRegistry(PyModuleDef *module, PyObject *args) @@ -145,8 +146,7 @@ HKEY key; HKEY _return_value; - if (!PyArg_ParseTuple(args, - "ZO&:ConnectRegistry", + if (!PyArg_ParseTuple(args, "ZO&:ConnectRegistry", &computer_name, clinic_HKEY_converter, &key)) goto exit; _return_value = winreg_ConnectRegistry_impl(module, computer_name, key); @@ -191,8 +191,7 @@ Py_UNICODE *sub_key; HKEY _return_value; - if (!PyArg_ParseTuple(args, - "O&Z:CreateKey", + if (!PyArg_ParseTuple(args, "O&Z:CreateKey", clinic_HKEY_converter, &key, &sub_key)) goto exit; _return_value = winreg_CreateKey_impl(module, key, sub_key); @@ -233,7 +232,8 @@ {"CreateKeyEx", (PyCFunction)winreg_CreateKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_CreateKeyEx__doc__}, static HKEY -winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); +winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access); static PyObject * winreg_CreateKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -246,8 +246,7 @@ REGSAM access = KEY_WRITE; HKEY _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&Z|ii:CreateKeyEx", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:CreateKeyEx", _keywords, clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) goto exit; _return_value = winreg_CreateKeyEx_impl(module, key, sub_key, reserved, access); @@ -290,8 +289,7 @@ HKEY key; Py_UNICODE *sub_key; - if (!PyArg_ParseTuple(args, - "O&u:DeleteKey", + if (!PyArg_ParseTuple(args, "O&u:DeleteKey", clinic_HKEY_converter, &key, &sub_key)) goto exit; return_value = winreg_DeleteKey_impl(module, key, sub_key); @@ -329,7 +327,8 @@ {"DeleteKeyEx", (PyCFunction)winreg_DeleteKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_DeleteKeyEx__doc__}, static PyObject * -winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, REGSAM access, int reserved); +winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + REGSAM access, int reserved); static PyObject * winreg_DeleteKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -341,8 +340,7 @@ REGSAM access = KEY_WOW64_64KEY; int reserved = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&u|ii:DeleteKeyEx", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&u|ii:DeleteKeyEx", _keywords, clinic_HKEY_converter, &key, &sub_key, &access, &reserved)) goto exit; return_value = winreg_DeleteKeyEx_impl(module, key, sub_key, access, reserved); @@ -375,8 +373,7 @@ HKEY key; Py_UNICODE *value; - if (!PyArg_ParseTuple(args, - "O&Z:DeleteValue", + if (!PyArg_ParseTuple(args, "O&Z:DeleteValue", clinic_HKEY_converter, &key, &value)) goto exit; return_value = winreg_DeleteValue_impl(module, key, value); @@ -413,8 +410,7 @@ HKEY key; int index; - if (!PyArg_ParseTuple(args, - "O&i:EnumKey", + if (!PyArg_ParseTuple(args, "O&i:EnumKey", clinic_HKEY_converter, &key, &index)) goto exit; return_value = winreg_EnumKey_impl(module, key, index); @@ -460,8 +456,7 @@ HKEY key; int index; - if (!PyArg_ParseTuple(args, - "O&i:EnumValue", + if (!PyArg_ParseTuple(args, "O&i:EnumValue", clinic_HKEY_converter, &key, &index)) goto exit; return_value = winreg_EnumValue_impl(module, key, index); @@ -488,9 +483,7 @@ PyObject *return_value = NULL; Py_UNICODE *string; - if (!PyArg_Parse(arg, - "u:ExpandEnvironmentStrings", - &string)) + if (!PyArg_Parse(arg, "u:ExpandEnvironmentStrings", &string)) goto exit; return_value = winreg_ExpandEnvironmentStrings_impl(module, string); @@ -529,9 +522,7 @@ PyObject *return_value = NULL; HKEY key; - if (!PyArg_Parse(arg, - "O&:FlushKey", - clinic_HKEY_converter, &key)) + if (!PyArg_Parse(arg, "O&:FlushKey", clinic_HKEY_converter, &key)) goto exit; return_value = winreg_FlushKey_impl(module, key); @@ -571,7 +562,8 @@ {"LoadKey", (PyCFunction)winreg_LoadKey, METH_VARARGS, winreg_LoadKey__doc__}, static PyObject * -winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, Py_UNICODE *file_name); +winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + Py_UNICODE *file_name); static PyObject * winreg_LoadKey(PyModuleDef *module, PyObject *args) @@ -581,8 +573,7 @@ Py_UNICODE *sub_key; Py_UNICODE *file_name; - if (!PyArg_ParseTuple(args, - "O&uu:LoadKey", + if (!PyArg_ParseTuple(args, "O&uu:LoadKey", clinic_HKEY_converter, &key, &sub_key, &file_name)) goto exit; return_value = winreg_LoadKey_impl(module, key, sub_key, file_name); @@ -614,7 +605,8 @@ {"OpenKey", (PyCFunction)winreg_OpenKey, METH_VARARGS|METH_KEYWORDS, winreg_OpenKey__doc__}, static HKEY -winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); +winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access); static PyObject * winreg_OpenKey(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -627,8 +619,7 @@ REGSAM access = KEY_READ; HKEY _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&Z|ii:OpenKey", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:OpenKey", _keywords, clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) goto exit; _return_value = winreg_OpenKey_impl(module, key, sub_key, reserved, access); @@ -663,7 +654,8 @@ {"OpenKeyEx", (PyCFunction)winreg_OpenKeyEx, METH_VARARGS|METH_KEYWORDS, winreg_OpenKeyEx__doc__}, static HKEY -winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access); +winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access); static PyObject * winreg_OpenKeyEx(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -676,8 +668,7 @@ REGSAM access = KEY_READ; HKEY _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&Z|ii:OpenKeyEx", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:OpenKeyEx", _keywords, clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) goto exit; _return_value = winreg_OpenKeyEx_impl(module, key, sub_key, reserved, access); @@ -716,9 +707,7 @@ PyObject *return_value = NULL; HKEY key; - if (!PyArg_Parse(arg, - "O&:QueryInfoKey", - clinic_HKEY_converter, &key)) + if (!PyArg_Parse(arg, "O&:QueryInfoKey", clinic_HKEY_converter, &key)) goto exit; return_value = winreg_QueryInfoKey_impl(module, key); @@ -759,8 +748,7 @@ HKEY key; Py_UNICODE *sub_key; - if (!PyArg_ParseTuple(args, - "O&Z:QueryValue", + if (!PyArg_ParseTuple(args, "O&Z:QueryValue", clinic_HKEY_converter, &key, &sub_key)) goto exit; return_value = winreg_QueryValue_impl(module, key, sub_key); @@ -798,8 +786,7 @@ HKEY key; Py_UNICODE *name; - if (!PyArg_ParseTuple(args, - "O&Z:QueryValueEx", + if (!PyArg_ParseTuple(args, "O&Z:QueryValueEx", clinic_HKEY_converter, &key, &name)) goto exit; return_value = winreg_QueryValueEx_impl(module, key, name); @@ -842,8 +829,7 @@ HKEY key; Py_UNICODE *file_name; - if (!PyArg_ParseTuple(args, - "O&u:SaveKey", + if (!PyArg_ParseTuple(args, "O&u:SaveKey", clinic_HKEY_converter, &key, &file_name)) goto exit; return_value = winreg_SaveKey_impl(module, key, file_name); @@ -882,7 +868,9 @@ {"SetValue", (PyCFunction)winreg_SetValue, METH_VARARGS, winreg_SetValue__doc__}, static PyObject * -winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, DWORD type, Py_UNICODE *value, Py_ssize_clean_t value_length); +winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + DWORD type, Py_UNICODE *value, + Py_ssize_clean_t value_length); static PyObject * winreg_SetValue(PyModuleDef *module, PyObject *args) @@ -894,8 +882,7 @@ Py_UNICODE *value; Py_ssize_clean_t value_length; - if (!PyArg_ParseTuple(args, - "O&Zku#:SetValue", + if (!PyArg_ParseTuple(args, "O&Zku#:SetValue", clinic_HKEY_converter, &key, &sub_key, &type, &value, &value_length)) goto exit; return_value = winreg_SetValue_impl(module, key, sub_key, type, value, value_length); @@ -949,7 +936,8 @@ {"SetValueEx", (PyCFunction)winreg_SetValueEx, METH_VARARGS, winreg_SetValueEx__doc__}, static PyObject * -winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, PyObject *reserved, DWORD type, PyObject *value); +winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, + PyObject *reserved, DWORD type, PyObject *value); static PyObject * winreg_SetValueEx(PyModuleDef *module, PyObject *args) @@ -961,8 +949,7 @@ DWORD type; PyObject *value; - if (!PyArg_ParseTuple(args, - "O&ZOkO:SetValueEx", + if (!PyArg_ParseTuple(args, "O&ZOkO:SetValueEx", clinic_HKEY_converter, &key, &value_name, &reserved, &type, &value)) goto exit; return_value = winreg_SetValueEx_impl(module, key, value_name, reserved, type, value); @@ -998,9 +985,7 @@ PyObject *return_value = NULL; HKEY key; - if (!PyArg_Parse(arg, - "O&:DisableReflectionKey", - clinic_HKEY_converter, &key)) + if (!PyArg_Parse(arg, "O&:DisableReflectionKey", clinic_HKEY_converter, &key)) goto exit; return_value = winreg_DisableReflectionKey_impl(module, key); @@ -1033,9 +1018,7 @@ PyObject *return_value = NULL; HKEY key; - if (!PyArg_Parse(arg, - "O&:EnableReflectionKey", - clinic_HKEY_converter, &key)) + if (!PyArg_Parse(arg, "O&:EnableReflectionKey", clinic_HKEY_converter, &key)) goto exit; return_value = winreg_EnableReflectionKey_impl(module, key); @@ -1066,13 +1049,11 @@ PyObject *return_value = NULL; HKEY key; - if (!PyArg_Parse(arg, - "O&:QueryReflectionKey", - clinic_HKEY_converter, &key)) + if (!PyArg_Parse(arg, "O&:QueryReflectionKey", clinic_HKEY_converter, &key)) goto exit; return_value = winreg_QueryReflectionKey_impl(module, key); exit: return return_value; } -/*[clinic end generated code: output=be6e50b901570878 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=71f5bc30b646807b input=a9049054013a1b77]*/ diff --git a/PC/clinic/winsound.c.h b/PC/clinic/winsound.c.h --- a/PC/clinic/winsound.c.h +++ b/PC/clinic/winsound.c.h @@ -26,8 +26,7 @@ Py_UNICODE *sound; int flags; - if (!PyArg_ParseTuple(args, - "Zi:PlaySound", + if (!PyArg_ParseTuple(args, "Zi:PlaySound", &sound, &flags)) goto exit; return_value = winsound_PlaySound_impl(module, sound, flags); @@ -61,8 +60,7 @@ int frequency; int duration; - if (!PyArg_ParseTuple(args, - "ii:Beep", + if (!PyArg_ParseTuple(args, "ii:Beep", &frequency, &duration)) goto exit; return_value = winsound_Beep_impl(module, frequency, duration); @@ -91,8 +89,7 @@ PyObject *return_value = NULL; int x = MB_OK; - if (!PyArg_ParseTuple(args, - "|i:MessageBeep", + if (!PyArg_ParseTuple(args, "|i:MessageBeep", &x)) goto exit; return_value = winsound_MessageBeep_impl(module, x); @@ -100,4 +97,4 @@ exit: return return_value; } -/*[clinic end generated code: output=89c85ed36c3af2fd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5b018ac9dc1f500 input=a9049054013a1b77]*/ diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c --- a/PC/msvcrtmodule.c +++ b/PC/msvcrtmodule.c @@ -160,8 +160,9 @@ [clinic start generated code]*/ static long -msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, int flags) -/*[clinic end generated code: output=8cda35b8e4ea4178 input=4d8516ed32db8f65]*/ +msvcrt_open_osfhandle_impl(PyModuleDef *module, Py_intptr_t handle, + int flags) +/*[clinic end generated code: output=86bce32582c49c06 input=4d8516ed32db8f65]*/ { int fd; @@ -320,7 +321,7 @@ /*[clinic input] msvcrt.putwch - unicode_char: int(types='str') + unicode_char: int(accept={str}) / Wide char variant of putch(), accepting a Unicode value. @@ -328,7 +329,7 @@ static PyObject * msvcrt_putwch_impl(PyModuleDef *module, int unicode_char) -/*[clinic end generated code: output=c216a73694ca73dd input=74377c932af728a4]*/ +/*[clinic end generated code: output=c216a73694ca73dd input=996ccd0bbcbac4c3]*/ { _putwch(unicode_char); Py_RETURN_NONE; @@ -362,7 +363,7 @@ /*[clinic input] msvcrt.ungetwch - unicode_char: int(types='str') + unicode_char: int(accept={str}) / Wide char variant of ungetch(), accepting a Unicode value. @@ -370,7 +371,7 @@ static PyObject * msvcrt_ungetwch_impl(PyModuleDef *module, int unicode_char) -/*[clinic end generated code: output=1ee7674710322bd1 input=6bcd16276e035902]*/ +/*[clinic end generated code: output=1ee7674710322bd1 input=83ec0492be04d564]*/ { if (_ungetwch(unicode_char) == WEOF) return PyErr_SetFromErrno(PyExc_IOError); diff --git a/PC/winreg.c b/PC/winreg.c --- a/PC/winreg.c +++ b/PC/winreg.c @@ -319,8 +319,9 @@ [clinic start generated code]*/ static PyObject * -winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback) -/*[clinic end generated code: output=51adcc1522e9c847 input=fb32489ee92403c7]*/ +winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, + PyObject *exc_value, PyObject *traceback) +/*[clinic end generated code: output=923ebe7389e6a263 input=fb32489ee92403c7]*/ { if (!PyHKEY_Close((PyObject *)self)) return NULL; @@ -784,7 +785,7 @@ /*[clinic input] winreg.ConnectRegistry -> HKEY - computer_name: Py_UNICODE(nullable=True) + computer_name: Py_UNICODE(accept={str, NoneType}) The name of the remote computer, of the form r"\\computername". If None, the local computer is used. key: HKEY @@ -798,8 +799,9 @@ [clinic start generated code]*/ static HKEY -winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, HKEY key) -/*[clinic end generated code: output=bce735a41d767290 input=dcea2c433af51576]*/ +winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name, + HKEY key) +/*[clinic end generated code: output=5c52f6f7ba6e7b46 input=9a056558ce318433]*/ { HKEY retKey; long rc; @@ -818,7 +820,7 @@ key: HKEY An already open key, or one of the predefined HKEY_* constants. - sub_key: Py_UNICODE(nullable=True) + sub_key: Py_UNICODE(accept={str, NoneType}) The name of the key this method opens or creates. / @@ -835,7 +837,7 @@ static HKEY winreg_CreateKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key) -/*[clinic end generated code: output=cd6843f30a73fc0e input=8014b171a5682fe7]*/ +/*[clinic end generated code: output=cd6843f30a73fc0e input=3cdd1622488acea2]*/ { HKEY retKey; long rc; @@ -853,7 +855,7 @@ key: HKEY An already open key, or one of the predefined HKEY_* constants. - sub_key: Py_UNICODE(nullable=True) + sub_key: Py_UNICODE(accept={str, NoneType}) The name of the key this method opens or creates. reserved: int = 0 A reserved integer, and must be zero. Default is zero. @@ -873,8 +875,9 @@ [clinic start generated code]*/ static HKEY -winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=543d176b19183749 input=4322acd5c7f2e787]*/ +winreg_CreateKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access) +/*[clinic end generated code: output=db835d5be84e72b2 input=42c2b03f98406b66]*/ { HKEY retKey; long rc; @@ -942,8 +945,9 @@ [clinic start generated code]*/ static PyObject * -winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, REGSAM access, int reserved) -/*[clinic end generated code: output=8b8a20684a59a902 input=711d9d89e7ecbed7]*/ +winreg_DeleteKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + REGSAM access, int reserved) +/*[clinic end generated code: output=0362a0ac6502379f input=711d9d89e7ecbed7]*/ { HMODULE hMod; typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int); @@ -975,7 +979,7 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - value: Py_UNICODE(nullable=True) + value: Py_UNICODE(accept={str, NoneType}) A string that identifies the value to remove. / @@ -984,7 +988,7 @@ static PyObject * winreg_DeleteValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value) -/*[clinic end generated code: output=308550b8cdcfd8e1 input=417a5c1005cbbddc]*/ +/*[clinic end generated code: output=308550b8cdcfd8e1 input=a78d3407a4197b21]*/ { long rc; Py_BEGIN_ALLOW_THREADS @@ -1244,8 +1248,9 @@ [clinic start generated code]*/ static PyObject * -winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, Py_UNICODE *file_name) -/*[clinic end generated code: output=53b22607f8e73d34 input=e3b5b45ade311582]*/ +winreg_LoadKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + Py_UNICODE *file_name) +/*[clinic end generated code: output=b8b700e39c695b90 input=e3b5b45ade311582]*/ { long rc; @@ -1262,7 +1267,7 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - sub_key: Py_UNICODE(nullable=True) + sub_key: Py_UNICODE(accept={str, NoneType}) A string that identifies the sub_key to open. reserved: int = 0 A reserved integer that must be zero. Default is zero. @@ -1277,8 +1282,9 @@ [clinic start generated code]*/ static HKEY -winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=8bf50881521469c6 input=dc84a4af4af4d387]*/ +winreg_OpenKey_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access) +/*[clinic end generated code: output=79818ea356490a55 input=098505ac36a9ae28]*/ { HKEY retKey; long rc; @@ -1303,8 +1309,9 @@ [clinic start generated code]*/ static HKEY -winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=f6f7cd4befb9585b input=c6c4972af8622959]*/ +winreg_OpenKeyEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + int reserved, REGSAM access) +/*[clinic end generated code: output=2dd9f29e84ea2dbc input=c6c4972af8622959]*/ { return winreg_OpenKey_impl(module, key, sub_key, reserved, access); } @@ -1355,7 +1362,7 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - sub_key: Py_UNICODE(nullable=True) + sub_key: Py_UNICODE(accept={str, NoneType}) A string that holds the name of the subkey with which the value is associated. If this parameter is None or empty, the function retrieves the value set by the SetValue() method for the key @@ -1373,7 +1380,7 @@ static PyObject * winreg_QueryValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key) -/*[clinic end generated code: output=f91cb6f623c3b65a input=e6ec57bb8d39aaa6]*/ +/*[clinic end generated code: output=f91cb6f623c3b65a input=41cafbbf423b21d6]*/ { long rc; PyObject *retStr; @@ -1426,7 +1433,7 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - name: Py_UNICODE(nullable=True) + name: Py_UNICODE(accept={str, NoneType}) A string indicating the value to query. / @@ -1440,7 +1447,7 @@ static PyObject * winreg_QueryValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *name) -/*[clinic end generated code: output=a4b07f7807194f23 input=4403ae868b44e563]*/ +/*[clinic end generated code: output=a4b07f7807194f23 input=cf366cada4836891]*/ { long rc; BYTE *retBuf, *tmp; @@ -1535,12 +1542,12 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - sub_key: Py_UNICODE(nullable=True) + sub_key: Py_UNICODE(accept={str, NoneType}) A string that names the subkey with which the value is associated. type: DWORD An integer that specifies the type of the data. Currently this must be REG_SZ, meaning only strings are supported. - value: Py_UNICODE(length=True) + value: Py_UNICODE(zeroes=True) A string that specifies the new value. / @@ -1558,8 +1565,10 @@ [clinic start generated code]*/ static PyObject * -winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, DWORD type, Py_UNICODE *value, Py_ssize_clean_t value_length) -/*[clinic end generated code: output=807274a1c01961b5 input=83ad2fae2ffbb941]*/ +winreg_SetValue_impl(PyModuleDef *module, HKEY key, Py_UNICODE *sub_key, + DWORD type, Py_UNICODE *value, + Py_ssize_clean_t value_length) +/*[clinic end generated code: output=3c9c7c2769e8f953 input=2cd2adab79339c53]*/ { long rc; @@ -1582,7 +1591,7 @@ key: HKEY An already open key, or any one of the predefined HKEY_* constants. - value_name: Py_UNICODE(nullable=True) + value_name: Py_UNICODE(accept={str, NoneType}) A string containing the name of the value to set, or None. reserved: object Can be anything - zero is always passed to the API. @@ -1620,8 +1629,9 @@ [clinic start generated code]*/ static PyObject * -winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, PyObject *reserved, DWORD type, PyObject *value) -/*[clinic end generated code: output=a53ac3aecef9b977 input=8fe45d7ac381cf96]*/ +winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name, + PyObject *reserved, DWORD type, PyObject *value) +/*[clinic end generated code: output=ea092a935c361582 input=e73dec535ebeea7d]*/ { BYTE *data; DWORD len; diff --git a/PC/winsound.c b/PC/winsound.c --- a/PC/winsound.c +++ b/PC/winsound.c @@ -64,7 +64,7 @@ /*[clinic input] winsound.PlaySound - sound: Py_UNICODE(nullable=True) + sound: Py_UNICODE(accept={str, NoneType}) The sound to play; a filename, data, or None. flags: int Flag values, ored together. See module documentation. @@ -75,7 +75,7 @@ static PyObject * winsound_PlaySound_impl(PyModuleDef *module, Py_UNICODE *sound, int flags) -/*[clinic end generated code: output=614273784bf59e5c input=c86fab5d8e86f31d]*/ +/*[clinic end generated code: output=614273784bf59e5c input=3411b1b7c1f36d93]*/ { int ok; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 20:10:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 18:10:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24178=3A_support_=27?= =?utf-8?q?async_with=27_for_asyncio_locks=2E?= Message-ID: <20150513181042.25439.79756@psf.io> https://hg.python.org/cpython/rev/616f15f05530 changeset: 96028:616f15f05530 user: Yury Selivanov date: Wed May 13 14:10:38 2015 -0400 summary: Issue 24178: support 'async with' for asyncio locks. files: Lib/asyncio/locks.py | 108 +++++++------- Lib/test/test_asyncio/test_pep492.py | 68 +++++++++ Misc/NEWS | 3 + 3 files changed, 124 insertions(+), 55 deletions(-) diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,12 +3,16 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections +import sys from . import events from . import futures from .coroutines import coroutine +_PY35 = sys.version_info >= (3, 5) + + class _ContextManager: """Context manager. @@ -39,7 +43,53 @@ self._lock = None # Crudely prevent reuse. -class Lock: +class _ContextManagerMixin: + def __enter__(self): + raise RuntimeError( + '"yield from" should be used as context manager expression') + + def __exit__(self, *args): + # This must exist because __enter__ exists, even though that + # always raises; that's how the with-statement works. + pass + + @coroutine + def __iter__(self): + # This is not a coroutine. It is meant to enable the idiom: + # + # with (yield from lock): + # + # + # as an alternative to: + # + # yield from lock.acquire() + # try: + # + # finally: + # lock.release() + yield from self.acquire() + return _ContextManager(self) + + if _PY35: + + def __await__(self): + # To make "with await lock" work. + yield from self.acquire() + return _ContextManager(self) + + @coroutine + def __aenter__(self): + yield from self.acquire() + # We have no use for the "as ..." clause in the with + # statement for locks. + return None + + @coroutine + def __aexit__(self, exc_type, exc, tb): + self.release() + + +class Lock(_ContextManagerMixin): """Primitive lock objects. A primitive lock is a synchronization primitive that is not owned @@ -153,32 +203,6 @@ else: raise RuntimeError('Lock is not acquired.') - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - - def __exit__(self, *args): - # This must exist because __enter__ exists, even though that - # always raises; that's how the with-statement works. - pass - - @coroutine - def __iter__(self): - # This is not a coroutine. It is meant to enable the idiom: - # - # with (yield from lock): - # - # - # as an alternative to: - # - # yield from lock.acquire() - # try: - # - # finally: - # lock.release() - yield from self.acquire() - return _ContextManager(self) - class Event: """Asynchronous equivalent to threading.Event. @@ -246,7 +270,7 @@ self._waiters.remove(fut) -class Condition: +class Condition(_ContextManagerMixin): """Asynchronous equivalent to threading.Condition. This class implements condition variable objects. A condition variable @@ -356,21 +380,8 @@ """ self.notify(len(self._waiters)) - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - def __exit__(self, *args): - pass - - @coroutine - def __iter__(self): - # See comment in Lock.__iter__(). - yield from self.acquire() - return _ContextManager(self) - - -class Semaphore: +class Semaphore(_ContextManagerMixin): """A Semaphore implementation. A semaphore manages an internal counter which is decremented by each @@ -441,19 +452,6 @@ waiter.set_result(True) break - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - - def __exit__(self, *args): - pass - - @coroutine - def __iter__(self): - # See comment in Lock.__iter__(). - yield from self.acquire() - return _ContextManager(self) - class BoundedSemaphore(Semaphore): """A bounded semaphore implementation. diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_asyncio/test_pep492.py @@ -0,0 +1,68 @@ +"""Tests support for new syntax introduced by PEP 492.""" + +import unittest +from unittest import mock + +import asyncio +from asyncio import test_utils + + +class BaseTest(test_utils.TestCase): + + def setUp(self): + self.loop = asyncio.BaseEventLoop() + self.loop._process_events = mock.Mock() + self.loop._selector = mock.Mock() + self.loop._selector.select.return_value = () + self.set_event_loop(self.loop) + + +class LockTests(BaseTest): + + def test_context_manager_async_with(self): + primitives = [ + asyncio.Lock(loop=self.loop), + asyncio.Condition(loop=self.loop), + asyncio.Semaphore(loop=self.loop), + asyncio.BoundedSemaphore(loop=self.loop), + ] + + async def test(lock): + await asyncio.sleep(0.01, loop=self.loop) + self.assertFalse(lock.locked()) + async with lock as _lock: + self.assertIs(_lock, None) + self.assertTrue(lock.locked()) + await asyncio.sleep(0.01, loop=self.loop) + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) + + for primitive in primitives: + self.loop.run_until_complete(test(primitive)) + self.assertFalse(primitive.locked()) + + def test_context_manager_with_await(self): + primitives = [ + asyncio.Lock(loop=self.loop), + asyncio.Condition(loop=self.loop), + asyncio.Semaphore(loop=self.loop), + asyncio.BoundedSemaphore(loop=self.loop), + ] + + async def test(lock): + await asyncio.sleep(0.01, loop=self.loop) + self.assertFalse(lock.locked()) + with await lock as _lock: + self.assertIs(_lock, None) + self.assertTrue(lock.locked()) + await asyncio.sleep(0.01, loop=self.loop) + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) + + for primitive in primitives: + self.loop.run_until_complete(test(primitive)) + self.assertFalse(primitive.locked()) + + +if __name__ == '__main__': + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -116,6 +116,9 @@ - asyncio: async() function is deprecated in favour of ensure_future(). +- Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore + support new 'async with' syntax. Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 20:12:45 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 18:12:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324064=3A_Help_pro?= =?utf-8?q?perty=28=29_support_GC?= Message-ID: <20150513181245.25431.33767@psf.io> https://hg.python.org/cpython/rev/2ddadd0e736d changeset: 96029:2ddadd0e736d user: Raymond Hettinger date: Wed May 13 11:12:33 2015 -0700 summary: Issue #24064: Help property() support GC files: Objects/descrobject.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1592,6 +1592,14 @@ return 0; } +static int +property_clear(PyObject *self) +{ + propertyobject *pp = (propertyobject *)self; + Py_CLEAR(pp->prop_doc); + return 0; +} + PyTypeObject PyProperty_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "property", /* tp_name */ @@ -1617,7 +1625,7 @@ Py_TPFLAGS_BASETYPE, /* tp_flags */ property_doc, /* tp_doc */ property_traverse, /* tp_traverse */ - 0, /* tp_clear */ + (inquiry)property_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 20:24:07 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 18:24:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24179=3A_Support_=27?= =?utf-8?q?async_for=27_for_asyncio=2EStreamReader=2E?= Message-ID: <20150513182407.11950.11149@psf.io> https://hg.python.org/cpython/rev/4f6978343ef6 changeset: 96030:4f6978343ef6 user: Yury Selivanov date: Wed May 13 14:23:29 2015 -0400 summary: Issue 24179: Support 'async for' for asyncio.StreamReader. files: Lib/asyncio/streams.py | 14 +++++++++++ Lib/test/test_asyncio/test_pep492.py | 19 ++++++++++++++++ Misc/NEWS | 3 ++ 3 files changed, 36 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,6 +6,7 @@ ] import socket +import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) @@ -19,6 +20,7 @@ _DEFAULT_LIMIT = 2**16 +_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -485,3 +487,15 @@ n -= len(block) return b''.join(blocks) + + if _PY35: + @coroutine + def __aiter__(self): + return self + + @coroutine + def __anext__(self): + val = yield from self.readline() + if val == b'': + raise StopAsyncIteration + return val diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -64,5 +64,24 @@ self.assertFalse(primitive.locked()) +class StreamReaderTests(BaseTest): + + def test_readline(self): + DATA = b'line1\nline2\nline3' + + stream = asyncio.StreamReader(loop=self.loop) + stream.feed_data(DATA) + stream.feed_eof() + + async def reader(): + data = [] + async for line in stream: + data.append(line) + return data + + data = self.loop.run_until_complete(reader()) + self.assertEqual(data, [b'line1\n', b'line2\n', b'line3']) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -119,6 +119,9 @@ - Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore support new 'async with' syntax. Contributed by Yury Selivanov. +- Issue 24179: Support 'async for' for asyncio.StreamReader. + Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:18:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:18:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Sync_asyncio_c?= =?utf-8?q?ode_from_default_branch=2E?= Message-ID: <20150513191805.8139.77495@psf.io> https://hg.python.org/cpython/rev/8298ea629c1d changeset: 96031:8298ea629c1d branch: 3.4 parent: 96020:571c82d8f4c9 user: Yury Selivanov date: Wed May 13 15:15:56 2015 -0400 summary: Sync asyncio code from default branch. files: Lib/asyncio/locks.py | 108 ++++++++++++++-------------- Lib/asyncio/streams.py | 14 +++ 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -3,12 +3,16 @@ __all__ = ['Lock', 'Event', 'Condition', 'Semaphore', 'BoundedSemaphore'] import collections +import sys from . import events from . import futures from .coroutines import coroutine +_PY35 = sys.version_info >= (3, 5) + + class _ContextManager: """Context manager. @@ -39,7 +43,53 @@ self._lock = None # Crudely prevent reuse. -class Lock: +class _ContextManagerMixin: + def __enter__(self): + raise RuntimeError( + '"yield from" should be used as context manager expression') + + def __exit__(self, *args): + # This must exist because __enter__ exists, even though that + # always raises; that's how the with-statement works. + pass + + @coroutine + def __iter__(self): + # This is not a coroutine. It is meant to enable the idiom: + # + # with (yield from lock): + # + # + # as an alternative to: + # + # yield from lock.acquire() + # try: + # + # finally: + # lock.release() + yield from self.acquire() + return _ContextManager(self) + + if _PY35: + + def __await__(self): + # To make "with await lock" work. + yield from self.acquire() + return _ContextManager(self) + + @coroutine + def __aenter__(self): + yield from self.acquire() + # We have no use for the "as ..." clause in the with + # statement for locks. + return None + + @coroutine + def __aexit__(self, exc_type, exc, tb): + self.release() + + +class Lock(_ContextManagerMixin): """Primitive lock objects. A primitive lock is a synchronization primitive that is not owned @@ -153,32 +203,6 @@ else: raise RuntimeError('Lock is not acquired.') - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - - def __exit__(self, *args): - # This must exist because __enter__ exists, even though that - # always raises; that's how the with-statement works. - pass - - @coroutine - def __iter__(self): - # This is not a coroutine. It is meant to enable the idiom: - # - # with (yield from lock): - # - # - # as an alternative to: - # - # yield from lock.acquire() - # try: - # - # finally: - # lock.release() - yield from self.acquire() - return _ContextManager(self) - class Event: """Asynchronous equivalent to threading.Event. @@ -246,7 +270,7 @@ self._waiters.remove(fut) -class Condition: +class Condition(_ContextManagerMixin): """Asynchronous equivalent to threading.Condition. This class implements condition variable objects. A condition variable @@ -356,21 +380,8 @@ """ self.notify(len(self._waiters)) - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - def __exit__(self, *args): - pass - - @coroutine - def __iter__(self): - # See comment in Lock.__iter__(). - yield from self.acquire() - return _ContextManager(self) - - -class Semaphore: +class Semaphore(_ContextManagerMixin): """A Semaphore implementation. A semaphore manages an internal counter which is decremented by each @@ -441,19 +452,6 @@ waiter.set_result(True) break - def __enter__(self): - raise RuntimeError( - '"yield from" should be used as context manager expression') - - def __exit__(self, *args): - pass - - @coroutine - def __iter__(self): - # See comment in Lock.__iter__(). - yield from self.acquire() - return _ContextManager(self) - class BoundedSemaphore(Semaphore): """A bounded semaphore implementation. diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,6 +6,7 @@ ] import socket +import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) @@ -19,6 +20,7 @@ _DEFAULT_LIMIT = 2**16 +_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -485,3 +487,15 @@ n -= len(block) return b''.join(blocks) + + if _PY35: + @coroutine + def __aiter__(self): + return self + + @coroutine + def __anext__(self): + val = yield from self.readline() + if val == b'': + raise StopAsyncIteration + return val -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:18:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:18:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40Lg==?= Message-ID: <20150513191805.7812.88870@psf.io> https://hg.python.org/cpython/rev/e79886e5aa88 changeset: 96032:e79886e5aa88 parent: 96030:4f6978343ef6 parent: 96031:8298ea629c1d user: Yury Selivanov date: Wed May 13 15:16:18 2015 -0400 summary: Merge 3.4. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:22:25 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:22:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_asyncio=3A_Use_=27collections=2Eabc=2ECoroutine=27_in_as?= =?utf-8?q?yncio=2Eiscoroutine=2E?= Message-ID: <20150513192214.11944.66664@psf.io> https://hg.python.org/cpython/rev/2c61caf9bcf5 changeset: 96034:2c61caf9bcf5 parent: 96032:e79886e5aa88 parent: 96033:0715059b3b55 user: Yury Selivanov date: Wed May 13 15:22:03 2015 -0400 summary: asyncio: Use 'collections.abc.Coroutine' in asyncio.iscoroutine. files: Lib/asyncio/coroutines.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -53,6 +53,11 @@ _is_native_coro_code = lambda code: (code.co_flags & inspect.CO_COROUTINE) +try: + from collections.abc import Coroutine as CoroutineABC +except ImportError: + CoroutineABC = None + # Check for CPython issue #21209 def has_yield_from_bug(): @@ -219,6 +224,9 @@ _COROUTINE_TYPES = (types.GeneratorType, CoroWrapper) +if CoroutineABC is not None: + _COROUTINE_TYPES += (CoroutineABC,) + def iscoroutine(obj): """Return True if obj is a coroutine object.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:22:25 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:22:25 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogVXNl?= =?utf-8?q?_=27collections=2Eabc=2ECoroutine=27_in_asyncio=2Eiscoroutine_?= =?utf-8?b?KGluIDMuNSk=?= Message-ID: <20150513192214.7810.72585@psf.io> https://hg.python.org/cpython/rev/0715059b3b55 changeset: 96033:0715059b3b55 branch: 3.4 parent: 96031:8298ea629c1d user: Yury Selivanov date: Wed May 13 15:21:41 2015 -0400 summary: asyncio: Use 'collections.abc.Coroutine' in asyncio.iscoroutine (in 3.5) files: Lib/asyncio/coroutines.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -53,6 +53,11 @@ _is_native_coro_code = lambda code: (code.co_flags & inspect.CO_COROUTINE) +try: + from collections.abc import Coroutine as CoroutineABC +except ImportError: + CoroutineABC = None + # Check for CPython issue #21209 def has_yield_from_bug(): @@ -219,6 +224,9 @@ _COROUTINE_TYPES = (types.GeneratorType, CoroWrapper) +if CoroutineABC is not None: + _COROUTINE_TYPES += (CoroutineABC,) + def iscoroutine(obj): """Return True if obj is a coroutine object.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:34:55 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:34:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Add_a_test_for_?= =?utf-8?q?asyncio=2Eiscoroutine=28=29=2E?= Message-ID: <20150513193454.7808.61670@psf.io> https://hg.python.org/cpython/rev/ae702d4f199b changeset: 96035:ae702d4f199b user: Yury Selivanov date: Wed May 13 15:34:12 2015 -0400 summary: asyncio: Add a test for asyncio.iscoroutine(). Test that asyncio.iscoroutine() supports 'async def' coroutines and collections.abc.Coroutine types. files: Lib/test/test_asyncio/test_pep492.py | 29 ++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -1,6 +1,10 @@ """Tests support for new syntax introduced by PEP 492.""" +import collections.abc +import gc import unittest + +from test import support from unittest import mock import asyncio @@ -83,5 +87,30 @@ self.assertEqual(data, [b'line1\n', b'line2\n', b'line3']) +class CoroutineTests(BaseTest): + + def test_iscoroutine(self): + async def foo(): pass + + f = foo() + try: + self.assertTrue(asyncio.iscoroutine(f)) + finally: + f.close() # silence warning + + class FakeCoro(collections.abc.Coroutine): + def send(self, value): pass + def throw(self, typ, val=None, tb=None): pass + + fc = FakeCoro() + try: + self.assertTrue(asyncio.iscoroutine(fc)) + finally: + # To make sure that ABCMeta caches are freed + # from FakeCoro ASAP. + fc = FakeCoro = None + support.gc_collect() + + if __name__ == '__main__': unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 21:37:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 19:37:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio/tests=3A_Drop_unus?= =?utf-8?q?ed_import=2E?= Message-ID: <20150513193751.11936.22786@psf.io> https://hg.python.org/cpython/rev/94eddf8ec0e5 changeset: 96036:94eddf8ec0e5 user: Yury Selivanov date: Wed May 13 15:37:48 2015 -0400 summary: asyncio/tests: Drop unused import. files: Lib/test/test_asyncio/test_pep492.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -1,7 +1,6 @@ """Tests support for new syntax introduced by PEP 492.""" import collections.abc -import gc import unittest from test import support -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 22:07:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 20:07:30 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Mention_PEP_484?= Message-ID: <20150513200728.11934.83913@psf.io> https://hg.python.org/peps/rev/945a64f0a892 changeset: 5848:945a64f0a892 user: Yury Selivanov date: Wed May 13 16:07:26 2015 -0400 summary: pep-0478: Mention PEP 484 files: pep-0478.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -73,6 +73,7 @@ Proposed changes for 3.5: +* PEP 484, type hints * PEP 489, redesigning extension module loading * PEP 431, improved support for time zone databases * PEP 432, simplifying Python's startup sequence -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 13 22:49:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 20:49:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24017=3A_More_tests_?= =?utf-8?q?for_=27async_for=27_and_=27async_with=27=2E?= Message-ID: <20150513204952.8141.86341@psf.io> https://hg.python.org/cpython/rev/0d80d46adfdb changeset: 96037:0d80d46adfdb user: Yury Selivanov date: Wed May 13 16:49:35 2015 -0400 summary: Issue 24017: More tests for 'async for' and 'async with'. files: Lib/test/test_coroutines.py | 35 +++++++++++++++++++++++++ 1 files changed, 35 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -623,6 +623,27 @@ run_async(foo()) + def test_with_13(self): + CNT = 0 + + class CM: + async def __aenter__(self): + 1/0 + + async def __aexit__(self, *e): + return True + + async def foo(): + nonlocal CNT + CNT += 1 + async with CM(): + CNT += 1000 + CNT += 10000 + + with self.assertRaises(ZeroDivisionError): + run_async(foo()) + self.assertEqual(CNT, 1) + def test_for_1(self): aiter_calls = 0 @@ -859,6 +880,20 @@ run_async(main()) self.assertEqual(I, 20555255) + def test_for_7(self): + CNT = 0 + class AI: + async def __aiter__(self): + 1/0 + async def foo(): + nonlocal CNT + async for i in AI(): + CNT += 1 + CNT += 10 + with self.assertRaises(ZeroDivisionError): + run_async(foo()) + self.assertEqual(CNT, 0) + class CoroAsyncIOCompatTest(unittest.TestCase): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 23:38:11 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 21:38:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Add_=5F=5Fslots?= =?utf-8?q?=5F=5F_to_BoundArguments=2E?= Message-ID: <20150513213811.1939.45761@psf.io> https://hg.python.org/cpython/rev/ee31277386cb changeset: 96038:ee31277386cb user: Yury Selivanov date: Wed May 13 17:18:41 2015 -0400 summary: inspect: Add __slots__ to BoundArguments. files: Lib/inspect.py | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2377,6 +2377,8 @@ Dict of keyword arguments values. """ + __slots__ = ('arguments', '_signature', '__weakref__') + def __init__(self, signature, arguments): self.arguments = arguments self._signature = signature @@ -2443,6 +2445,13 @@ self.signature == other.signature and self.arguments == other.arguments) + def __setstate__(self, state): + self._signature = state['_signature'] + self.arguments = state['arguments'] + + def __getstate__(self): + return {'_signature': self._signature, 'arguments': self.arguments} + class Signature: """A Signature object represents the overall signature of a function. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 23:39:44 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 21:39:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_mangled_wo?= =?utf-8?q?rding?= Message-ID: <20150513213942.11950.95129@psf.io> https://hg.python.org/cpython/rev/679253430ce5 changeset: 96039:679253430ce5 branch: 3.4 parent: 96033:0715059b3b55 user: Raymond Hettinger date: Wed May 13 14:39:04 2015 -0700 summary: Fix mangled wording files: Doc/library/collections.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -269,8 +269,8 @@ Return a list of the *n* most common elements and their counts from the most common to the least. If *n* is omitted or ``None``, - :func:`most_common` returns *all* elements in the counter. Elements - with equal counts are ordered arbitrarily: + :func:`most_common` returns *all* elements in the counter. + Elements with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 13 23:39:44 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 13 May 2015 21:39:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150513213942.11922.90898@psf.io> https://hg.python.org/cpython/rev/1e1bb3eb6f93 changeset: 96040:1e1bb3eb6f93 parent: 96038:ee31277386cb parent: 96039:679253430ce5 user: Raymond Hettinger date: Wed May 13 14:39:35 2015 -0700 summary: merge files: Doc/library/collections.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -269,8 +269,8 @@ Return a list of the *n* most common elements and their counts from the most common to the least. If *n* is omitted or ``None``, - :func:`most_common` returns *all* elements in the counter. Elements - with equal counts are ordered arbitrarily: + :func:`most_common` returns *all* elements in the counter. + Elements with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 00:44:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 22:44:43 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Mention_new_ABC_c?= =?utf-8?q?lasses=2E?= Message-ID: <20150513224443.11934.77072@psf.io> https://hg.python.org/peps/rev/4fe76401ee20 changeset: 5849:4fe76401ee20 user: Yury Selivanov date: Wed May 13 18:44:41 2015 -0400 summary: pep-0492: Mention new ABC classes. files: pep-0492.txt | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -696,6 +696,21 @@ thread-specific. See `Debugging Features`_ for more details. +New Abstract Base Classes +------------------------- + +In order to allow better integration with existing frameworks (such as +Tornado, see [13]_) and compilers (such as Cython, see [16]_), two new +Abstract Base Classes (ABC) are added: + +* ``collections.abc.Awaitable`` ABC for *Future-like* classes, that + implement ``__await__`` method. + +* ``collections.abc.Coroutine`` ABC for *coroutine* objects, that + implement ``send(value)``, ``throw(type, exc, tb)``, and ``close()`` + methods. + + Glossary ======== @@ -1314,6 +1329,9 @@ 7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. +8. New ABCs: ``collections.abc.Awaitable`` and + ``collections.abc.Coroutine``. + While the list of changes and new things is not short, it is important to understand, that most users will not use these features directly. It is intended to be used in frameworks and libraries to provide users @@ -1396,10 +1414,13 @@ .. [12] https://docs.python.org/3/reference/expressions.html#primaries +.. [13] https://mail.python.org/pipermail/python-dev/2015-May/139851.html + .. [14] https://mail.python.org/pipermail/python-dev/2015-May/139844.html .. [15] http://bugs.python.org/issue24017 +.. [16] https://github.com/python/asyncio/issues/233 Acknowledgments =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 14 00:46:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 13 May 2015 22:46:09 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_an_empty_line?= =?utf-8?q?=2E?= Message-ID: <20150513224609.7818.74502@psf.io> https://hg.python.org/peps/rev/319e99540c22 changeset: 5850:319e99540c22 user: Yury Selivanov date: Wed May 13 18:46:07 2015 -0400 summary: pep-0492: Add an empty line. files: pep-0492.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1422,6 +1422,7 @@ .. [16] https://github.com/python/asyncio/issues/233 + Acknowledgments =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 14 02:32:30 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 14 May 2015 00:32:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIzMDg4OiBDbGFy?= =?utf-8?q?ify_null_termination_of_bytes_and_strings_in_C_API=2E?= Message-ID: <20150514003229.11950.25702@psf.io> https://hg.python.org/cpython/rev/99d2f83290c0 changeset: 96041:99d2f83290c0 branch: 3.4 parent: 96039:679253430ce5 user: R David Murray date: Wed May 13 20:31:53 2015 -0400 summary: #23088: Clarify null termination of bytes and strings in C API. Patch by Martin Panter, reviewed by Serhiy Storchaka and R. David Murray. files: Doc/c-api/bytearray.rst | 3 +- Doc/c-api/bytes.rst | 32 +++++++++++++---------- Doc/c-api/unicode.rst | 40 +++++++++++++++++----------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst --- a/Doc/c-api/bytearray.rst +++ b/Doc/c-api/bytearray.rst @@ -64,7 +64,8 @@ .. c:function:: char* PyByteArray_AsString(PyObject *bytearray) Return the contents of *bytearray* as a char array after checking for a - *NULL* pointer. + *NULL* pointer. The returned array always has an extra + null byte appended. .. c:function:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len) diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -69,8 +69,8 @@ +===================+===============+================================+ | :attr:`%%` | *n/a* | The literal % character. | +-------------------+---------------+--------------------------------+ - | :attr:`%c` | int | A single character, | - | | | represented as an C int. | + | :attr:`%c` | int | A single byte, | + | | | represented as a C int. | +-------------------+---------------+--------------------------------+ | :attr:`%d` | int | Exactly equivalent to | | | | ``printf("%d")``. | @@ -109,7 +109,7 @@ +-------------------+---------------+--------------------------------+ An unrecognized format character causes all the rest of the format string to be - copied as-is to the result string, and any extra arguments discarded. + copied as-is to the result object, and any extra arguments discarded. .. c:function:: PyObject* PyBytes_FromFormatV(const char *format, va_list vargs) @@ -136,11 +136,13 @@ .. c:function:: char* PyBytes_AsString(PyObject *o) - Return a NUL-terminated representation of the contents of *o*. The pointer - refers to the internal buffer of *o*, not a copy. The data must not be - modified in any way, unless the string was just created using + Return a pointer to the contents of *o*. The pointer + refers to the internal buffer of *o*, which consists of ``len(o) + 1`` + bytes. The last byte in the buffer is always null, regardless of + whether there are any other null bytes. The data must not be + modified in any way, unless the object was just created using ``PyBytes_FromStringAndSize(NULL, size)``. It must not be deallocated. If - *o* is not a string object at all, :c:func:`PyBytes_AsString` returns *NULL* + *o* is not a bytes object at all, :c:func:`PyBytes_AsString` returns *NULL* and raises :exc:`TypeError`. @@ -151,16 +153,18 @@ .. c:function:: int PyBytes_AsStringAndSize(PyObject *obj, char **buffer, Py_ssize_t *length) - Return a NUL-terminated representation of the contents of the object *obj* + Return the null-terminated contents of the object *obj* through the output variables *buffer* and *length*. - If *length* is *NULL*, the resulting buffer may not contain NUL characters; + If *length* is *NULL*, the bytes object + may not contain embedded null bytes; if it does, the function returns ``-1`` and a :exc:`TypeError` is raised. - The buffer refers to an internal string buffer of *obj*, not a copy. The data - must not be modified in any way, unless the string was just created using + The buffer refers to an internal buffer of *obj*, which includes an + additional null byte at the end (not counted in *length*). The data + must not be modified in any way, unless the object was just created using ``PyBytes_FromStringAndSize(NULL, size)``. It must not be deallocated. If - *string* is not a string object at all, :c:func:`PyBytes_AsStringAndSize` + *obj* is not a bytes object at all, :c:func:`PyBytes_AsStringAndSize` returns ``-1`` and raises :exc:`TypeError`. @@ -168,14 +172,14 @@ Create a new bytes object in *\*bytes* containing the contents of *newpart* appended to *bytes*; the caller will own the new reference. The reference to - the old value of *bytes* will be stolen. If the new string cannot be + the old value of *bytes* will be stolen. If the new object cannot be created, the old reference to *bytes* will still be discarded and the value of *\*bytes* will be set to *NULL*; the appropriate exception will be set. .. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart) - Create a new string object in *\*bytes* containing the contents of *newpart* + Create a new bytes object in *\*bytes* containing the contents of *newpart* appended to *bytes*. This version decrements the reference count of *newpart*. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -227,7 +227,10 @@ const char* PyUnicode_AS_DATA(PyObject *o) Return a pointer to a :c:type:`Py_UNICODE` representation of the object. The - ``AS_DATA`` form casts the pointer to :c:type:`const char *`. *o* has to be + returned buffer is always terminated with an extra null code point. It + may also contain embedded null code points, which would cause the string + to be truncated when used in most C functions. The ``AS_DATA`` form + casts the pointer to :c:type:`const char *`. The *o* argument has to be a Unicode object (not checked). .. versionchanged:: 3.3 @@ -650,7 +653,8 @@ Copy the string *u* into a new UCS4 buffer that is allocated using :c:func:`PyMem_Malloc`. If this fails, *NULL* is returned with a - :exc:`MemoryError` set. + :exc:`MemoryError` set. The returned buffer always has an extra + null code point appended. .. versionadded:: 3.3 @@ -689,8 +693,9 @@ Return a read-only pointer to the Unicode object's internal :c:type:`Py_UNICODE` buffer, or *NULL* on error. This will create the :c:type:`Py_UNICODE*` representation of the object if it is not yet - available. Note that the resulting :c:type:`Py_UNICODE` string may contain - embedded null characters, which would cause the string to be truncated when + available. The buffer is always terminated with an extra null code point. + Note that the resulting :c:type:`Py_UNICODE` string may also contain + embedded null code points, which would cause the string to be truncated when used in most C functions. Please migrate to using :c:func:`PyUnicode_AsUCS4`, @@ -708,8 +713,9 @@ .. c:function:: Py_UNICODE* PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size) Like :c:func:`PyUnicode_AsUnicode`, but also saves the :c:func:`Py_UNICODE` - array length in *size*. Note that the resulting :c:type:`Py_UNICODE*` string - may contain embedded null characters, which would cause the string to be + array length (excluding the extra null terminator) in *size*. + Note that the resulting :c:type:`Py_UNICODE*` string + may contain embedded null code points, which would cause the string to be truncated when used in most C functions. .. versionadded:: 3.3 @@ -717,11 +723,11 @@ .. c:function:: Py_UNICODE* PyUnicode_AsUnicodeCopy(PyObject *unicode) - Create a copy of a Unicode string ending with a nul character. Return *NULL* + Create a copy of a Unicode string ending with a null code point. Return *NULL* and raise a :exc:`MemoryError` exception on memory allocation failure, otherwise return a new allocated buffer (use :c:func:`PyMem_Free` to free the buffer). Note that the resulting :c:type:`Py_UNICODE*` string may - contain embedded null characters, which would cause the string to be + contain embedded null code points, which would cause the string to be truncated when used in most C functions. .. versionadded:: 3.2 @@ -895,10 +901,10 @@ Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing - 0-termination character). Return the number of :c:type:`wchar_t` characters + null termination character). Return the number of :c:type:`wchar_t` characters copied or -1 in case of an error. Note that the resulting :c:type:`wchar_t*` - string may or may not be 0-terminated. It is the responsibility of the caller - to make sure that the :c:type:`wchar_t*` string is 0-terminated in case this is + string may or may not be null-terminated. It is the responsibility of the caller + to make sure that the :c:type:`wchar_t*` string is null-terminated in case this is required by the application. Also, note that the :c:type:`wchar_t*` string might contain null characters, which would cause the string to be truncated when used with most C functions. @@ -907,8 +913,8 @@ .. c:function:: wchar_t* PyUnicode_AsWideCharString(PyObject *unicode, Py_ssize_t *size) Convert the Unicode object to a wide character string. The output string - always ends with a nul character. If *size* is not *NULL*, write the number - of wide characters (excluding the trailing 0-termination character) into + always ends with a null character. If *size* is not *NULL*, write the number + of wide characters (excluding the trailing null termination character) into *\*size*. Returns a buffer allocated by :c:func:`PyMem_Alloc` (use @@ -1038,9 +1044,11 @@ .. c:function:: char* PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *size) - Return a pointer to the default encoding (UTF-8) of the Unicode object, and - store the size of the encoded representation (in bytes) in *size*. *size* - can be *NULL*, in this case no size will be stored. + Return a pointer to the UTF-8 encoding of the Unicode object, and + store the size of the encoded representation (in bytes) in *size*. The + *size* argument can be *NULL*; in this case no size will be stored. The + returned buffer always has an extra null byte appended (not included in + *size*), regardless of whether there are any other null code points. In the case of an error, *NULL* is returned with an exception set and no *size* is stored. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 02:32:30 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 14 May 2015 00:32:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2323088=3A_Clarify_null_termination_of_bytes_a?= =?utf-8?q?nd_strings_in_C_API=2E?= Message-ID: <20150514003230.7820.24137@psf.io> https://hg.python.org/cpython/rev/863f7c57081b changeset: 96042:863f7c57081b parent: 96040:1e1bb3eb6f93 parent: 96041:99d2f83290c0 user: R David Murray date: Wed May 13 20:32:19 2015 -0400 summary: Merge: #23088: Clarify null termination of bytes and strings in C API. files: Doc/c-api/bytearray.rst | 3 +- Doc/c-api/bytes.rst | 32 +++++++++++++---------- Doc/c-api/unicode.rst | 40 +++++++++++++++++----------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst --- a/Doc/c-api/bytearray.rst +++ b/Doc/c-api/bytearray.rst @@ -64,7 +64,8 @@ .. c:function:: char* PyByteArray_AsString(PyObject *bytearray) Return the contents of *bytearray* as a char array after checking for a - *NULL* pointer. + *NULL* pointer. The returned array always has an extra + null byte appended. .. c:function:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len) diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -69,8 +69,8 @@ +===================+===============+================================+ | :attr:`%%` | *n/a* | The literal % character. | +-------------------+---------------+--------------------------------+ - | :attr:`%c` | int | A single character, | - | | | represented as an C int. | + | :attr:`%c` | int | A single byte, | + | | | represented as a C int. | +-------------------+---------------+--------------------------------+ | :attr:`%d` | int | Exactly equivalent to | | | | ``printf("%d")``. | @@ -109,7 +109,7 @@ +-------------------+---------------+--------------------------------+ An unrecognized format character causes all the rest of the format string to be - copied as-is to the result string, and any extra arguments discarded. + copied as-is to the result object, and any extra arguments discarded. .. c:function:: PyObject* PyBytes_FromFormatV(const char *format, va_list vargs) @@ -136,11 +136,13 @@ .. c:function:: char* PyBytes_AsString(PyObject *o) - Return a NUL-terminated representation of the contents of *o*. The pointer - refers to the internal buffer of *o*, not a copy. The data must not be - modified in any way, unless the string was just created using + Return a pointer to the contents of *o*. The pointer + refers to the internal buffer of *o*, which consists of ``len(o) + 1`` + bytes. The last byte in the buffer is always null, regardless of + whether there are any other null bytes. The data must not be + modified in any way, unless the object was just created using ``PyBytes_FromStringAndSize(NULL, size)``. It must not be deallocated. If - *o* is not a string object at all, :c:func:`PyBytes_AsString` returns *NULL* + *o* is not a bytes object at all, :c:func:`PyBytes_AsString` returns *NULL* and raises :exc:`TypeError`. @@ -151,16 +153,18 @@ .. c:function:: int PyBytes_AsStringAndSize(PyObject *obj, char **buffer, Py_ssize_t *length) - Return a NUL-terminated representation of the contents of the object *obj* + Return the null-terminated contents of the object *obj* through the output variables *buffer* and *length*. - If *length* is *NULL*, the resulting buffer may not contain NUL characters; + If *length* is *NULL*, the bytes object + may not contain embedded null bytes; if it does, the function returns ``-1`` and a :exc:`TypeError` is raised. - The buffer refers to an internal string buffer of *obj*, not a copy. The data - must not be modified in any way, unless the string was just created using + The buffer refers to an internal buffer of *obj*, which includes an + additional null byte at the end (not counted in *length*). The data + must not be modified in any way, unless the object was just created using ``PyBytes_FromStringAndSize(NULL, size)``. It must not be deallocated. If - *string* is not a string object at all, :c:func:`PyBytes_AsStringAndSize` + *obj* is not a bytes object at all, :c:func:`PyBytes_AsStringAndSize` returns ``-1`` and raises :exc:`TypeError`. @@ -168,14 +172,14 @@ Create a new bytes object in *\*bytes* containing the contents of *newpart* appended to *bytes*; the caller will own the new reference. The reference to - the old value of *bytes* will be stolen. If the new string cannot be + the old value of *bytes* will be stolen. If the new object cannot be created, the old reference to *bytes* will still be discarded and the value of *\*bytes* will be set to *NULL*; the appropriate exception will be set. .. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart) - Create a new string object in *\*bytes* containing the contents of *newpart* + Create a new bytes object in *\*bytes* containing the contents of *newpart* appended to *bytes*. This version decrements the reference count of *newpart*. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -227,7 +227,10 @@ const char* PyUnicode_AS_DATA(PyObject *o) Return a pointer to a :c:type:`Py_UNICODE` representation of the object. The - ``AS_DATA`` form casts the pointer to :c:type:`const char *`. *o* has to be + returned buffer is always terminated with an extra null code point. It + may also contain embedded null code points, which would cause the string + to be truncated when used in most C functions. The ``AS_DATA`` form + casts the pointer to :c:type:`const char *`. The *o* argument has to be a Unicode object (not checked). .. versionchanged:: 3.3 @@ -650,7 +653,8 @@ Copy the string *u* into a new UCS4 buffer that is allocated using :c:func:`PyMem_Malloc`. If this fails, *NULL* is returned with a - :exc:`MemoryError` set. + :exc:`MemoryError` set. The returned buffer always has an extra + null code point appended. .. versionadded:: 3.3 @@ -689,8 +693,9 @@ Return a read-only pointer to the Unicode object's internal :c:type:`Py_UNICODE` buffer, or *NULL* on error. This will create the :c:type:`Py_UNICODE*` representation of the object if it is not yet - available. Note that the resulting :c:type:`Py_UNICODE` string may contain - embedded null characters, which would cause the string to be truncated when + available. The buffer is always terminated with an extra null code point. + Note that the resulting :c:type:`Py_UNICODE` string may also contain + embedded null code points, which would cause the string to be truncated when used in most C functions. Please migrate to using :c:func:`PyUnicode_AsUCS4`, @@ -708,8 +713,9 @@ .. c:function:: Py_UNICODE* PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size) Like :c:func:`PyUnicode_AsUnicode`, but also saves the :c:func:`Py_UNICODE` - array length in *size*. Note that the resulting :c:type:`Py_UNICODE*` string - may contain embedded null characters, which would cause the string to be + array length (excluding the extra null terminator) in *size*. + Note that the resulting :c:type:`Py_UNICODE*` string + may contain embedded null code points, which would cause the string to be truncated when used in most C functions. .. versionadded:: 3.3 @@ -717,11 +723,11 @@ .. c:function:: Py_UNICODE* PyUnicode_AsUnicodeCopy(PyObject *unicode) - Create a copy of a Unicode string ending with a nul character. Return *NULL* + Create a copy of a Unicode string ending with a null code point. Return *NULL* and raise a :exc:`MemoryError` exception on memory allocation failure, otherwise return a new allocated buffer (use :c:func:`PyMem_Free` to free the buffer). Note that the resulting :c:type:`Py_UNICODE*` string may - contain embedded null characters, which would cause the string to be + contain embedded null code points, which would cause the string to be truncated when used in most C functions. .. versionadded:: 3.2 @@ -902,10 +908,10 @@ Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing - 0-termination character). Return the number of :c:type:`wchar_t` characters + null termination character). Return the number of :c:type:`wchar_t` characters copied or -1 in case of an error. Note that the resulting :c:type:`wchar_t*` - string may or may not be 0-terminated. It is the responsibility of the caller - to make sure that the :c:type:`wchar_t*` string is 0-terminated in case this is + string may or may not be null-terminated. It is the responsibility of the caller + to make sure that the :c:type:`wchar_t*` string is null-terminated in case this is required by the application. Also, note that the :c:type:`wchar_t*` string might contain null characters, which would cause the string to be truncated when used with most C functions. @@ -914,8 +920,8 @@ .. c:function:: wchar_t* PyUnicode_AsWideCharString(PyObject *unicode, Py_ssize_t *size) Convert the Unicode object to a wide character string. The output string - always ends with a nul character. If *size* is not *NULL*, write the number - of wide characters (excluding the trailing 0-termination character) into + always ends with a null character. If *size* is not *NULL*, write the number + of wide characters (excluding the trailing null termination character) into *\*size*. Returns a buffer allocated by :c:func:`PyMem_Alloc` (use @@ -1045,9 +1051,11 @@ .. c:function:: char* PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *size) - Return a pointer to the default encoding (UTF-8) of the Unicode object, and - store the size of the encoded representation (in bytes) in *size*. *size* - can be *NULL*, in this case no size will be stored. + Return a pointer to the UTF-8 encoding of the Unicode object, and + store the size of the encoded representation (in bytes) in *size*. The + *size* argument can be *NULL*; in this case no size will be stored. The + returned buffer always has an extra null byte appended (not included in + *size*), regardless of whether there are any other null code points. In the case of an error, *NULL* is returned with an exception set and no *size* is stored. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 04:36:25 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 14 May 2015 02:36:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323995=3A_Removes_?= =?utf-8?q?=5FWCONIO=5FDEFINED_check_as_the_wchar=5Ft_console_functions?= Message-ID: <20150514023625.8143.65687@psf.io> https://hg.python.org/cpython/rev/d56a941865fb changeset: 96043:d56a941865fb user: Steve Dower date: Wed May 13 19:35:49 2015 -0700 summary: Issue #23995: Removes _WCONIO_DEFINED check as the wchar_t console functions are always available. files: PC/clinic/msvcrtmodule.c.h | 34 +------------------------- PC/msvcrtmodule.c | 8 ------ 2 files changed, 1 insertions(+), 41 deletions(-) diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -222,8 +222,6 @@ return return_value; } -#if defined(_WCONIO_DEFINED) - PyDoc_STRVAR(msvcrt_getwch__doc__, "getwch($module, /)\n" "--\n" @@ -248,8 +246,6 @@ return return_value; } -#endif /* defined(_WCONIO_DEFINED) */ - PyDoc_STRVAR(msvcrt_getche__doc__, "getche($module, /)\n" "--\n" @@ -274,8 +270,6 @@ return return_value; } -#if defined(_WCONIO_DEFINED) - PyDoc_STRVAR(msvcrt_getwche__doc__, "getwche($module, /)\n" "--\n" @@ -300,8 +294,6 @@ return return_value; } -#endif /* defined(_WCONIO_DEFINED) */ - PyDoc_STRVAR(msvcrt_putch__doc__, "putch($module, char, /)\n" "--\n" @@ -328,8 +320,6 @@ return return_value; } -#if defined(_WCONIO_DEFINED) - PyDoc_STRVAR(msvcrt_putwch__doc__, "putwch($module, unicode_char, /)\n" "--\n" @@ -356,8 +346,6 @@ return return_value; } -#endif /* defined(_WCONIO_DEFINED) */ - PyDoc_STRVAR(msvcrt_ungetch__doc__, "ungetch($module, char, /)\n" "--\n" @@ -388,8 +376,6 @@ return return_value; } -#if defined(_WCONIO_DEFINED) - PyDoc_STRVAR(msvcrt_ungetwch__doc__, "ungetwch($module, unicode_char, /)\n" "--\n" @@ -416,8 +402,6 @@ return return_value; } -#endif /* defined(_WCONIO_DEFINED) */ - #if defined(_DEBUG) PyDoc_STRVAR(msvcrt_CrtSetReportFile__doc__, @@ -556,22 +540,6 @@ return return_value; } -#ifndef MSVCRT_GETWCH_METHODDEF - #define MSVCRT_GETWCH_METHODDEF -#endif /* !defined(MSVCRT_GETWCH_METHODDEF) */ - -#ifndef MSVCRT_GETWCHE_METHODDEF - #define MSVCRT_GETWCHE_METHODDEF -#endif /* !defined(MSVCRT_GETWCHE_METHODDEF) */ - -#ifndef MSVCRT_PUTWCH_METHODDEF - #define MSVCRT_PUTWCH_METHODDEF -#endif /* !defined(MSVCRT_PUTWCH_METHODDEF) */ - -#ifndef MSVCRT_UNGETWCH_METHODDEF - #define MSVCRT_UNGETWCH_METHODDEF -#endif /* !defined(MSVCRT_UNGETWCH_METHODDEF) */ - #ifndef MSVCRT_CRTSETREPORTFILE_METHODDEF #define MSVCRT_CRTSETREPORTFILE_METHODDEF #endif /* !defined(MSVCRT_CRTSETREPORTFILE_METHODDEF) */ @@ -583,4 +551,4 @@ #ifndef MSVCRT_SET_ERROR_MODE_METHODDEF #define MSVCRT_SET_ERROR_MODE_METHODDEF #endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ -/*[clinic end generated code: output=72468bb32006a11b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=16613d3119a1fd44 input=a9049054013a1b77]*/ diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c --- a/PC/msvcrtmodule.c +++ b/PC/msvcrtmodule.c @@ -242,7 +242,6 @@ return ch; } -#ifdef _WCONIO_DEFINED /*[clinic input] msvcrt.getwch -> wchar_t @@ -260,7 +259,6 @@ Py_END_ALLOW_THREADS return ch; } -#endif /* _WCONIO_DEFINED */ /*[clinic input] msvcrt.getche -> byte_char @@ -280,7 +278,6 @@ return ch; } -#ifdef _WCONIO_DEFINED /*[clinic input] msvcrt.getwche -> wchar_t @@ -298,7 +295,6 @@ Py_END_ALLOW_THREADS return ch; } -#endif /* _WCONIO_DEFINED */ /*[clinic input] msvcrt.putch @@ -317,7 +313,6 @@ Py_RETURN_NONE; } -#ifdef _WCONIO_DEFINED /*[clinic input] msvcrt.putwch @@ -335,7 +330,6 @@ Py_RETURN_NONE; } -#endif /* _WCONIO_DEFINED */ /*[clinic input] msvcrt.ungetch @@ -359,7 +353,6 @@ Py_RETURN_NONE; } -#ifdef _WCONIO_DEFINED /*[clinic input] msvcrt.ungetwch @@ -377,7 +370,6 @@ return PyErr_SetFromErrno(PyExc_IOError); Py_RETURN_NONE; } -#endif /* _WCONIO_DEFINED */ #ifdef _DEBUG /*[clinic input] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 05:42:14 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 03:42:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_collections=2Eabc=3A_Test_?= =?utf-8?q?that_if_an_object_is_a_Coroutine_it_is_also_an_Awaitable?= Message-ID: <20150514034214.11920.8267@psf.io> https://hg.python.org/cpython/rev/c217362b17c1 changeset: 96044:c217362b17c1 user: Yury Selivanov date: Wed May 13 23:41:55 2015 -0400 summary: collections.abc: Test that if an object is a Coroutine it is also an Awaitable files: Lib/test/test_collections.py | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -495,6 +495,22 @@ self.assertIsInstance(c, Awaitable) c.close() # awoid RuntimeWarning that coro() was not awaited + class CoroLike: + def send(self, value): + pass + def throw(self, typ, val=None, tb=None): + pass + def close(self): + pass + Coroutine.register(CoroLike) + try: + self.assertTrue(isinstance(CoroLike(), Awaitable)) + self.assertTrue(issubclass(CoroLike, Awaitable)) + CoroLike = None + finally: + support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache + + def test_Coroutine(self): def gen(): yield -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 05:58:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 03:58:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_collections=2Eabc=2Etests?= =?utf-8?q?=3A_Remove_some_unnecessary_code=2E?= Message-ID: <20150514035803.25445.88844@psf.io> https://hg.python.org/cpython/rev/664aaad8ad13 changeset: 96045:664aaad8ad13 user: Yury Selivanov date: Wed May 13 23:57:59 2015 -0400 summary: collections.abc.tests: Remove some unnecessary code. files: Lib/test/test_collections.py | 11 ++++------- 1 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -503,13 +503,10 @@ def close(self): pass Coroutine.register(CoroLike) - try: - self.assertTrue(isinstance(CoroLike(), Awaitable)) - self.assertTrue(issubclass(CoroLike, Awaitable)) - CoroLike = None - finally: - support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache - + self.assertTrue(isinstance(CoroLike(), Awaitable)) + self.assertTrue(issubclass(CoroLike, Awaitable)) + CoroLike = None + support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache def test_Coroutine(self): def gen(): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 06:44:15 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 14 May 2015 04:44:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324186=3A_Disable_?= =?utf-8?q?optimised_OpenSSL_functions_on_64-bit_Windows_to_avoid?= Message-ID: <20150514044415.24000.58017@psf.io> https://hg.python.org/cpython/rev/25d78aa1ec21 changeset: 96046:25d78aa1ec21 user: Steve Dower date: Wed May 13 21:44:02 2015 -0700 summary: Issue #24186: Disable optimised OpenSSL functions on 64-bit Windows to avoid crashing. files: PCbuild/openssl.props | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props --- a/PCbuild/openssl.props +++ b/PCbuild/openssl.props @@ -17,7 +17,6 @@ - @@ -38,6 +37,7 @@ + -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu May 14 10:40:40 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 14 May 2015 08:40:40 +0000 Subject: [Python-checkins] Daily reference leaks (25d78aa1ec21): sum=59 Message-ID: <20150514084040.25425.26188@psf.io> results for 25d78aa1ec21 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, 38, 0] references, sum=38 test_multiprocessing_forkserver leaked [0, 17, 0] memory blocks, sum=17 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogycrsPF', '--timeout', '7200'] From python-checkins at python.org Thu May 14 14:51:28 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 14 May 2015 12:51:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_Make_sentence_correct_English=2E?= Message-ID: <20150514125126.11922.70509@psf.io> https://hg.python.org/cpython/rev/07b88b324243 changeset: 96048:07b88b324243 parent: 96046:25d78aa1ec21 parent: 96047:90a0881755e9 user: R David Murray date: Thu May 14 08:51:09 2015 -0400 summary: Merge: Make sentence correct English. files: Doc/library/asyncio-subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -179,7 +179,7 @@ :func:`create_subprocess_shell` function. The API of the :class:`~asyncio.subprocess.Process` class was designed to be - closed the API of the :class:`subprocess.Popen` class, but they are some + close to the API of the :class:`subprocess.Popen` class, but there are some differences: * There is no explicit :meth:`~subprocess.Popen.poll` method -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 14:51:28 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 14 May 2015 12:51:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Make_sentence_?= =?utf-8?q?correct_English=2E?= Message-ID: <20150514125126.8129.22810@psf.io> https://hg.python.org/cpython/rev/90a0881755e9 changeset: 96047:90a0881755e9 branch: 3.4 parent: 96041:99d2f83290c0 user: R David Murray date: Thu May 14 08:50:38 2015 -0400 summary: Make sentence correct English. files: Doc/library/asyncio-subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -179,7 +179,7 @@ :func:`create_subprocess_shell` function. The API of the :class:`~asyncio.subprocess.Process` class was designed to be - closed the API of the :class:`subprocess.Popen` class, but they are some + close to the API of the :class:`subprocess.Popen` class, but there are some differences: * There is no explicit :meth:`~subprocess.Popen.poll` method -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 18:19:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 16:19:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24184=3A_Add_AsyncIt?= =?utf-8?q?erator_and_AsyncIterable_to_collections=2Eabc=2E?= Message-ID: <20150514161923.1931.9600@psf.io> https://hg.python.org/cpython/rev/4347ce7acd84 changeset: 96049:4347ce7acd84 user: Yury Selivanov date: Thu May 14 12:19:16 2015 -0400 summary: Issue 24184: Add AsyncIterator and AsyncIterable to collections.abc. files: Lib/_collections_abc.py | 39 +++++++++++++++++++++++- Lib/test/test_collections.py | 36 +++++++++++++++++++++- Misc/NEWS | 3 + 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -9,7 +9,7 @@ from abc import ABCMeta, abstractmethod import sys -__all__ = ["Awaitable", "Coroutine", +__all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", "Hashable", "Iterable", "Iterator", "Generator", "Sized", "Container", "Callable", "Set", "MutableSet", @@ -148,6 +148,43 @@ Awaitable.register(Coroutine) +class AsyncIterable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + async def __aiter__(self): + return AsyncIterator() + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncIterable: + if any("__aiter__" in B.__dict__ for B in C.__mro__): + return True + return NotImplemented + + +class AsyncIterator(AsyncIterable): + + __slots__ = () + + @abstractmethod + async def __anext__(self): + """Return the next item or raise StopAsyncIteration when exhausted.""" + raise StopAsyncIteration + + async def __aiter__(self): + return self + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncIterator: + if (any("__anext__" in B.__dict__ for B in C.__mro__) and + any("__aiter__" in B.__dict__ for B in C.__mro__)): + return True + return NotImplemented + + class Iterable(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -15,7 +15,7 @@ from collections import UserDict from collections import ChainMap from collections import deque -from collections.abc import Awaitable, Coroutine +from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable from collections.abc import Hashable, Iterable, Iterator, Generator from collections.abc import Sized, Container, Callable from collections.abc import Set, MutableSet @@ -573,6 +573,40 @@ self.validate_abstract_methods(Hashable, '__hash__') self.validate_isinstance(Hashable, '__hash__') + def test_AsyncIterable(self): + class AI: + async def __aiter__(self): + return self + self.assertTrue(isinstance(AI(), AsyncIterable)) + self.assertTrue(issubclass(AI, AsyncIterable)) + # Check some non-iterables + non_samples = [None, object, []] + for x in non_samples: + self.assertNotIsInstance(x, AsyncIterable) + self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x))) + self.validate_abstract_methods(AsyncIterable, '__aiter__') + self.validate_isinstance(AsyncIterable, '__aiter__') + + def test_AsyncIterator(self): + class AI: + async def __aiter__(self): + return self + async def __anext__(self): + raise StopAsyncIteration + self.assertTrue(isinstance(AI(), AsyncIterator)) + self.assertTrue(issubclass(AI, AsyncIterator)) + non_samples = [None, object, []] + # Check some non-iterables + for x in non_samples: + self.assertNotIsInstance(x, AsyncIterator) + self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x))) + # Similarly to regular iterators (see issue 10565) + class AnextOnly: + async def __anext__(self): + raise StopAsyncIteration + self.assertNotIsInstance(AnextOnly(), AsyncIterator) + self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__') + def test_Iterable(self): # Check some non-iterables non_samples = [None, 42, 3.14, 1j] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -122,6 +122,9 @@ - Issue 24179: Support 'async for' for asyncio.StreamReader. Contributed by Yury Selivanov. +- Issue 24184: Add AsyncIterator and AsyncIterable ABCs to + collections.abc. Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 20:14:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 18:14:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQxOTE6?= =?utf-8?q?_Document_BoundArguments=2Esignature?= Message-ID: <20150514181423.8141.68521@psf.io> https://hg.python.org/cpython/rev/1012a8138fcb changeset: 96050:1012a8138fcb branch: 3.4 parent: 96047:90a0881755e9 user: Yury Selivanov date: Thu May 14 14:14:02 2015 -0400 summary: Issue 24191: Document BoundArguments.signature files: Doc/library/inspect.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -660,6 +660,10 @@ A dict of keyword arguments values. Dynamically computed from the :attr:`arguments` attribute. + .. attribute:: BoundArguments.signature + + A reference to the parent :class:`Signature` object. + The :attr:`args` and :attr:`kwargs` properties can be used to invoke functions:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 14 20:14:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 18:14:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_24191=3A_Document_BoundArguments=2Esignature?= Message-ID: <20150514181423.8147.74783@psf.io> https://hg.python.org/cpython/rev/970454df99cd changeset: 96051:970454df99cd parent: 96049:4347ce7acd84 parent: 96050:1012a8138fcb user: Yury Selivanov date: Thu May 14 14:14:18 2015 -0400 summary: Issue 24191: Document BoundArguments.signature files: Doc/library/inspect.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -699,6 +699,10 @@ A dict of keyword arguments values. Dynamically computed from the :attr:`arguments` attribute. + .. attribute:: BoundArguments.signature + + A reference to the parent :class:`Signature` object. + The :attr:`args` and :attr:`kwargs` properties can be used to invoke functions:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:12:21 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 May 2015 22:12:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogaWRsZWxpYjogcmVt?= =?utf-8?q?ove_unused_names_and_imports_=28one_is_a_duplicate_import=29=2E?= Message-ID: <20150514221221.21200.98018@psf.io> https://hg.python.org/cpython/rev/a980da5f79f9 changeset: 96052:a980da5f79f9 branch: 2.7 parent: 96026:68d653f9a2c9 user: Terry Jan Reedy date: Thu May 14 18:10:30 2015 -0400 summary: idlelib: remove unused names and imports (one is a duplicate import). files: Lib/idlelib/IOBinding.py | 7 +++---- Lib/idlelib/RemoteDebugger.py | 1 - Lib/idlelib/SearchDialog.py | 2 +- Lib/idlelib/TreeWidget.py | 2 +- Lib/idlelib/configDialog.py | 1 - 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -6,7 +6,6 @@ # which will only understand the local convention. import os -import types import pipes import sys import codecs @@ -391,7 +390,7 @@ return False def encode(self, chars): - if isinstance(chars, types.StringType): + if isinstance(chars, str): # This is either plain ASCII, or Tk was returning mixed-encoding # text to us. Don't try to guess further. return chars @@ -568,7 +567,7 @@ "Update recent file list on all editor windows" self.editwin.update_recent_files_list(filename) -def _io_binding(parent): +def _io_binding(parent): # htest # root = Tk() root.title("Test IOBinding") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) @@ -591,7 +590,7 @@ text.pack() text.focus_set() editwin = MyEditWin(text) - io = IOBinding(editwin) + IOBinding(editwin) if __name__ == "__main__": from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -21,7 +21,6 @@ """ import types -from idlelib import rpc from idlelib import Debugger debugging = 0 diff --git a/Lib/idlelib/SearchDialog.py b/Lib/idlelib/SearchDialog.py --- a/Lib/idlelib/SearchDialog.py +++ b/Lib/idlelib/SearchDialog.py @@ -23,7 +23,7 @@ class SearchDialog(SearchDialogBase): def create_widgets(self): - f = SearchDialogBase.create_widgets(self) + SearchDialogBase.create_widgets(self) self.make_button("Find Next", self.default_command, 1) def default_command(self, event=None): diff --git a/Lib/idlelib/TreeWidget.py b/Lib/idlelib/TreeWidget.py --- a/Lib/idlelib/TreeWidget.py +++ b/Lib/idlelib/TreeWidget.py @@ -246,7 +246,7 @@ else: self.edit_finish() try: - label = self.label + self.label except AttributeError: # padding carefully selected (on Windows) to match Entry widget: self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -14,7 +14,6 @@ from idlelib.configHandler import idleConf from idlelib.dynOptionMenuWidget import DynOptionMenu -from idlelib.tabbedpages import TabbedPageSet from idlelib.keybindingDialog import GetKeysDialog from idlelib.configSectionNameDialog import GetCfgSectionNameDialog from idlelib.configHelpSourceEdit import GetHelpSourceDialog -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:12:21 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 May 2015 22:12:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogaWRsZWxpYjogcmVt?= =?utf-8?q?ove_unused_names_and_imports_=28one_is_a_duplicate_import=29=2E?= Message-ID: <20150514221221.1726.62648@psf.io> https://hg.python.org/cpython/rev/5386aedf3ac9 changeset: 96053:5386aedf3ac9 branch: 3.4 parent: 96050:1012a8138fcb user: Terry Jan Reedy date: Thu May 14 18:10:50 2015 -0400 summary: idlelib: remove unused names and imports (one is a duplicate import). files: Lib/idlelib/GrepDialog.py | 1 - Lib/idlelib/IOBinding.py | 5 ++--- Lib/idlelib/PyParse.py | 1 - Lib/idlelib/RemoteDebugger.py | 1 - Lib/idlelib/ScriptBinding.py | 4 +--- Lib/idlelib/SearchDialog.py | 2 +- Lib/idlelib/TreeWidget.py | 2 +- Lib/idlelib/configDialog.py | 1 - 8 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -5,7 +5,6 @@ from tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog from tkinter import Tk, Text, Button, SEL, END # for htest from idlelib import SearchEngine -import itertools from idlelib.SearchDialogBase import SearchDialogBase # Importing OutputWindow fails due to import loop # EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -1,5 +1,4 @@ import os -import types import shlex import sys import codecs @@ -525,7 +524,7 @@ if self.editwin.flist: self.editwin.update_recent_files_list(filename) -def _io_binding(parent): +def _io_binding(parent): # htest # root = Tk() root.title("Test IOBinding") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) @@ -548,7 +547,7 @@ text.pack() text.focus_set() editwin = MyEditWin(text) - io = IOBinding(editwin) + IOBinding(editwin) if __name__ == "__main__": from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/PyParse.py b/Lib/idlelib/PyParse.py --- a/Lib/idlelib/PyParse.py +++ b/Lib/idlelib/PyParse.py @@ -1,7 +1,6 @@ import re import sys from collections import Mapping -from functools import partial # Reason last stmt is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -21,7 +21,6 @@ """ import types -from idlelib import rpc from idlelib import Debugger debugging = 0 diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -18,13 +18,11 @@ """ import os -import re import string import tabnanny import tokenize import tkinter.messagebox as tkMessageBox -from idlelib.EditorWindow import EditorWindow -from idlelib import PyShell, IOBinding +from idlelib import PyShell from idlelib.configHandler import idleConf from idlelib import macosxSupport diff --git a/Lib/idlelib/SearchDialog.py b/Lib/idlelib/SearchDialog.py --- a/Lib/idlelib/SearchDialog.py +++ b/Lib/idlelib/SearchDialog.py @@ -23,7 +23,7 @@ class SearchDialog(SearchDialogBase): def create_widgets(self): - f = SearchDialogBase.create_widgets(self) + SearchDialogBase.create_widgets(self) self.make_button("Find Next", self.default_command, 1) def default_command(self, event=None): diff --git a/Lib/idlelib/TreeWidget.py b/Lib/idlelib/TreeWidget.py --- a/Lib/idlelib/TreeWidget.py +++ b/Lib/idlelib/TreeWidget.py @@ -245,7 +245,7 @@ else: self.edit_finish() try: - label = self.label + self.label except AttributeError: # padding carefully selected (on Windows) to match Entry widget: self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -16,7 +16,6 @@ from idlelib.configHandler import idleConf from idlelib.dynOptionMenuWidget import DynOptionMenu -from idlelib.tabbedpages import TabbedPageSet from idlelib.keybindingDialog import GetKeysDialog from idlelib.configSectionNameDialog import GetCfgSectionNameDialog from idlelib.configHelpSourceEdit import GetHelpSourceDialog -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:12:22 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 May 2015 22:12:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogaWRsZWxpYjogcmVt?= =?utf-8?q?ove_unused_names_and_imports_=28forgot_one=29=2E?= Message-ID: <20150514221221.27641.95659@psf.io> https://hg.python.org/cpython/rev/3fa58e779308 changeset: 96055:3fa58e779308 branch: 2.7 parent: 96052:a980da5f79f9 user: Terry Jan Reedy date: Thu May 14 18:11:50 2015 -0400 summary: idlelib: remove unused names and imports (forgot one). files: Lib/idlelib/GrepDialog.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -5,7 +5,6 @@ from Tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog from Tkinter import Tk, Text, Button, SEL, END # for htest from idlelib import SearchEngine -import itertools from idlelib.SearchDialogBase import SearchDialogBase # Importing OutputWindow fails due to import loop # EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:12:35 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 14 May 2015 22:12:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150514221221.107533.69103@psf.io> https://hg.python.org/cpython/rev/15701e89d710 changeset: 96054:15701e89d710 parent: 96051:970454df99cd parent: 96053:5386aedf3ac9 user: Terry Jan Reedy date: Thu May 14 18:11:14 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/GrepDialog.py | 1 - Lib/idlelib/IOBinding.py | 5 ++--- Lib/idlelib/PyParse.py | 1 - Lib/idlelib/RemoteDebugger.py | 1 - Lib/idlelib/ScriptBinding.py | 4 +--- Lib/idlelib/SearchDialog.py | 2 +- Lib/idlelib/TreeWidget.py | 2 +- Lib/idlelib/configDialog.py | 1 - 8 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -5,7 +5,6 @@ from tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog from tkinter import Tk, Text, Button, SEL, END # for htest from idlelib import SearchEngine -import itertools from idlelib.SearchDialogBase import SearchDialogBase # Importing OutputWindow fails due to import loop # EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -1,5 +1,4 @@ import os -import types import shlex import sys import codecs @@ -525,7 +524,7 @@ if self.editwin.flist: self.editwin.update_recent_files_list(filename) -def _io_binding(parent): +def _io_binding(parent): # htest # root = Tk() root.title("Test IOBinding") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) @@ -548,7 +547,7 @@ text.pack() text.focus_set() editwin = MyEditWin(text) - io = IOBinding(editwin) + IOBinding(editwin) if __name__ == "__main__": from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/PyParse.py b/Lib/idlelib/PyParse.py --- a/Lib/idlelib/PyParse.py +++ b/Lib/idlelib/PyParse.py @@ -1,7 +1,6 @@ import re import sys from collections import Mapping -from functools import partial # Reason last stmt is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -21,7 +21,6 @@ """ import types -from idlelib import rpc from idlelib import Debugger debugging = 0 diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -18,13 +18,11 @@ """ import os -import re import string import tabnanny import tokenize import tkinter.messagebox as tkMessageBox -from idlelib.EditorWindow import EditorWindow -from idlelib import PyShell, IOBinding +from idlelib import PyShell from idlelib.configHandler import idleConf from idlelib import macosxSupport diff --git a/Lib/idlelib/SearchDialog.py b/Lib/idlelib/SearchDialog.py --- a/Lib/idlelib/SearchDialog.py +++ b/Lib/idlelib/SearchDialog.py @@ -23,7 +23,7 @@ class SearchDialog(SearchDialogBase): def create_widgets(self): - f = SearchDialogBase.create_widgets(self) + SearchDialogBase.create_widgets(self) self.make_button("Find Next", self.default_command, 1) def default_command(self, event=None): diff --git a/Lib/idlelib/TreeWidget.py b/Lib/idlelib/TreeWidget.py --- a/Lib/idlelib/TreeWidget.py +++ b/Lib/idlelib/TreeWidget.py @@ -245,7 +245,7 @@ else: self.edit_finish() try: - label = self.label + self.label except AttributeError: # padding carefully selected (on Windows) to match Entry widget: self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -16,7 +16,6 @@ from idlelib.configHandler import idleConf from idlelib.dynOptionMenuWidget import DynOptionMenu -from idlelib.tabbedpages import TabbedPageSet from idlelib.keybindingDialog import GetKeysDialog from idlelib.configSectionNameDialog import GetCfgSectionNameDialog from idlelib.configHelpSourceEdit import GetHelpSourceDialog -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:23:01 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 22:23:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Micro-optimize_?= =?utf-8?q?=5F=5Feq=5F=5F_for_Signature=2C_Parameter_and_BoundArguments?= Message-ID: <20150514222301.27985.39244@psf.io> https://hg.python.org/cpython/rev/f0b10980b19e changeset: 96056:f0b10980b19e parent: 96054:15701e89d710 user: Yury Selivanov date: Thu May 14 18:20:01 2015 -0400 summary: inspect: Micro-optimize __eq__ for Signature, Parameter and BoundArguments Provide __ne__ method for consistency. files: Lib/inspect.py | 32 ++++++++++++++++++++++---------- 1 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2353,11 +2353,15 @@ return hash((self.name, self.kind, self.annotation, self.default)) def __eq__(self, other): - return (issubclass(other.__class__, Parameter) and - self._name == other._name and - self._kind == other._kind and - self._default == other._default and - self._annotation == other._annotation) + return (self is other or + (issubclass(other.__class__, Parameter) and + self._name == other._name and + self._kind == other._kind and + self._default == other._default and + self._annotation == other._annotation)) + + def __ne__(self, other): + return not self.__eq__(other) class BoundArguments: @@ -2441,9 +2445,13 @@ return kwargs def __eq__(self, other): - return (issubclass(other.__class__, BoundArguments) and - self.signature == other.signature and - self.arguments == other.arguments) + return (self is other or + (issubclass(other.__class__, BoundArguments) and + self.signature == other.signature and + self.arguments == other.arguments)) + + def __ne__(self, other): + return not self.__eq__(other) def __setstate__(self, state): self._signature = state['_signature'] @@ -2663,8 +2671,12 @@ return hash((params, kwo_params, return_annotation)) def __eq__(self, other): - return (isinstance(other, Signature) and - self._hash_basis() == other._hash_basis()) + return (self is other or + (isinstance(other, Signature) and + self._hash_basis() == other._hash_basis())) + + def __ne__(self, other): + return not self.__eq__(other) def _bind(self, args, kwargs, *, partial=False): """Private method. Don't use directly.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:33:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 22:33:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Test_that_Bound?= =?utf-8?q?Arguments=2E=5F=5Feq=5F=5F_repects_the_order_of_params?= Message-ID: <20150514223335.27983.92698@psf.io> https://hg.python.org/cpython/rev/5a40fb5ad890 changeset: 96057:5a40fb5ad890 parent: 96054:15701e89d710 user: Yury Selivanov date: Thu May 14 18:30:27 2015 -0400 summary: inspect: Test that BoundArguments.__eq__ repects the order of params files: Lib/test/test_inspect.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3133,6 +3133,12 @@ ba4 = inspect.signature(bar).bind(1) self.assertNotEqual(ba, ba4) + def foo(*, a, b): pass + sig = inspect.signature(foo) + ba1 = sig.bind(a=1, b=2) + ba2 = sig.bind(b=2, a=1) + self.assertEqual(ba1, ba2) + def test_signature_bound_arguments_pickle(self): def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass sig = inspect.signature(foo) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:33:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 22:33:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <20150514223335.4511.61471@psf.io> https://hg.python.org/cpython/rev/1cdcce187c43 changeset: 96058:1cdcce187c43 parent: 96057:5a40fb5ad890 parent: 96056:f0b10980b19e user: Yury Selivanov date: Thu May 14 18:33:14 2015 -0400 summary: Merge files: Lib/inspect.py | 32 ++++++++++++++++++++++---------- 1 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2353,11 +2353,15 @@ return hash((self.name, self.kind, self.annotation, self.default)) def __eq__(self, other): - return (issubclass(other.__class__, Parameter) and - self._name == other._name and - self._kind == other._kind and - self._default == other._default and - self._annotation == other._annotation) + return (self is other or + (issubclass(other.__class__, Parameter) and + self._name == other._name and + self._kind == other._kind and + self._default == other._default and + self._annotation == other._annotation)) + + def __ne__(self, other): + return not self.__eq__(other) class BoundArguments: @@ -2441,9 +2445,13 @@ return kwargs def __eq__(self, other): - return (issubclass(other.__class__, BoundArguments) and - self.signature == other.signature and - self.arguments == other.arguments) + return (self is other or + (issubclass(other.__class__, BoundArguments) and + self.signature == other.signature and + self.arguments == other.arguments)) + + def __ne__(self, other): + return not self.__eq__(other) def __setstate__(self, state): self._signature = state['_signature'] @@ -2663,8 +2671,12 @@ return hash((params, kwo_params, return_annotation)) def __eq__(self, other): - return (isinstance(other, Signature) and - self._hash_basis() == other._hash_basis()) + return (self is other or + (isinstance(other, Signature) and + self._hash_basis() == other._hash_basis())) + + def __ne__(self, other): + return not self.__eq__(other) def _bind(self, args, kwargs, *, partial=False): """Private method. Don't use directly.""" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 00:47:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 14 May 2015 22:47:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_22547=3A_Implement_i?= =?utf-8?q?nformative_=5F=5Frepr=5F=5F_for_inspect=2EBoundArguments?= Message-ID: <20150514224722.31578.49994@psf.io> https://hg.python.org/cpython/rev/a444464a2e87 changeset: 96059:a444464a2e87 user: Yury Selivanov date: Thu May 14 18:47:17 2015 -0400 summary: Issue 22547: Implement informative __repr__ for inspect.BoundArguments files: Lib/inspect.py | 7 +++++++ Lib/test/test_inspect.py | 7 +++++++ Misc/NEWS | 3 +++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2460,6 +2460,13 @@ def __getstate__(self): return {'_signature': self._signature, 'arguments': self.arguments} + def __repr__(self): + args = [] + for arg, value in self.arguments.items(): + args.append('{}={!r}'.format(arg, value)) + return '<{} at {:#x} ({})>'.format(self.__class__.__name__, + id(self), ', '.join(args)) + class Signature: """A Signature object represents the overall signature of a function. diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3149,6 +3149,13 @@ ba_pickled = pickle.loads(pickle.dumps(ba, ver)) self.assertEqual(ba, ba_pickled) + def test_signature_bound_arguments_repr(self): + def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass + sig = inspect.signature(foo) + ba = sig.bind(20, 30, z={}) + self.assertRegex(repr(ba), + r'') + class TestSignaturePrivateHelpers(unittest.TestCase): def test_signature_get_bound_param(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -125,6 +125,9 @@ - Issue 24184: Add AsyncIterator and AsyncIterable ABCs to collections.abc. Contributed by Yury Selivanov. +- Issue 22547: Implement informative __repr__ for inspect.BoundArguments. + Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 04:05:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 15 May 2015 02:05:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Mention_AsyncItera?= =?utf-8?q?tor_and_AsyncIterable_ABCs=2E?= Message-ID: <20150515020527.1737.42372@psf.io> https://hg.python.org/peps/rev/8f453d25770c changeset: 5851:8f453d25770c user: Yury Selivanov date: Thu May 14 22:05:24 2015 -0400 summary: pep-492: Mention AsyncIterator and AsyncIterable ABCs. files: pep-0492.txt | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -710,6 +710,14 @@ implement ``send(value)``, ``throw(type, exc, tb)``, and ``close()`` methods. +To allow easy testing if objects support asynchronous iteration, two +more ABCs are added: + +* ``collections.abc.AsyncIterable`` -- tests for ``__aiter__`` method. + +* ``collections.abc.AsyncIterator`` -- tests for ``__aiter__`` and + ``__anext__`` methods. + Glossary ======== @@ -1329,8 +1337,9 @@ 7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. -8. New ABCs: ``collections.abc.Awaitable`` and - ``collections.abc.Coroutine``. +8. New ABCs: ``collections.abc.Awaitable``, + ``collections.abc.Coroutine``, ``collections.abc.AsyncIterable``, and + ``collections.abc.AsyncIterator``. While the list of changes and new things is not short, it is important to understand, that most users will not use these features directly. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 15 04:36:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 15 May 2015 02:36:33 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0455=3A_Update_status=2E?= Message-ID: <20150515023633.31558.44632@psf.io> https://hg.python.org/peps/rev/1c2304cab236 changeset: 5852:1c2304cab236 user: Yury Selivanov date: Thu May 14 22:36:30 2015 -0400 summary: pep-0455: Update status. files: pep-0455.txt | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/pep-0455.txt b/pep-0455.txt --- a/pep-0455.txt +++ b/pep-0455.txt @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Antoine Pitrou BDFL-Delegate: Raymond Hettinger -Status: Draft +Status: Rejected Type: Standards Track Content-Type: text/x-rst Created: 13-Sep-2013 @@ -20,6 +20,11 @@ which transforms the key using a given function when doing a lookup, but retains the original key when reading. +Rejection +--------- + +See https://mail.python.org/pipermail/python-dev/2015-May/140003.html + Rationale ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 15 09:13:08 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 15 May 2015 07:13:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_os_module_doc=3A_remove_av?= =?utf-8?q?ailability_when_useless?= Message-ID: <20150515071308.4531.504@psf.io> https://hg.python.org/cpython/rev/77ebd3720284 changeset: 96060:77ebd3720284 user: Victor Stinner date: Fri May 15 09:11:59 2015 +0200 summary: os module doc: remove availability when useless Remove "Availability: Unix, Windows." from os module documentation for functions available on all platforms. files: Doc/library/os.rst | 58 ---------------------------------- 1 files changed, 0 insertions(+), 58 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -312,8 +312,6 @@ Return the current process id. - Availability: Unix, Windows. - .. function:: getppid() @@ -550,8 +548,6 @@ On platforms where :c:func:`strerror` returns ``NULL`` when given an unknown error number, :exc:`ValueError` is raised. - Availability: Unix, Windows. - .. data:: supports_bytes_environ @@ -565,8 +561,6 @@ Set the current numeric umask and return the previous umask. - Availability: Unix, Windows. - .. function:: uname() @@ -657,8 +651,6 @@ Close file descriptor *fd*. - Availability: Unix, Windows. - .. note:: This function is intended for low-level I/O and must be applied to a file @@ -678,8 +670,6 @@ except OSError: pass - Availability: Unix, Windows. - .. function:: device_encoding(fd) @@ -696,8 +686,6 @@ 2: stderr), the new file descriptor is :ref:`inheritable `. - Availability: Unix, Windows. - .. versionchanged:: 3.4 The new file descriptor is now non-inheritable. @@ -708,8 +696,6 @@ The file descriptor *fd2* is :ref:`inheritable ` by default, or non-inheritable if *inheritable* is ``False``. - Availability: Unix, Windows. - .. versionchanged:: 3.4 Add the optional *inheritable* parameter. @@ -775,8 +761,6 @@ The :func:`.stat` function. - Availability: Unix, Windows. - .. function:: fstatvfs(fd) @@ -860,8 +844,6 @@ current position; :const:`SEEK_END` or ``2`` to set it relative to the end of the file. Return the new cursor position in bytes, starting from the beginning. - Availability: Unix, Windows. - .. data:: SEEK_SET SEEK_CUR @@ -870,8 +852,6 @@ Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, respectively. - Availability: Unix, Windows. - .. versionadded:: 3.3 Some operating systems could support additional values, like :data:`os.SEEK_HOLE` or :data:`os.SEEK_DATA`. @@ -892,8 +872,6 @@ This function can support :ref:`paths relative to directory descriptors ` with the *dir_fd* parameter. - Availability: Unix, Windows. - .. versionchanged:: 3.4 The new file descriptor is now non-inheritable. @@ -1079,8 +1057,6 @@ bytes read. If the end of the file referred to by *fd* has been reached, an empty bytes object is returned. - Availability: Unix, Windows. - .. note:: This function is intended for low-level I/O and must be applied to a file @@ -1199,8 +1175,6 @@ Write the bytestring in *str* to file descriptor *fd*. Return the number of bytes actually written. - Availability: Unix, Windows. - .. note:: This function is intended for low-level I/O and must be applied to a file @@ -1376,8 +1350,6 @@ or not it is available using :data:`os.supports_effective_ids`. If it is unavailable, using it will raise a :exc:`NotImplementedError`. - Availability: Unix, Windows. - .. note:: Using :func:`access` to check if a user is authorized to e.g. open a file @@ -1430,8 +1402,6 @@ This function can support :ref:`specifying a file descriptor `. The descriptor must refer to an opened directory, not an open file. - Availability: Unix, Windows. - .. versionadded:: 3.3 Added support for specifying *path* as a file descriptor on some platforms. @@ -1493,8 +1463,6 @@ :ref:`paths relative to directory descriptors ` and :ref:`not following symlinks `. - Availability: Unix, Windows. - .. note:: Although Windows supports :func:`chmod`, you can only set the file's @@ -1545,15 +1513,11 @@ Return a string representing the current working directory. - Availability: Unix, Windows. - .. function:: getcwdb() Return a bytestring representing the current working directory. - Availability: Unix, Windows. - .. function:: lchflags(path, flags) @@ -1616,8 +1580,6 @@ .. note:: To encode ``str`` filenames to ``bytes``, use :func:`~os.fsencode`. - Availability: Unix, Windows. - .. seealso:: The :func:`scandir` function returns the directory entries with more @@ -1670,8 +1632,6 @@ It is also possible to create temporary directories; see the :mod:`tempfile` module's :func:`tempfile.mkdtemp` function. - Availability: Unix, Windows. - .. versionadded:: 3.3 The *dir_fd* argument. @@ -1830,8 +1790,6 @@ This function is identical to :func:`unlink`. - Availability: Unix, Windows. - .. versionadded:: 3.3 The *dir_fd* argument. @@ -1865,8 +1823,6 @@ If you want cross-platform overwriting of the destination, use :func:`replace`. - Availability: Unix, Windows. - .. versionadded:: 3.3 The *src_dir_fd* and *dst_dir_fd* arguments. @@ -1895,8 +1851,6 @@ This function can support specifying *src_dir_fd* and/or *dst_dir_fd* to supply :ref:`paths relative to directory descriptors `. - Availability: Unix, Windows. - .. versionadded:: 3.3 @@ -1909,8 +1863,6 @@ This function can support :ref:`paths relative to directory descriptors `. - Availability: Unix, Windows. - .. versionadded:: 3.3 The *dir_fd* parameter. @@ -2113,8 +2065,6 @@ >>> statinfo.st_size 264 - Availability: Unix, Windows. - .. seealso:: :func:`fstat` and :func:`lstat` functions. @@ -2508,8 +2458,6 @@ name. Please see the documentation for :func:`remove` for further information. - Availability: Unix, Windows. - .. versionadded:: 3.3 The *dir_fd* parameter. @@ -2546,8 +2494,6 @@ :ref:`paths relative to directory descriptors ` and :ref:`not following symlinks `. - Availability: Unix, Windows. - .. versionadded:: 3.3 Added support for specifying an open file descriptor for *path*, and the *dir_fd*, *follow_symlinks*, and *ns* parameters. @@ -2799,8 +2745,6 @@ Python signal handler registered for :const:`SIGABRT` with :func:`signal.signal`. - Availability: Unix, Windows. - .. function:: execl(path, arg0, arg1, ...) execle(path, arg0, arg1, ..., env) @@ -2864,8 +2808,6 @@ Exit the process with status *n*, without calling cleanup handlers, flushing stdio buffers, etc. - Availability: Unix, Windows. - .. note:: The standard way to exit is ``sys.exit(n)``. :func:`_exit` should -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 09:13:08 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 15 May 2015 07:13:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2324013=3A_Improve?= =?utf-8?q?_os=2Escandir=28=29_and_DirEntry_documentation?= Message-ID: <20150515071308.27993.58387@psf.io> https://hg.python.org/cpython/rev/e7c7431f91b2 changeset: 96061:e7c7431f91b2 user: Victor Stinner date: Fri May 15 09:12:58 2015 +0200 summary: Closes #24013: Improve os.scandir() and DirEntry documentation Patch written by Ben Hoyt. files: Doc/library/os.rst | 178 ++++++++++++++++---------------- 1 files changed, 88 insertions(+), 90 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1582,8 +1582,9 @@ .. seealso:: - The :func:`scandir` function returns the directory entries with more - information than just the name. + The :func:`scandir` function returns directory entries along with + file attribute information, giving better performance for many + common use cases. .. versionchanged:: 3.2 The *path* parameter became optional. @@ -1873,21 +1874,27 @@ in the directory given by *path*. The entries are yielded in arbitrary order, and the special entries ``'.'`` and ``'..'`` are not included. - On Windows, *path* must of type :class:`str`. On POSIX, *path* can be of - type :class:`str` or :class:`bytes`. If *path* is of type :class:`bytes`, - the :attr:`~DirEntry.name` and :attr:`~DirEntry.path` attributes of - :class:`DirEntry` are also of type ``bytes``. Use :func:`~os.fsencode` and - :func:`~os.fsdecode` to encode and decode paths. - - The :func:`scandir` function is recommended, instead of :func:`listdir`, - when the file type of entries is used. In most cases, the file type of a - :class:`DirEntry` is retrieved directly by :func:`scandir`, no system call - is required. If only the name of entries is used, :func:`listdir` can - be more efficient than :func:`scandir`. + Using :func:`scandir` instead of :func:`listdir` can significantly + increase the performance of code that also needs file type or file + attribute information, because :class:`DirEntry` objects expose this + information if the operating system provides it when scanning a directory. + All :class:`DirEntry` methods may perform a system call, but + :func:`~DirEntry.is_dir` and :func:`~DirEntry.is_file` usually only + require a system call for symbolic links; :func:`DirEntry.stat` + always requires a system call on Unix but only requires one for + symbolic links on Windows. + + On Unix, *path* can be of type :class:`str` or :class:`bytes` (use + :func:`~os.fsencode` and :func:`~os.fsdecode` to encode and decode + :class:`bytes` paths). On Windows, *path* must be of type :class:`str`. + On both sytems, the type of the :attr:`~DirEntry.name` and + :attr:`~DirEntry.path` attributes of each :class:`DirEntry` will be of + the same type as *path*. The following example shows a simple use of :func:`scandir` to display all - the files excluding directories in the given *path* that don't start with - ``'.'``:: + the files (excluding directories) in the given *path* that don't start with + ``'.'``. The ``entry.is_file()`` call will generally not make an additional + system call:: for entry in os.scandir(path): if not entry.name.startswith('.') and entry.is_file(): @@ -1905,10 +1912,6 @@ `FindNextFileW `_ functions. - .. seealso:: - - The :func:`listdir` function returns the names of the directory entries. - .. versionadded:: 3.5 @@ -1919,7 +1922,7 @@ :func:`scandir` will provide as much of this information as possible without making additional system calls. When a ``stat()`` or ``lstat()`` system call - is made, the ``DirEntry`` object cache the result . + is made, the ``DirEntry`` object will cache the result. ``DirEntry`` instances are not intended to be stored in long-lived data structures; if you know the file metadata has changed or if a long time has @@ -1927,10 +1930,7 @@ up-to-date information. Because the ``DirEntry`` methods can make operating system calls, they may - also raise :exc:`OSError`. For example, if a file is deleted between calling - :func:`scandir` and calling :func:`DirEntry.stat`, a - :exc:`FileNotFoundError` exception can be raised. Unfortunately, the - behaviour on errors depends on the platform. If you need very fine-grained + also raise :exc:`OSError`. If you need very fine-grained control over errors, you can catch :exc:`OSError` when calling one of the ``DirEntry`` methods and handle as appropriate. @@ -1941,100 +1941,99 @@ The entry's base filename, relative to the :func:`scandir` *path* argument. - The :attr:`name` type is :class:`str`. On POSIX, it can be of type - :class:`bytes` if the type of the :func:`scandir` *path* argument is also - :class:`bytes`. Use :func:`~os.fsdecode` to decode the name. + The :attr:`name` attribute will be of the same type (``str`` or + ``bytes``) as the :func:`scandir` *path* argument. Use + :func:`~os.fsdecode` to decode byte filenames. .. attribute:: path The entry's full path name: equivalent to ``os.path.join(scandir_path, entry.name)`` where *scandir_path* is the :func:`scandir` *path* argument. The path is only absolute if the :func:`scandir` *path* - argument is absolute. - - The :attr:`name` type is :class:`str`. On POSIX, it can be of type - :class:`bytes` if the type of the :func:`scandir` *path* argument is also - :class:`bytes`. Use :func:`~os.fsdecode` to decode the path. + argument was absolute. + + The :attr:`path` attribute will be of the same type (``str`` or + ``bytes``) as the :func:`scandir` *path* argument. Use + :func:`~os.fsdecode` to decode byte filenames. .. method:: inode() Return the inode number of the entry. - The result is cached in the object, use ``os.stat(entry.path, + The result is cached on the ``DirEntry`` object, use ``os.stat(entry.path, follow_symlinks=False).st_ino`` to fetch up-to-date information. - On POSIX, no system call is required. + On Unix, no system call is required. .. method:: is_dir(\*, follow_symlinks=True) If *follow_symlinks* is ``True`` (the default), return ``True`` if the - entry is a directory or a symbolic link pointing to a directory, - return ``False`` if it points to another kind of file, if it doesn't - exist anymore or if it is a broken symbolic link. + entry is a directory or a symbolic link pointing to a directory; + return ``False`` if it is or points to any other kind of file, or if it + doesn't exist anymore. If *follow_symlinks* is ``False``, return ``True`` only if this entry - is a directory, return ``False`` if it points to a symbolic link or - another kind of file, if the entry doesn't exist anymore or if it is a - broken symbolic link - - The result is cached in the object. Call :func:`stat.S_ISDIR` with - :func:`os.stat` to fetch up-to-date information. + is a directory; return ``False`` if it is any other kind of file + or if it doesn't exist anymore. + + The result is cached on the ``DirEntry`` object. Call :func:`os.stat` + along with :func:`stat.S_ISDIR` to fetch up-to-date information. + + This method can raise :exc:`OSError`, such as :exc:`PermissionError`, + but :exc:`FileNotFoundError` is caught and not raised. + + In most cases, no system call is required. + + .. method:: is_file(\*, follow_symlinks=True) + + If *follow_symlinks* is ``True`` (the default), return ``True`` if the + entry is a file or a symbolic link pointing to a file; return ``False`` + if it is or points to a directory or other non-file entry, or if it + doesn't exist anymore. + + If *follow_symlinks* is ``False``, return ``True`` only if this entry + is a file; return ``False`` if it is a directory or other non-file entry, + or if it doesn't exist anymore. + + The result is cached on the ``DirEntry`` object. Call :func:`os.stat` + along with :func:`stat.S_ISREG` to fetch up-to-date information. + + This method can raise :exc:`OSError`, such as :exc:`PermissionError`, + but :exc:`FileNotFoundError` is caught and not raised. + + In most cases, no system call is required. + + .. method:: is_symlink() + + Return ``True`` if this entry is a symbolic link (even if broken); + return ``False`` if it points to a directory or any kind of file, + or if it doesn't exist anymore. + + The result is cached on the ``DirEntry`` object. Call + :func:`os.path.islink` to fetch up-to-date information. The method can raise :exc:`OSError`, such as :exc:`PermissionError`, - but :exc:`FileNotFoundError` is catched. + but :exc:`FileNotFoundError` is caught and not raised. In most cases, no system call is required. - .. method:: is_file(\*, follow_symlinks=True) - - If *follow_symlinks* is ``True`` (the default), return ``True`` if the - entry is a regular file or a symbolic link pointing to a regular file, - return ``False`` if it points to another kind of file, if it doesn't - exist anymore or if it is a broken symbolic link. - - If *follow_symlinks* is ``False``, return ``True`` only if this entry - is a regular file, return ``False`` if it points to a symbolic link or - another kind of file, if it doesn't exist anymore or if it is a broken - symbolic link. - - The result is cached in the object. Call :func:`stat.S_ISREG` with - :func:`os.stat` to fetch up-to-date information. - - The method can raise :exc:`OSError`, such as :exc:`PermissionError`, - but :exc:`FileNotFoundError` is catched. - - In most cases, no system call is required. - - .. method:: is_symlink() - - Return ``True`` if this entry is a symbolic link or a broken symbolic - link, return ``False`` if it points to a another kind of file or if the - entry doesn't exist anymore. - - The result is cached in the object. Call :func:`os.path.islink` to fetch - up-to-date information. - - The method can raise :exc:`OSError`, such as :exc:`PermissionError`, - but :exc:`FileNotFoundError` is catched. - - In most cases, no system call is required. - .. method:: stat(\*, follow_symlinks=True) - Return a :class:`stat_result` object for this entry. This function - normally follows symbolic links; to stat a symbolic link add the - argument ``follow_symlinks=False``. + Return a :class:`stat_result` object for this entry. This method + follows symbolic links by default; to stat a symbolic link add the + ``follow_symlinks=False`` argument. + + On Unix, this method always requires a system call. On Windows, + ``DirEntry.stat()`` requires a system call only if the + entry is a symbolic link, and ``DirEntry.stat(follow_symlinks=False)`` + never requires a system call. On Windows, the ``st_ino``, ``st_dev`` and ``st_nlink`` attributes of the :class:`stat_result` are always set to zero. Call :func:`os.stat` to get these attributes. - The result is cached in the object. Call :func:`os.stat` to fetch - up-to-date information. - - On Windows, ``DirEntry.stat(follow_symlinks=False)`` doesn't require a - system call. ``DirEntry.stat()`` requires a system call if the entry is a - symbolic link. + The result is cached on the ``DirEntry`` object. Call :func:`os.stat` + to fetch up-to-date information. .. versionadded:: 3.5 @@ -2585,9 +2584,8 @@ os.rmdir(os.path.join(root, name)) .. versionchanged:: 3.5 - The function now calls :func:`os.scandir` instead of :func:`os.listdir`. - The usage of :func:`os.scandir` reduces the number of calls to - :func:`os.stat`. + This function now calls :func:`os.scandir` instead of :func:`os.listdir`, + making it faster by reducing the number of calls to :func:`os.stat`. .. function:: fwalk(top='.', topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri May 15 10:42:19 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 15 May 2015 08:42:19 +0000 Subject: [Python-checkins] Daily reference leaks (a444464a2e87): sum=4 Message-ID: <20150515084218.107529.75790@psf.io> results for a444464a2e87 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogLNAKnp', '--timeout', '7200'] From python-checkins at python.org Fri May 15 18:19:45 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 15 May 2015 16:19:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_deque_is_not_v?= =?utf-8?q?arsized=2C_so_using_Py=5FSIZE_is_nonsensical_=28closes_=2324162?= =?utf-8?q?=29?= Message-ID: <20150515161944.4507.77565@psf.io> https://hg.python.org/cpython/rev/7adfc99103d2 changeset: 96062:7adfc99103d2 branch: 2.7 parent: 95938:b99d50fde755 user: Benjamin Peterson date: Fri May 15 12:19:18 2015 -0400 summary: deque is not varsized, so using Py_SIZE is nonsensical (closes #24162) files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -708,7 +708,7 @@ PyObject *item; int rv; - assert (i >= 0 && i < Py_SIZE(deque)); + assert (i >= 0 && i < deque->len); if (_deque_rotate(deque, -i)) return -1; item = deque_popleft(deque, NULL); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 18:19:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 15 May 2015 16:19:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge_2=2E7=2E10_release_branch?= Message-ID: <20150515161944.107511.64080@psf.io> https://hg.python.org/cpython/rev/81c3a75e0307 changeset: 96063:81c3a75e0307 branch: 2.7 parent: 96055:3fa58e779308 parent: 96062:7adfc99103d2 user: Benjamin Peterson date: Fri May 15 12:19:41 2015 -0400 summary: merge 2.7.10 release branch files: Modules/_collectionsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -708,7 +708,7 @@ PyObject *item; int rv; - assert (i >= 0 && i < Py_SIZE(deque)); + assert (i >= 0 && i < deque->len); if (_deque_rotate(deque, -i)) return -1; item = deque_popleft(deque, NULL); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 18:54:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 15 May 2015 16:54:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Remove_=220x=2E?= =?utf-8?q?=2E=2E=22_IDs_from_Signature_objects=27_=5F=5Frepr=5F=5F?= Message-ID: <20150515165400.1721.49084@psf.io> https://hg.python.org/cpython/rev/d72d31f4b69a changeset: 96064:d72d31f4b69a parent: 96061:e7c7431f91b2 user: Yury Selivanov date: Fri May 15 12:53:56 2015 -0400 summary: inspect: Remove "0x..." IDs from Signature objects' __repr__ Issue 24200. files: Lib/inspect.py | 9 +++------ Lib/test/test_inspect.py | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2346,8 +2346,7 @@ return formatted def __repr__(self): - return '<{} at {:#x} "{}">'.format(self.__class__.__name__, - id(self), self) + return '<{} "{}">'.format(self.__class__.__name__, self) def __hash__(self): return hash((self.name, self.kind, self.annotation, self.default)) @@ -2464,8 +2463,7 @@ args = [] for arg, value in self.arguments.items(): args.append('{}={!r}'.format(arg, value)) - return '<{} at {:#x} ({})>'.format(self.__class__.__name__, - id(self), ', '.join(args)) + return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args)) class Signature: @@ -2835,8 +2833,7 @@ self._return_annotation = state['_return_annotation'] def __repr__(self): - return '<{} at {:#x} "{}">'.format(self.__class__.__name__, - id(self), self) + return '<{} {}>'.format(self.__class__.__name__, self) def __str__(self): result = [] diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3153,8 +3153,7 @@ def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass sig = inspect.signature(foo) ba = sig.bind(20, 30, z={}) - self.assertRegex(repr(ba), - r'') + self.assertRegex(repr(ba), r'') class TestSignaturePrivateHelpers(unittest.TestCase): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 18:55:25 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 15 May 2015 16:55:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24200=3A_Fix_broken_?= =?utf-8?q?unittest=2E?= Message-ID: <20150515165524.31572.9819@psf.io> https://hg.python.org/cpython/rev/f23d0a4278aa changeset: 96065:f23d0a4278aa user: Yury Selivanov date: Fri May 15 12:55:20 2015 -0400 summary: Issue 24200: Fix broken unittest. files: Lib/test/test_inspect.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1793,7 +1793,7 @@ S((pkd, pk)) self.assertTrue(repr(sig).startswith(' {42:'ham'}: pass -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 15 19:25:12 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 15 May 2015 17:25:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_link_to_an_earlier_part?= =?utf-8?q?ial_review=2E?= Message-ID: <20150515172512.113178.93064@psf.io> https://hg.python.org/peps/rev/ee559992bbe4 changeset: 5853:ee559992bbe4 user: Raymond Hettinger date: Fri May 15 10:25:04 2015 -0700 summary: Add a link to an earlier partial review. files: pep-0455.txt | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pep-0455.txt b/pep-0455.txt --- a/pep-0455.txt +++ b/pep-0455.txt @@ -23,8 +23,10 @@ Rejection --------- -See https://mail.python.org/pipermail/python-dev/2015-May/140003.html - +See the rationale at +https://mail.python.org/pipermail/python-dev/2015-May/140003.html +and for a earlier partial review, see +https://mail.python.org/pipermail/python-dev/2013-October/129937.html . Rationale ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 15 21:11:17 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 15 May 2015 19:11:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixes_default_per-user_ins?= =?utf-8?q?tall_precompiling_the_standard_library=2E?= Message-ID: <20150515191111.13245.66218@psf.io> https://hg.python.org/cpython/rev/b6fa81bcf118 changeset: 96066:b6fa81bcf118 user: Steve Dower date: Fri May 15 12:10:53 2015 -0700 summary: Fixes default per-user install precompiling the standard library. files: Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 13 ++++++--- 1 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -302,10 +302,17 @@ case ID_INSTALL_JUST_FOR_ME_BUTTON: SavePageSettings(); - + + if (!QueryElevateForCrtInstall()) { + break; + } + hr = _engine->SetVariableNumeric(L"InstallAllUsers", 0); ExitOnFailure(hr, L"Failed to set install scope"); + hr = _engine->SetVariableNumeric(L"CompileAll", 0); + ExitOnFailure(hr, L"Failed to unset CompileAll"); + hr = BalGetStringVariable(L"DefaultJustForMeTargetDir", &defaultDir); BalExitOnFailure(hr, "Failed to get the default per-user install directory"); @@ -320,10 +327,6 @@ ReleaseStr(targetDir); BalExitOnFailure(hr, "Failed to set install target directory"); - if (!QueryElevateForCrtInstall()) { - break; - } - OnPlan(BOOTSTRAPPER_ACTION_INSTALL); break; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 01:17:28 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 15 May 2015 23:17:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324064=3A__Docueme?= =?utf-8?q?nt_that_oroperty_docstrings_are_now_writeable=2E?= Message-ID: <20150515231710.44673.1288@psf.io> https://hg.python.org/cpython/rev/5262dd507ee5 changeset: 96067:5262dd507ee5 user: Raymond Hettinger date: Fri May 15 16:17:05 2015 -0700 summary: Issue #24064: Docuement that oroperty docstrings are now writeable. files: Doc/library/functions.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1193,6 +1193,9 @@ The returned property object also has the attributes ``fget``, ``fset``, and ``fdel`` corresponding to the constructor arguments. + .. versionchanged:: 3.5 + The docstrings of property objects are now writeable. + .. _func-range: .. function:: range(stop) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 02:53:59 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 16 May 2015 00:53:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_code_clean-up=2E?= Message-ID: <20150516005359.26850.98206@psf.io> https://hg.python.org/cpython/rev/e03987f2d274 changeset: 96068:e03987f2d274 user: Raymond Hettinger date: Fri May 15 17:53:52 2015 -0700 summary: Minor code clean-up. files: Modules/_heapqmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -261,8 +261,8 @@ int i = 0; while (n > 1) { - i += 1; n >>= 1; + i++; } return n << i; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:04:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:04:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMTg0?= =?utf-8?q?=3A_idlelib=2C_remove_more_unused_names_and_imports=2E?= Message-ID: <20150516030421.4247.9700@psf.io> https://hg.python.org/cpython/rev/777569dd4bca changeset: 96070:777569dd4bca branch: 3.4 parent: 96053:5386aedf3ac9 user: Terry Jan Reedy date: Fri May 15 23:03:17 2015 -0400 summary: Issue #23184: idlelib, remove more unused names and imports. files: Lib/idlelib/EditorWindow.py | 4 +--- Lib/idlelib/PyShell.py | 17 +++++++---------- Lib/idlelib/RemoteDebugger.py | 2 +- Lib/idlelib/ScriptBinding.py | 1 - Lib/idlelib/macosxSupport.py | 4 +--- Lib/idlelib/run.py | 2 -- 6 files changed, 10 insertions(+), 20 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -13,7 +13,6 @@ import webbrowser from idlelib.MultiCall import MultiCallCreator -from idlelib import idlever from idlelib import WindowList from idlelib import SearchDialog from idlelib import GrepDialog @@ -125,7 +124,6 @@ EditorWindow.help_url = 'file://' + EditorWindow.help_url else: EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2] - currentTheme=idleConf.CurrentTheme() self.flist = flist root = root or flist.root self.root = root @@ -714,7 +712,7 @@ cmd = [sys.executable, '-c', 'from turtledemo.__main__ import main; main()'] - p = subprocess.Popen(cmd, shell=False) + subprocess.Popen(cmd, shell=False) def gotoline(self, lineno): if lineno is not None and lineno > 0: diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -10,8 +10,6 @@ import threading import time import tokenize -import traceback -import types import io import linecache @@ -32,7 +30,6 @@ from idlelib.UndoDelegator import UndoDelegator from idlelib.OutputWindow import OutputWindow from idlelib.configHandler import idleConf -from idlelib import idlever from idlelib import rpc from idlelib import Debugger from idlelib import RemoteDebugger @@ -166,7 +163,7 @@ filename = self.io.filename text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) try: - i = self.breakpoints.index(lineno) + self.breakpoints.index(lineno) except ValueError: # only add if missing, i.e. do once self.breakpoints.append(lineno) try: # update the subprocess debugger @@ -427,7 +424,7 @@ try: self.rpcclt = MyRPCClient(addr) break - except OSError as err: + except OSError: pass else: self.display_port_binding_error() @@ -448,7 +445,7 @@ self.rpcclt.listening_sock.settimeout(10) try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.rpcclt.register("console", self.tkconsole) @@ -483,7 +480,7 @@ self.spawn_subprocess() try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.transfer_path(with_cwd=with_cwd) @@ -501,7 +498,7 @@ # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI - gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) + RemoteDebugger.restart_subprocess_debugger(self.rpcclt) # reload remote debugger breakpoints for all PyShellEditWindows debug.load_breakpoints() self.compile.compiler.flags = self.original_compiler_flags @@ -1231,7 +1228,7 @@ while i > 0 and line[i-1] in " \t": i = i-1 line = line[:i] - more = self.interp.runsource(line) + self.interp.runsource(line) def open_stack_viewer(self, event=None): if self.interp.rpcclt: @@ -1245,7 +1242,7 @@ master=self.text) return from idlelib.StackViewer import StackBrowser - sv = StackBrowser(self.root, self.flist) + StackBrowser(self.root, self.flist) def view_restart_mark(self, event=None): self.text.see("iomark") diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -98,7 +98,7 @@ else: tb = tracebacktable[tbid] stack, i = self.idb.get_stack(frame, tb) - stack = [(wrap_frame(frame), k) for frame, k in stack] + stack = [(wrap_frame(frame2), k) for frame2, k in stack] return stack, i def run(self, cmd): diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -18,7 +18,6 @@ """ import os -import string import tabnanny import tokenize import tkinter.messagebox as tkMessageBox diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -123,11 +123,9 @@ # # Due to a (mis-)feature of TkAqua the user will also see an empty Help # menu. - from tkinter import Menu, Text, Text - from idlelib.EditorWindow import prepstr, get_accelerator + from tkinter import Menu from idlelib import Bindings from idlelib import WindowList - from idlelib.MultiCall import MultiCallCreator closeItem = Bindings.menudefs[0][1][-2] diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,8 +1,6 @@ import sys -import io import linecache import time -import socket import traceback import _thread as thread import threading -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:04:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:04:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMTg0?= =?utf-8?q?=3A_idlelib=2C_remove_more_unused_names_and_imports=2E?= Message-ID: <20150516030421.21156.60969@psf.io> https://hg.python.org/cpython/rev/d50d661a08f5 changeset: 96069:d50d661a08f5 branch: 2.7 parent: 96063:81c3a75e0307 user: Terry Jan Reedy date: Fri May 15 23:03:11 2015 -0400 summary: Issue #23184: idlelib, remove more unused names and imports. files: Lib/idlelib/EditorWindow.py | 2 -- Lib/idlelib/PyShell.py | 19 ++++++++----------- Lib/idlelib/RemoteDebugger.py | 2 +- Lib/idlelib/macosxSupport.py | 4 +--- Lib/idlelib/run.py | 1 - 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -9,7 +9,6 @@ import webbrowser from idlelib.MultiCall import MultiCallCreator -from idlelib import idlever from idlelib import WindowList from idlelib import SearchDialog from idlelib import GrepDialog @@ -154,7 +153,6 @@ EditorWindow.help_url = 'file://' + EditorWindow.help_url else: EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2] - currentTheme=idleConf.CurrentTheme() self.flist = flist root = root or flist.root self.root = root diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -10,8 +10,6 @@ import socket import time import threading -import traceback -import types import io import linecache @@ -32,7 +30,6 @@ from idlelib.UndoDelegator import UndoDelegator from idlelib.OutputWindow import OutputWindow from idlelib.configHandler import idleConf -from idlelib import idlever from idlelib import rpc from idlelib import Debugger from idlelib import RemoteDebugger @@ -171,7 +168,7 @@ filename = self.io.filename text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) try: - i = self.breakpoints.index(lineno) + self.breakpoints.index(lineno) except ValueError: # only add if missing, i.e. do once self.breakpoints.append(lineno) try: # update the subprocess debugger @@ -439,7 +436,7 @@ try: self.rpcclt = MyRPCClient(addr) break - except socket.error as err: + except socket.error: pass else: self.display_port_binding_error() @@ -460,7 +457,7 @@ self.rpcclt.listening_sock.settimeout(10) try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.rpcclt.register("console", self.tkconsole) @@ -495,7 +492,7 @@ self.spawn_subprocess() try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.transfer_path(with_cwd=with_cwd) @@ -513,7 +510,7 @@ # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI - gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) + RemoteDebugger.restart_subprocess_debugger(self.rpcclt) # reload remote debugger breakpoints for all PyShellEditWindows debug.load_breakpoints() self.compile.compiler.flags = self.original_compiler_flags @@ -671,7 +668,7 @@ self.more = 0 self.save_warnings_filters = warnings.filters[:] warnings.filterwarnings(action="error", category=SyntaxWarning) - if isinstance(source, types.UnicodeType): + if isinstance(source, unicode): from idlelib import IOBinding try: source = source.encode(IOBinding.encoding) @@ -1246,7 +1243,7 @@ while i > 0 and line[i-1] in " \t": i = i-1 line = line[:i] - more = self.interp.runsource(line) + self.interp.runsource(line) def open_stack_viewer(self, event=None): if self.interp.rpcclt: @@ -1260,7 +1257,7 @@ master=self.text) return from idlelib.StackViewer import StackBrowser - sv = StackBrowser(self.root, self.flist) + StackBrowser(self.root, self.flist) def view_restart_mark(self, event=None): self.text.see("iomark") diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -100,7 +100,7 @@ tb = tracebacktable[tbid] stack, i = self.idb.get_stack(frame, tb) ##print >>sys.__stderr__, "get_stack() ->", stack - stack = [(wrap_frame(frame), k) for frame, k in stack] + stack = [(wrap_frame(frame2), k) for frame2, k in stack] ##print >>sys.__stderr__, "get_stack() ->", stack return stack, i diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -125,11 +125,9 @@ # # Due to a (mis-)feature of TkAqua the user will also see an empty Help # menu. - from Tkinter import Menu, Text, Text - from idlelib.EditorWindow import prepstr, get_accelerator + from Tkinter import Menu from idlelib import Bindings from idlelib import WindowList - from idlelib.MultiCall import MultiCallCreator closeItem = Bindings.menudefs[0][1][-2] diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,5 +1,4 @@ import sys -import io import linecache import time import socket -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:04:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:04:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4_Issue_=2323184=3A_idlelib=2C_remove_mor?= =?utf-8?q?e_unused_names_and_imports=2E?= Message-ID: <20150516030421.26852.37133@psf.io> https://hg.python.org/cpython/rev/6c424b06320b changeset: 96071:6c424b06320b parent: 96068:e03987f2d274 parent: 96070:777569dd4bca user: Terry Jan Reedy date: Fri May 15 23:03:53 2015 -0400 summary: Merge with 3.4 Issue #23184: idlelib, remove more unused names and imports. files: Lib/idlelib/EditorWindow.py | 4 +--- Lib/idlelib/PyShell.py | 17 +++++++---------- Lib/idlelib/RemoteDebugger.py | 2 +- Lib/idlelib/ScriptBinding.py | 1 - Lib/idlelib/macosxSupport.py | 4 +--- Lib/idlelib/run.py | 2 -- 6 files changed, 10 insertions(+), 20 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -13,7 +13,6 @@ import webbrowser from idlelib.MultiCall import MultiCallCreator -from idlelib import idlever from idlelib import WindowList from idlelib import SearchDialog from idlelib import GrepDialog @@ -125,7 +124,6 @@ EditorWindow.help_url = 'file://' + EditorWindow.help_url else: EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2] - currentTheme=idleConf.CurrentTheme() self.flist = flist root = root or flist.root self.root = root @@ -714,7 +712,7 @@ cmd = [sys.executable, '-c', 'from turtledemo.__main__ import main; main()'] - p = subprocess.Popen(cmd, shell=False) + subprocess.Popen(cmd, shell=False) def gotoline(self, lineno): if lineno is not None and lineno > 0: diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -10,8 +10,6 @@ import threading import time import tokenize -import traceback -import types import io import linecache @@ -32,7 +30,6 @@ from idlelib.UndoDelegator import UndoDelegator from idlelib.OutputWindow import OutputWindow from idlelib.configHandler import idleConf -from idlelib import idlever from idlelib import rpc from idlelib import Debugger from idlelib import RemoteDebugger @@ -166,7 +163,7 @@ filename = self.io.filename text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) try: - i = self.breakpoints.index(lineno) + self.breakpoints.index(lineno) except ValueError: # only add if missing, i.e. do once self.breakpoints.append(lineno) try: # update the subprocess debugger @@ -427,7 +424,7 @@ try: self.rpcclt = MyRPCClient(addr) break - except OSError as err: + except OSError: pass else: self.display_port_binding_error() @@ -448,7 +445,7 @@ self.rpcclt.listening_sock.settimeout(10) try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.rpcclt.register("console", self.tkconsole) @@ -483,7 +480,7 @@ self.spawn_subprocess() try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.transfer_path(with_cwd=with_cwd) @@ -501,7 +498,7 @@ # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI - gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) + RemoteDebugger.restart_subprocess_debugger(self.rpcclt) # reload remote debugger breakpoints for all PyShellEditWindows debug.load_breakpoints() self.compile.compiler.flags = self.original_compiler_flags @@ -1231,7 +1228,7 @@ while i > 0 and line[i-1] in " \t": i = i-1 line = line[:i] - more = self.interp.runsource(line) + self.interp.runsource(line) def open_stack_viewer(self, event=None): if self.interp.rpcclt: @@ -1245,7 +1242,7 @@ master=self.text) return from idlelib.StackViewer import StackBrowser - sv = StackBrowser(self.root, self.flist) + StackBrowser(self.root, self.flist) def view_restart_mark(self, event=None): self.text.see("iomark") diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -98,7 +98,7 @@ else: tb = tracebacktable[tbid] stack, i = self.idb.get_stack(frame, tb) - stack = [(wrap_frame(frame), k) for frame, k in stack] + stack = [(wrap_frame(frame2), k) for frame2, k in stack] return stack, i def run(self, cmd): diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -18,7 +18,6 @@ """ import os -import string import tabnanny import tokenize import tkinter.messagebox as tkMessageBox diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -123,11 +123,9 @@ # # Due to a (mis-)feature of TkAqua the user will also see an empty Help # menu. - from tkinter import Menu, Text, Text - from idlelib.EditorWindow import prepstr, get_accelerator + from tkinter import Menu from idlelib import Bindings from idlelib import WindowList - from idlelib.MultiCall import MultiCallCreator closeItem = Bindings.menudefs[0][1][-2] diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,8 +1,6 @@ import sys -import io import linecache import time -import socket import traceback import _thread as thread import threading -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:56:13 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:56:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMTg0?= =?utf-8?q?=3A_idle_tests=2C_remove_unused_names_and_imports=2E?= Message-ID: <20150516035613.125540.42438@psf.io> https://hg.python.org/cpython/rev/8875d7c6a99d changeset: 96072:8875d7c6a99d branch: 2.7 parent: 96069:d50d661a08f5 user: Terry Jan Reedy date: Fri May 15 23:55:15 2015 -0400 summary: Issue #23184: idle tests, remove unused names and imports. files: Lib/idlelib/idle_test/test_autocomplete.py | 4 ++-- Lib/idlelib/idle_test/test_formatparagraph.py | 2 +- Lib/idlelib/idle_test/test_searchdialogbase.py | 7 +++---- Lib/idlelib/idle_test/test_searchengine.py | 2 +- Lib/idlelib/idle_test/test_text.py | 1 - 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,6 +1,6 @@ import unittest from test.test_support import requires -from Tkinter import Tk, Text, TclError +from Tkinter import Tk, Text import idlelib.AutoComplete as ac import idlelib.AutoCompleteWindow as acw @@ -95,8 +95,8 @@ del ev.mc_state # If autocomplete window is open, complete() method is called - testwin = self.autocomplete._make_autocomplete_window() self.text.insert('1.0', 're.') + # This must call autocomplete._make_autocomplete_window() Equal(self.autocomplete.autocomplete_event(ev), 'break') # If autocomplete window is not active or does not exist, diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -2,7 +2,7 @@ import unittest from idlelib import FormatParagraph as fp from idlelib.EditorWindow import EditorWindow -from Tkinter import Tk, Text, TclError +from Tkinter import Tk, Text from test.test_support import requires diff --git a/Lib/idlelib/idle_test/test_searchdialogbase.py b/Lib/idlelib/idle_test/test_searchdialogbase.py --- a/Lib/idlelib/idle_test/test_searchdialogbase.py +++ b/Lib/idlelib/idle_test/test_searchdialogbase.py @@ -6,14 +6,13 @@ ''' import unittest from test.test_support import requires -from Tkinter import Tk, Toplevel, Frame, Label, BooleanVar, StringVar +from Tkinter import Tk, Toplevel, Frame ## BooleanVar, StringVar from idlelib import SearchEngine as se from idlelib import SearchDialogBase as sdb from idlelib.idle_test.mock_idle import Func -from idlelib.idle_test.mock_tk import Var, Mbox +##from idlelib.idle_test.mock_tk import Var -# The following could help make some tests gui-free. -# However, they currently make radiobutton tests fail. +# The ## imports above & following could help make some tests gui-free.# However, they currently make radiobutton tests fail. ##def setUpModule(): ## # Replace tk objects used to initialize se.SearchEngine. ## se.BooleanVar = Var diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -7,7 +7,7 @@ import re import unittest -from test.test_support import requires +#from test.test_support import requires from Tkinter import BooleanVar, StringVar, TclError # ,Tk, Text import tkMessageBox from idlelib import SearchEngine as se diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -3,7 +3,6 @@ from test.test_support import requires from _tkinter import TclError -import Tkinter as tk class TextTest(object): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:56:14 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:56:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMTg0?= =?utf-8?q?=3A_idle_tests=2C_remove_unused_names_and_imports=2E?= Message-ID: <20150516035613.16318.76153@psf.io> https://hg.python.org/cpython/rev/526ce81f700d changeset: 96073:526ce81f700d branch: 3.4 parent: 96070:777569dd4bca user: Terry Jan Reedy date: Fri May 15 23:55:21 2015 -0400 summary: Issue #23184: idle tests, remove unused names and imports. files: Lib/idlelib/idle_test/test_autocomplete.py | 4 ++-- Lib/idlelib/idle_test/test_formatparagraph.py | 2 +- Lib/idlelib/idle_test/test_searchdialogbase.py | 6 +++--- Lib/idlelib/idle_test/test_searchengine.py | 2 +- Lib/idlelib/idle_test/test_text.py | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,6 +1,6 @@ import unittest from test.support import requires -from tkinter import Tk, Text, TclError +from tkinter import Tk, Text import idlelib.AutoComplete as ac import idlelib.AutoCompleteWindow as acw @@ -95,8 +95,8 @@ del ev.mc_state # If autocomplete window is open, complete() method is called - testwin = self.autocomplete._make_autocomplete_window() self.text.insert('1.0', 're.') + # This must call autocomplete._make_autocomplete_window() Equal(self.autocomplete.autocomplete_event(ev), 'break') # If autocomplete window is not active or does not exist, diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -2,7 +2,7 @@ import unittest from idlelib import FormatParagraph as fp from idlelib.EditorWindow import EditorWindow -from tkinter import Tk, Text, TclError +from tkinter import Tk, Text from test.support import requires diff --git a/Lib/idlelib/idle_test/test_searchdialogbase.py b/Lib/idlelib/idle_test/test_searchdialogbase.py --- a/Lib/idlelib/idle_test/test_searchdialogbase.py +++ b/Lib/idlelib/idle_test/test_searchdialogbase.py @@ -6,13 +6,13 @@ ''' import unittest from test.support import requires -from tkinter import Tk, Toplevel, Frame, Label, BooleanVar, StringVar +from tkinter import Tk, Toplevel, Frame ##, BooleanVar, StringVar from idlelib import SearchEngine as se from idlelib import SearchDialogBase as sdb from idlelib.idle_test.mock_idle import Func -from idlelib.idle_test.mock_tk import Var, Mbox +## from idlelib.idle_test.mock_tk import Var -# The following could help make some tests gui-free. +# The ## imports above & following could help make some tests gui-free. # However, they currently make radiobutton tests fail. ##def setUpModule(): ## # Replace tk objects used to initialize se.SearchEngine. diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -7,7 +7,7 @@ import re import unittest -from test.support import requires +# from test.support import requires from tkinter import BooleanVar, StringVar, TclError # ,Tk, Text import tkinter.messagebox as tkMessageBox from idlelib import SearchEngine as se diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -3,7 +3,6 @@ from test.support import requires from _tkinter import TclError -import tkinter as tk class TextTest(object): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:56:19 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 03:56:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=2323184=3A_idle_tests=2C_remove_unused_name?= =?utf-8?q?s_and_imports=2E?= Message-ID: <20150516035619.39255.72009@psf.io> https://hg.python.org/cpython/rev/2a56eb5c08cc changeset: 96074:2a56eb5c08cc parent: 96071:6c424b06320b parent: 96073:526ce81f700d user: Terry Jan Reedy date: Fri May 15 23:55:49 2015 -0400 summary: Merge 3.4 #23184: idle tests, remove unused names and imports. files: Lib/idlelib/idle_test/test_autocomplete.py | 4 ++-- Lib/idlelib/idle_test/test_formatparagraph.py | 2 +- Lib/idlelib/idle_test/test_searchdialogbase.py | 6 +++--- Lib/idlelib/idle_test/test_searchengine.py | 2 +- Lib/idlelib/idle_test/test_text.py | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,6 +1,6 @@ import unittest from test.support import requires -from tkinter import Tk, Text, TclError +from tkinter import Tk, Text import idlelib.AutoComplete as ac import idlelib.AutoCompleteWindow as acw @@ -95,8 +95,8 @@ del ev.mc_state # If autocomplete window is open, complete() method is called - testwin = self.autocomplete._make_autocomplete_window() self.text.insert('1.0', 're.') + # This must call autocomplete._make_autocomplete_window() Equal(self.autocomplete.autocomplete_event(ev), 'break') # If autocomplete window is not active or does not exist, diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -2,7 +2,7 @@ import unittest from idlelib import FormatParagraph as fp from idlelib.EditorWindow import EditorWindow -from tkinter import Tk, Text, TclError +from tkinter import Tk, Text from test.support import requires diff --git a/Lib/idlelib/idle_test/test_searchdialogbase.py b/Lib/idlelib/idle_test/test_searchdialogbase.py --- a/Lib/idlelib/idle_test/test_searchdialogbase.py +++ b/Lib/idlelib/idle_test/test_searchdialogbase.py @@ -6,13 +6,13 @@ ''' import unittest from test.support import requires -from tkinter import Tk, Toplevel, Frame, Label, BooleanVar, StringVar +from tkinter import Tk, Toplevel, Frame ##, BooleanVar, StringVar from idlelib import SearchEngine as se from idlelib import SearchDialogBase as sdb from idlelib.idle_test.mock_idle import Func -from idlelib.idle_test.mock_tk import Var, Mbox +## from idlelib.idle_test.mock_tk import Var -# The following could help make some tests gui-free. +# The ## imports above & following could help make some tests gui-free. # However, they currently make radiobutton tests fail. ##def setUpModule(): ## # Replace tk objects used to initialize se.SearchEngine. diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -7,7 +7,7 @@ import re import unittest -from test.support import requires +# from test.support import requires from tkinter import BooleanVar, StringVar, TclError # ,Tk, Text import tkinter.messagebox as tkMessageBox from idlelib import SearchEngine as se diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -3,7 +3,6 @@ from test.support import requires from _tkinter import TclError -import tkinter as tk class TextTest(object): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 05:57:10 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 16 May 2015 03:57:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324192=3A_Fix_name?= =?utf-8?q?space_package_imports=2E?= Message-ID: <20150516035710.26554.92409@psf.io> https://hg.python.org/cpython/rev/46b2c99121f5 changeset: 96075:46b2c99121f5 user: Eric Snow date: Fri May 15 21:54:59 2015 -0600 summary: Issue #24192: Fix namespace package imports. files: Lib/importlib/__init__.py | 1 + Lib/importlib/_bootstrap.py | 19 +- Lib/importlib/_bootstrap_external.py | 50 +- Lib/importlib/abc.py | 3 +- Lib/test/test_importlib/util.py | 2 +- Misc/NEWS | 2 + Python/importlib.h | 3902 +++++----- Python/importlib_external.h | 5137 ++++++------- 8 files changed, 4525 insertions(+), 4591 deletions(-) diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -35,6 +35,7 @@ except ImportError: from . import _bootstrap_external _bootstrap_external._setup(_bootstrap) + _bootstrap._bootstrap_external = _bootstrap_external else: _bootstrap_external.__name__ = 'importlib._bootstrap_external' _bootstrap_external.__package__ = 'importlib' diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -22,6 +22,8 @@ # Bootstrap-related code ###################################################### +_bootstrap_external = None + def _wrap(new, old): """Simple substitute for functools.update_wrapper.""" for replace in ['__module__', '__name__', '__qualname__', '__doc__']: @@ -405,7 +407,8 @@ def cached(self): if self._cached is None: if self.origin is not None and self._set_fileattr: - import _frozen_importlib_external as _bootstrap_external # XXX yuck + if _bootstrap_external is None: + raise NotImplementedError self._cached = _bootstrap_external._get_cached(self.origin) return self._cached @@ -433,7 +436,10 @@ def spec_from_loader(name, loader, *, origin=None, is_package=None): """Return a module spec based on various loader methods.""" if hasattr(loader, 'get_filename'): - from ._bootstrap_external import spec_from_file_location # XXX yuck + if _bootstrap_external is None: + raise NotImplementedError + spec_from_file_location = _bootstrap_external.spec_from_file_location + if is_package is None: return spec_from_file_location(name, loader=loader) search = [] if is_package else None @@ -516,7 +522,10 @@ if loader is None: # A backward compatibility hack. if spec.submodule_search_locations is not None: - from ._bootstrap_external import _NamespaceLoader # XXX yuck + if _bootstrap_external is None: + raise NotImplementedError + _NamespaceLoader = _bootstrap_external._NamespaceLoader + loader = _NamespaceLoader.__new__(_NamespaceLoader) loader._path = spec.submodule_search_locations try: @@ -810,7 +819,6 @@ This method is deprecated. Use exec_module() instead. """ - from ._bootstrap_external import _load_module_shim # XXX yuck return _load_module_shim(cls, fullname) @classmethod @@ -1125,6 +1133,7 @@ sys.meta_path.append(BuiltinImporter) sys.meta_path.append(FrozenImporter) + global _bootstrap_external import _frozen_importlib_external + _bootstrap_external = _frozen_importlib_external _frozen_importlib_external._install(sys.modules[__name__]) - sys.modules[__name__]._bootstrap_external = _frozen_importlib_external diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -410,22 +410,6 @@ return loader -# Typically used by loader classes as a method replacement. -def _load_module_shim(self, fullname): - """Load the specified module into sys.modules and return it. - - This method is deprecated. Use loader.exec_module instead. - - """ - spec = spec_from_loader(fullname, self) - if fullname in sys.modules: - module = sys.modules[fullname] - _bootstrap._exec(spec, module) - return sys.modules[fullname] - else: - return _bootstrap._load(spec) - - def _validate_bytecode_header(data, source_stats=None, name=None, path=None): """Validate the header of the passed-in bytecode against source_stats (if given) and returning the bytecode that can be compiled by compile(). @@ -517,28 +501,6 @@ # Module specifications ####################################################### -def spec_from_loader(name, loader, *, origin=None, is_package=None): - """Return a module spec based on various loader methods.""" - if hasattr(loader, 'get_filename'): - if is_package is None: - return spec_from_file_location(name, loader=loader) - search = [] if is_package else None - return spec_from_file_location(name, loader=loader, - submodule_search_locations=search) - - if is_package is None: - if hasattr(loader, 'is_package'): - try: - is_package = loader.is_package(name) - except ImportError: - is_package = None # aka, undefined - else: - # the default - is_package = False - - return _bootstrap.ModuleSpec(name, loader, origin=origin, is_package=is_package) - - _POPULATE = object() @@ -653,8 +615,9 @@ return None for loader, suffixes in _get_supported_file_loaders(): if filepath.endswith(tuple(suffixes)): - spec = spec_from_loader(fullname, loader(fullname, filepath), - origin=filepath) + spec = _bootstrap.spec_from_loader(fullname, + loader(fullname, filepath), + origin=filepath) return spec @classmethod @@ -695,7 +658,8 @@ 'returns None'.format(module.__name__)) _bootstrap._call_with_frames_removed(exec, code, module.__dict__) - load_module = _load_module_shim + def load_module(self, fullname): + return _bootstrap._load_module_shim(self, fullname) class SourceLoader(_LoaderBasics): @@ -1061,7 +1025,7 @@ """ # The import system never calls this method. _verbose_message('namespace module loaded with path {!r}', self._path) - return _load_module_shim(self, fullname) + return _bootstrap._load_module_shim(self, fullname) # Finders ##################################################################### @@ -1127,7 +1091,7 @@ loader = finder.find_module(fullname) portions = [] if loader is not None: - return spec_from_loader(fullname, loader) + return _bootstrap.spec_from_loader(fullname, loader) spec = _bootstrap.ModuleSpec(fullname, None) spec.submodule_search_locations = portions return spec diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -1,4 +1,5 @@ """Abstract base classes related to import.""" +from . import _bootstrap from . import _bootstrap_external from . import machinery try: @@ -152,7 +153,7 @@ """ if not hasattr(self, 'exec_module'): raise ImportError - return _bootstrap_external._load_module_shim(self, fullname) + return _bootstrap._load_module_shim(self, fullname) def module_repr(self, module): """Return a module's repr. diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -49,7 +49,7 @@ fresh = ('importlib',) if '.' in module_name else () frozen = support.import_fresh_module(module_name) source = support.import_fresh_module(module_name, fresh=fresh, - blocked=('_frozen_importlib',)) + blocked=('_frozen_importlib', '_frozen_importlib_external')) return {'Frozen': frozen, 'Source': source} diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ - Issue #23911: Move path-based importlib bootstrap code to a separate frozen module. +- Issue #24192: Fix namespace package imports. + - Issue #24022: Fix tokenizer crash when processing undecodable source code. - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1,8 +1,8 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__importlib_external[] = { 99,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, - 0,64,0,0,0,115,2,3,0,0,100,0,0,90,0,0, - 100,102,0,90,1,0,100,4,0,100,5,0,132,0,0,90, + 0,64,0,0,0,115,222,2,0,0,100,0,0,90,0,0, + 100,96,0,90,1,0,100,4,0,100,5,0,132,0,0,90, 2,0,100,6,0,100,7,0,132,0,0,90,3,0,100,8, 0,100,9,0,132,0,0,90,4,0,100,10,0,100,11,0, 132,0,0,90,5,0,100,12,0,100,13,0,132,0,0,90, @@ -23,2611 +23,2568 @@ 0,0,90,30,0,100,45,0,100,46,0,100,47,0,100,48, 0,132,0,1,90,31,0,100,49,0,100,50,0,132,0,0, 90,32,0,100,51,0,100,52,0,132,0,0,90,33,0,100, - 53,0,100,54,0,132,0,0,90,34,0,100,33,0,100,33, - 0,100,33,0,100,55,0,100,56,0,132,3,0,90,35,0, - 100,33,0,100,33,0,100,33,0,100,57,0,100,58,0,132, - 3,0,90,36,0,100,59,0,100,59,0,100,60,0,100,61, - 0,132,2,0,90,37,0,100,62,0,100,63,0,132,0,0, - 90,38,0,100,64,0,100,33,0,100,65,0,100,33,0,100, - 66,0,100,67,0,132,0,2,90,39,0,101,40,0,131,0, - 0,90,41,0,100,33,0,100,68,0,100,33,0,100,69,0, - 101,41,0,100,70,0,100,71,0,132,1,2,90,42,0,71, - 100,72,0,100,73,0,132,0,0,100,73,0,131,2,0,90, - 43,0,71,100,74,0,100,75,0,132,0,0,100,75,0,131, - 2,0,90,44,0,71,100,76,0,100,77,0,132,0,0,100, - 77,0,101,44,0,131,3,0,90,45,0,71,100,78,0,100, - 79,0,132,0,0,100,79,0,131,2,0,90,46,0,71,100, - 80,0,100,81,0,132,0,0,100,81,0,101,46,0,101,45, - 0,131,4,0,90,47,0,71,100,82,0,100,83,0,132,0, - 0,100,83,0,101,46,0,101,44,0,131,4,0,90,48,0, - 103,0,0,90,49,0,71,100,84,0,100,85,0,132,0,0, - 100,85,0,131,2,0,90,50,0,71,100,86,0,100,87,0, - 132,0,0,100,87,0,131,2,0,90,51,0,71,100,88,0, - 100,89,0,132,0,0,100,89,0,131,2,0,90,52,0,71, - 100,90,0,100,91,0,132,0,0,100,91,0,131,2,0,90, - 53,0,71,100,92,0,100,93,0,132,0,0,100,93,0,131, - 2,0,90,54,0,100,33,0,100,94,0,100,95,0,132,1, - 0,90,55,0,100,96,0,100,97,0,132,0,0,90,56,0, - 100,98,0,100,99,0,132,0,0,90,57,0,100,100,0,100, - 101,0,132,0,0,90,58,0,100,33,0,83,41,103,97,94, - 1,0,0,67,111,114,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,112,97,116,104,45,98, - 97,115,101,100,32,105,109,112,111,114,116,46,10,10,84,104, - 105,115,32,109,111,100,117,108,101,32,105,115,32,78,79,84, - 32,109,101,97,110,116,32,116,111,32,98,101,32,100,105,114, - 101,99,116,108,121,32,105,109,112,111,114,116,101,100,33,32, - 73,116,32,104,97,115,32,98,101,101,110,32,100,101,115,105, - 103,110,101,100,32,115,117,99,104,10,116,104,97,116,32,105, - 116,32,99,97,110,32,98,101,32,98,111,111,116,115,116,114, - 97,112,112,101,100,32,105,110,116,111,32,80,121,116,104,111, - 110,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,114, - 116,46,32,65,115,10,115,117,99,104,32,105,116,32,114,101, - 113,117,105,114,101,115,32,116,104,101,32,105,110,106,101,99, - 116,105,111,110,32,111,102,32,115,112,101,99,105,102,105,99, - 32,109,111,100,117,108,101,115,32,97,110,100,32,97,116,116, - 114,105,98,117,116,101,115,32,105,110,32,111,114,100,101,114, - 32,116,111,10,119,111,114,107,46,32,79,110,101,32,115,104, - 111,117,108,100,32,117,115,101,32,105,109,112,111,114,116,108, - 105,98,32,97,115,32,116,104,101,32,112,117,98,108,105,99, - 45,102,97,99,105,110,103,32,118,101,114,115,105,111,110,32, - 111,102,32,116,104,105,115,32,109,111,100,117,108,101,46,10, - 10,218,3,119,105,110,218,6,99,121,103,119,105,110,218,6, - 100,97,114,119,105,110,99,0,0,0,0,0,0,0,0,1, - 0,0,0,2,0,0,0,67,0,0,0,115,49,0,0,0, - 116,0,0,106,1,0,106,2,0,116,3,0,131,1,0,114, - 33,0,100,1,0,100,2,0,132,0,0,125,0,0,110,12, - 0,100,3,0,100,2,0,132,0,0,125,0,0,124,0,0, - 83,41,4,78,99,0,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,83,0,0,0,115,13,0,0,0,100,1, - 0,116,0,0,106,1,0,107,6,0,83,41,2,122,53,84, - 114,117,101,32,105,102,32,102,105,108,101,110,97,109,101,115, - 32,109,117,115,116,32,98,101,32,99,104,101,99,107,101,100, - 32,99,97,115,101,45,105,110,115,101,110,115,105,116,105,118, - 101,108,121,46,115,12,0,0,0,80,89,84,72,79,78,67, - 65,83,69,79,75,41,2,218,3,95,111,115,90,7,101,110, - 118,105,114,111,110,169,0,114,4,0,0,0,114,4,0,0, - 0,250,38,60,102,114,111,122,101,110,32,105,109,112,111,114, - 116,108,105,98,46,95,98,111,111,116,115,116,114,97,112,95, - 101,120,116,101,114,110,97,108,62,218,11,95,114,101,108,97, - 120,95,99,97,115,101,30,0,0,0,115,2,0,0,0,0, - 2,122,37,95,109,97,107,101,95,114,101,108,97,120,95,99, - 97,115,101,46,60,108,111,99,97,108,115,62,46,95,114,101, - 108,97,120,95,99,97,115,101,99,0,0,0,0,0,0,0, - 0,0,0,0,0,1,0,0,0,83,0,0,0,115,4,0, - 0,0,100,1,0,83,41,2,122,53,84,114,117,101,32,105, - 102,32,102,105,108,101,110,97,109,101,115,32,109,117,115,116, - 32,98,101,32,99,104,101,99,107,101,100,32,99,97,115,101, - 45,105,110,115,101,110,115,105,116,105,118,101,108,121,46,70, + 33,0,100,33,0,100,33,0,100,53,0,100,54,0,132,3, + 0,90,34,0,100,33,0,100,33,0,100,33,0,100,55,0, + 100,56,0,132,3,0,90,35,0,100,57,0,100,57,0,100, + 58,0,100,59,0,132,2,0,90,36,0,100,60,0,100,61, + 0,132,0,0,90,37,0,101,38,0,131,0,0,90,39,0, + 100,33,0,100,62,0,100,33,0,100,63,0,101,39,0,100, + 64,0,100,65,0,132,1,2,90,40,0,71,100,66,0,100, + 67,0,132,0,0,100,67,0,131,2,0,90,41,0,71,100, + 68,0,100,69,0,132,0,0,100,69,0,131,2,0,90,42, + 0,71,100,70,0,100,71,0,132,0,0,100,71,0,101,42, + 0,131,3,0,90,43,0,71,100,72,0,100,73,0,132,0, + 0,100,73,0,131,2,0,90,44,0,71,100,74,0,100,75, + 0,132,0,0,100,75,0,101,44,0,101,43,0,131,4,0, + 90,45,0,71,100,76,0,100,77,0,132,0,0,100,77,0, + 101,44,0,101,42,0,131,4,0,90,46,0,103,0,0,90, + 47,0,71,100,78,0,100,79,0,132,0,0,100,79,0,131, + 2,0,90,48,0,71,100,80,0,100,81,0,132,0,0,100, + 81,0,131,2,0,90,49,0,71,100,82,0,100,83,0,132, + 0,0,100,83,0,131,2,0,90,50,0,71,100,84,0,100, + 85,0,132,0,0,100,85,0,131,2,0,90,51,0,71,100, + 86,0,100,87,0,132,0,0,100,87,0,131,2,0,90,52, + 0,100,33,0,100,88,0,100,89,0,132,1,0,90,53,0, + 100,90,0,100,91,0,132,0,0,90,54,0,100,92,0,100, + 93,0,132,0,0,90,55,0,100,94,0,100,95,0,132,0, + 0,90,56,0,100,33,0,83,41,97,97,94,1,0,0,67, + 111,114,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,112,97,116,104,45,98,97,115,101,100, + 32,105,109,112,111,114,116,46,10,10,84,104,105,115,32,109, + 111,100,117,108,101,32,105,115,32,78,79,84,32,109,101,97, + 110,116,32,116,111,32,98,101,32,100,105,114,101,99,116,108, + 121,32,105,109,112,111,114,116,101,100,33,32,73,116,32,104, + 97,115,32,98,101,101,110,32,100,101,115,105,103,110,101,100, + 32,115,117,99,104,10,116,104,97,116,32,105,116,32,99,97, + 110,32,98,101,32,98,111,111,116,115,116,114,97,112,112,101, + 100,32,105,110,116,111,32,80,121,116,104,111,110,32,97,115, + 32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116, + 105,111,110,32,111,102,32,105,109,112,111,114,116,46,32,65, + 115,10,115,117,99,104,32,105,116,32,114,101,113,117,105,114, + 101,115,32,116,104,101,32,105,110,106,101,99,116,105,111,110, + 32,111,102,32,115,112,101,99,105,102,105,99,32,109,111,100, + 117,108,101,115,32,97,110,100,32,97,116,116,114,105,98,117, + 116,101,115,32,105,110,32,111,114,100,101,114,32,116,111,10, + 119,111,114,107,46,32,79,110,101,32,115,104,111,117,108,100, + 32,117,115,101,32,105,109,112,111,114,116,108,105,98,32,97, + 115,32,116,104,101,32,112,117,98,108,105,99,45,102,97,99, + 105,110,103,32,118,101,114,115,105,111,110,32,111,102,32,116, + 104,105,115,32,109,111,100,117,108,101,46,10,10,218,3,119, + 105,110,218,6,99,121,103,119,105,110,218,6,100,97,114,119, + 105,110,99,0,0,0,0,0,0,0,0,1,0,0,0,2, + 0,0,0,67,0,0,0,115,49,0,0,0,116,0,0,106, + 1,0,106,2,0,116,3,0,131,1,0,114,33,0,100,1, + 0,100,2,0,132,0,0,125,0,0,110,12,0,100,3,0, + 100,2,0,132,0,0,125,0,0,124,0,0,83,41,4,78, + 99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,83,0,0,0,115,13,0,0,0,100,1,0,116,0,0, + 106,1,0,107,6,0,83,41,2,122,53,84,114,117,101,32, + 105,102,32,102,105,108,101,110,97,109,101,115,32,109,117,115, + 116,32,98,101,32,99,104,101,99,107,101,100,32,99,97,115, + 101,45,105,110,115,101,110,115,105,116,105,118,101,108,121,46, + 115,12,0,0,0,80,89,84,72,79,78,67,65,83,69,79, + 75,41,2,218,3,95,111,115,90,7,101,110,118,105,114,111, + 110,169,0,114,4,0,0,0,114,4,0,0,0,250,38,60, + 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, + 46,95,98,111,111,116,115,116,114,97,112,95,101,120,116,101, + 114,110,97,108,62,218,11,95,114,101,108,97,120,95,99,97, + 115,101,30,0,0,0,115,2,0,0,0,0,2,122,37,95, + 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, + 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, + 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,83,0,0,0,115,4,0,0,0,100,1, + 0,83,41,2,122,53,84,114,117,101,32,105,102,32,102,105, + 108,101,110,97,109,101,115,32,109,117,115,116,32,98,101,32, + 99,104,101,99,107,101,100,32,99,97,115,101,45,105,110,115, + 101,110,115,105,116,105,118,101,108,121,46,70,114,4,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,6,0,0,0,34,0,0,0,115,2, + 0,0,0,0,2,41,4,218,3,115,121,115,218,8,112,108, + 97,116,102,111,114,109,218,10,115,116,97,114,116,115,119,105, + 116,104,218,27,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,41, + 1,114,6,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,16,95,109,97,107,101,95,114,101,108, + 97,120,95,99,97,115,101,28,0,0,0,115,8,0,0,0, + 0,1,18,1,15,4,12,3,114,11,0,0,0,99,1,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,26,0,0,0,116,0,0,124,0,0,131,1,0, + 100,1,0,64,106,1,0,100,2,0,100,3,0,131,2,0, + 83,41,4,122,42,67,111,110,118,101,114,116,32,97,32,51, + 50,45,98,105,116,32,105,110,116,101,103,101,114,32,116,111, + 32,108,105,116,116,108,101,45,101,110,100,105,97,110,46,108, + 3,0,0,0,255,127,255,127,3,0,233,4,0,0,0,218, + 6,108,105,116,116,108,101,41,2,218,3,105,110,116,218,8, + 116,111,95,98,121,116,101,115,41,1,218,1,120,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,7,95,119, + 95,108,111,110,103,40,0,0,0,115,2,0,0,0,0,2, + 114,17,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,16,0,0,0,116, + 0,0,106,1,0,124,0,0,100,1,0,131,2,0,83,41, + 2,122,47,67,111,110,118,101,114,116,32,52,32,98,121,116, + 101,115,32,105,110,32,108,105,116,116,108,101,45,101,110,100, + 105,97,110,32,116,111,32,97,110,32,105,110,116,101,103,101, + 114,46,114,13,0,0,0,41,2,114,14,0,0,0,218,10, + 102,114,111,109,95,98,121,116,101,115,41,1,90,9,105,110, + 116,95,98,121,116,101,115,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,7,95,114,95,108,111,110,103,45, + 0,0,0,115,2,0,0,0,0,2,114,19,0,0,0,99, + 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 71,0,0,0,115,26,0,0,0,116,0,0,106,1,0,100, + 1,0,100,2,0,132,0,0,124,0,0,68,131,1,0,131, + 1,0,83,41,3,122,31,82,101,112,108,97,99,101,109,101, + 110,116,32,102,111,114,32,111,115,46,112,97,116,104,46,106, + 111,105,110,40,41,46,99,1,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,83,0,0,0,115,37,0,0,0, + 103,0,0,124,0,0,93,27,0,125,1,0,124,1,0,114, + 6,0,124,1,0,106,0,0,116,1,0,131,1,0,145,2, + 0,113,6,0,83,114,4,0,0,0,41,2,218,6,114,115, + 116,114,105,112,218,15,112,97,116,104,95,115,101,112,97,114, + 97,116,111,114,115,41,2,218,2,46,48,218,4,112,97,114, + 116,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 250,10,60,108,105,115,116,99,111,109,112,62,52,0,0,0, + 115,2,0,0,0,9,1,122,30,95,112,97,116,104,95,106, + 111,105,110,46,60,108,111,99,97,108,115,62,46,60,108,105, + 115,116,99,111,109,112,62,41,2,218,8,112,97,116,104,95, + 115,101,112,218,4,106,111,105,110,41,1,218,10,112,97,116, + 104,95,112,97,114,116,115,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,10,95,112,97,116,104,95,106,111, + 105,110,50,0,0,0,115,4,0,0,0,0,2,15,1,114, + 28,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, + 0,5,0,0,0,67,0,0,0,115,134,0,0,0,116,0, + 0,116,1,0,131,1,0,100,1,0,107,2,0,114,52,0, + 124,0,0,106,2,0,116,3,0,131,1,0,92,3,0,125, + 1,0,125,2,0,125,3,0,124,1,0,124,3,0,102,2, + 0,83,120,69,0,116,4,0,124,0,0,131,1,0,68,93, + 55,0,125,4,0,124,4,0,116,1,0,107,6,0,114,65, + 0,124,0,0,106,5,0,124,4,0,100,2,0,100,1,0, + 131,1,1,92,2,0,125,1,0,125,3,0,124,1,0,124, + 3,0,102,2,0,83,113,65,0,87,100,3,0,124,0,0, + 102,2,0,83,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,90,8,109, + 97,120,115,112,108,105,116,218,0,41,6,218,3,108,101,110, + 114,21,0,0,0,218,10,114,112,97,114,116,105,116,105,111, + 110,114,25,0,0,0,218,8,114,101,118,101,114,115,101,100, + 218,6,114,115,112,108,105,116,41,5,218,4,112,97,116,104, + 90,5,102,114,111,110,116,218,1,95,218,4,116,97,105,108, + 114,16,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,11,95,112,97,116,104,95,115,112,108,105, + 116,56,0,0,0,115,16,0,0,0,0,2,18,1,24,1, + 10,1,19,1,12,1,27,1,14,1,114,38,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,13,0,0,0,116,0,0,106,1,0,124, + 0,0,131,1,0,83,41,1,122,126,83,116,97,116,32,116, + 104,101,32,112,97,116,104,46,10,10,32,32,32,32,77,97, + 100,101,32,97,32,115,101,112,97,114,97,116,101,32,102,117, + 110,99,116,105,111,110,32,116,111,32,109,97,107,101,32,105, + 116,32,101,97,115,105,101,114,32,116,111,32,111,118,101,114, + 114,105,100,101,32,105,110,32,101,120,112,101,114,105,109,101, + 110,116,115,10,32,32,32,32,40,101,46,103,46,32,99,97, + 99,104,101,32,115,116,97,116,32,114,101,115,117,108,116,115, + 41,46,10,10,32,32,32,32,41,2,114,3,0,0,0,90, + 4,115,116,97,116,41,1,114,35,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,10,95,112,97, + 116,104,95,115,116,97,116,68,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,11,0,0,0,67,0,0,0,115,58,0,0, + 0,121,16,0,116,0,0,124,0,0,131,1,0,125,2,0, + 87,110,22,0,4,116,1,0,107,10,0,114,40,0,1,1, + 1,100,1,0,83,89,110,1,0,88,124,2,0,106,2,0, + 100,2,0,64,124,1,0,107,2,0,83,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,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,18,95,112,97,116,104,95,105,115, + 95,109,111,100,101,95,116,121,112,101,78,0,0,0,115,10, + 0,0,0,0,2,3,1,16,1,13,1,9,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,13,0,0,0,116,0,0,124, + 0,0,100,1,0,131,2,0,83,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, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, + 95,112,97,116,104,95,105,115,102,105,108,101,87,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,31,0,0,0,124,0,0,115,18,0,116,0,0,106, + 1,0,131,0,0,125,0,0,116,2,0,124,0,0,100,1, + 0,131,2,0,83,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,3, + 0,0,0,218,6,103,101,116,99,119,100,114,43,0,0,0, + 41,1,114,35,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,11,95,112,97,116,104,95,105,115, + 100,105,114,92,0,0,0,115,6,0,0,0,0,2,6,1, + 12,1,114,46,0,0,0,105,182,1,0,0,99,3,0,0, + 0,0,0,0,0,6,0,0,0,17,0,0,0,67,0,0, + 0,115,193,0,0,0,100,1,0,106,0,0,124,0,0,116, + 1,0,124,0,0,131,1,0,131,2,0,125,3,0,116,2, + 0,106,3,0,124,3,0,116,2,0,106,4,0,116,2,0, + 106,5,0,66,116,2,0,106,6,0,66,124,2,0,100,2, + 0,64,131,3,0,125,4,0,121,61,0,116,7,0,106,8, + 0,124,4,0,100,3,0,131,2,0,143,20,0,125,5,0, + 124,5,0,106,9,0,124,1,0,131,1,0,1,87,100,4, + 0,81,82,88,116,2,0,106,10,0,124,3,0,124,0,0, + 131,2,0,1,87,110,59,0,4,116,11,0,107,10,0,114, + 188,0,1,1,1,121,17,0,116,2,0,106,12,0,124,3, + 0,131,1,0,1,87,110,18,0,4,116,11,0,107,10,0, + 114,180,0,1,1,1,89,110,1,0,88,130,0,0,89,110, + 1,0,88,100,4,0,83,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,3,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,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,13,95,119,114,105,116,101,95,97,116,111,109,105,99, + 99,0,0,0,115,26,0,0,0,0,5,24,1,9,1,33, + 1,3,3,21,1,20,1,20,1,13,1,3,1,17,1,13, + 1,5,1,114,55,0,0,0,105,2,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,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,87,1,0,0,124,1,0,100,1,0,107,9,0,114,76, + 0,116,0,0,106,1,0,100,2,0,116,2,0,131,2,0, + 1,124,2,0,100,1,0,107,9,0,114,58,0,100,3,0, + 125,3,0,116,3,0,124,3,0,131,1,0,130,1,0,124, + 1,0,114,70,0,100,4,0,110,3,0,100,5,0,125,2, + 0,116,4,0,124,0,0,131,1,0,92,2,0,125,4,0, + 125,5,0,124,5,0,106,5,0,100,6,0,131,1,0,92, + 3,0,125,6,0,125,7,0,125,8,0,116,6,0,106,7, + 0,106,8,0,125,9,0,124,9,0,100,1,0,107,8,0, + 114,154,0,116,9,0,100,7,0,131,1,0,130,1,0,100, + 4,0,106,10,0,124,6,0,114,172,0,124,6,0,110,3, + 0,124,8,0,124,7,0,124,9,0,103,3,0,131,1,0, + 125,10,0,124,2,0,100,1,0,107,8,0,114,241,0,116, + 6,0,106,11,0,106,12,0,100,8,0,107,2,0,114,229, + 0,100,4,0,125,2,0,110,12,0,116,6,0,106,11,0, + 106,12,0,125,2,0,116,13,0,124,2,0,131,1,0,125, + 2,0,124,2,0,100,4,0,107,3,0,114,63,1,124,2, + 0,106,14,0,131,0,0,115,42,1,116,15,0,100,9,0, + 106,16,0,124,2,0,131,1,0,131,1,0,130,1,0,100, + 10,0,106,16,0,124,10,0,116,17,0,124,2,0,131,3, + 0,125,10,0,116,18,0,124,4,0,116,19,0,124,10,0, + 116,20,0,100,8,0,25,23,131,3,0,83,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,21,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,38,0,0,0, + 114,32,0,0,0,114,7,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,47,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,57, + 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,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,17,99, + 97,99,104,101,95,102,114,111,109,95,115,111,117,114,99,101, + 241,0,0,0,115,46,0,0,0,0,18,12,1,9,1,7, + 1,12,1,6,1,12,1,18,1,18,1,24,1,12,1,12, + 1,12,1,36,1,12,1,18,1,9,2,12,1,12,1,12, + 1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0,106,2,0,100, + 1,0,107,8,0,114,30,0,116,3,0,100,2,0,131,1, + 0,130,1,0,116,4,0,124,0,0,131,1,0,92,2,0, + 125,1,0,125,2,0,116,4,0,124,1,0,131,1,0,92, + 2,0,125,1,0,125,3,0,124,3,0,116,5,0,107,3, + 0,114,102,0,116,6,0,100,3,0,106,7,0,116,5,0, + 124,0,0,131,2,0,131,1,0,130,1,0,124,2,0,106, + 8,0,100,4,0,131,1,0,125,4,0,124,4,0,100,11, + 0,107,7,0,114,153,0,116,6,0,100,7,0,106,7,0, + 124,2,0,131,1,0,131,1,0,130,1,0,110,125,0,124, + 4,0,100,6,0,107,2,0,114,22,1,124,2,0,106,9, + 0,100,4,0,100,5,0,131,2,0,100,12,0,25,125,5, + 0,124,5,0,106,10,0,116,11,0,131,1,0,115,223,0, + 116,6,0,100,8,0,106,7,0,116,11,0,131,1,0,131, + 1,0,130,1,0,124,5,0,116,12,0,116,11,0,131,1, + 0,100,1,0,133,2,0,25,125,6,0,124,6,0,106,13, + 0,131,0,0,115,22,1,116,6,0,100,9,0,106,7,0, + 124,5,0,131,1,0,131,1,0,130,1,0,124,2,0,106, + 14,0,100,4,0,131,1,0,100,10,0,25,125,7,0,116, + 15,0,124,1,0,124,7,0,116,16,0,100,10,0,25,23, + 131,2,0,83,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,58,0,0,0,114,56,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,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,59,0,0,0,62, + 2,0,0,0,114,56,0,0,0,114,80,0,0,0,233,254, + 255,255,255,41,17,114,7,0,0,0,114,64,0,0,0,114, + 65,0,0,0,114,66,0,0,0,114,38,0,0,0,114,73, + 0,0,0,114,71,0,0,0,114,47,0,0,0,218,5,99, + 111,117,110,116,114,34,0,0,0,114,9,0,0,0,114,72, + 0,0,0,114,31,0,0,0,114,70,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,76,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,57,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, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17, + 115,111,117,114,99,101,95,102,114,111,109,95,99,97,99,104, + 101,29,1,0,0,115,44,0,0,0,0,9,18,1,12,1, + 18,1,18,1,12,1,9,1,15,1,15,1,12,1,9,1, + 15,1,12,1,22,1,15,1,9,1,12,1,22,1,12,1, + 9,1,12,1,19,1,114,85,0,0,0,99,1,0,0,0, + 0,0,0,0,5,0,0,0,12,0,0,0,67,0,0,0, + 115,164,0,0,0,116,0,0,124,0,0,131,1,0,100,1, + 0,107,2,0,114,22,0,100,2,0,83,124,0,0,106,1, + 0,100,3,0,131,1,0,92,3,0,125,1,0,125,2,0, + 125,3,0,124,1,0,12,115,81,0,124,3,0,106,2,0, + 131,0,0,100,7,0,100,8,0,133,2,0,25,100,6,0, + 107,3,0,114,85,0,124,0,0,83,121,16,0,116,3,0, + 124,0,0,131,1,0,125,4,0,87,110,40,0,4,116,4, + 0,116,5,0,102,2,0,107,10,0,114,143,0,1,1,1, + 124,0,0,100,2,0,100,9,0,133,2,0,25,125,4,0, + 89,110,1,0,88,116,6,0,124,4,0,131,1,0,114,160, + 0,124,4,0,83,124,0,0,83,41,10,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,59,0,0,0,78,114, + 58,0,0,0,114,80,0,0,0,114,29,0,0,0,90,2, + 112,121,233,253,255,255,255,233,255,255,255,255,114,87,0,0, + 0,41,7,114,31,0,0,0,114,32,0,0,0,218,5,108, + 111,119,101,114,114,85,0,0,0,114,66,0,0,0,114,71, + 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,78,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,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,15,95,103,101,116, + 95,115,111,117,114,99,101,102,105,108,101,62,1,0,0,115, + 20,0,0,0,0,7,18,1,4,1,24,1,35,1,4,1, + 3,1,16,1,19,1,21,1,114,91,0,0,0,99,1,0, + 0,0,0,0,0,0,1,0,0,0,11,0,0,0,67,0, + 0,0,115,92,0,0,0,124,0,0,106,0,0,116,1,0, + 116,2,0,131,1,0,131,1,0,114,59,0,121,14,0,116, + 3,0,124,0,0,131,1,0,83,87,113,88,0,4,116,4, + 0,107,10,0,114,55,0,1,1,1,89,113,88,0,88,110, + 29,0,124,0,0,106,0,0,116,1,0,116,5,0,131,1, + 0,131,1,0,114,84,0,124,0,0,83,100,0,0,83,100, + 0,0,83,41,1,78,41,6,218,8,101,110,100,115,119,105, + 116,104,218,5,116,117,112,108,101,114,84,0,0,0,114,79, + 0,0,0,114,66,0,0,0,114,74,0,0,0,41,1,218, + 8,102,105,108,101,110,97,109,101,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,11,95,103,101,116,95,99, + 97,99,104,101,100,81,1,0,0,115,16,0,0,0,0,1, + 21,1,3,1,14,1,13,1,8,1,21,1,4,2,114,95, + 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,60,0,0,0,121,19,0, + 116,0,0,124,0,0,131,1,0,106,1,0,125,1,0,87, + 110,24,0,4,116,2,0,107,10,0,114,45,0,1,1,1, + 100,1,0,125,1,0,89,110,1,0,88,124,1,0,100,2, + 0,79,125,1,0,124,1,0,83,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,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,10,95,99,97,108,99,95,109,111, + 100,101,93,1,0,0,115,12,0,0,0,0,2,3,1,19, + 1,13,1,11,3,10,1,114,97,0,0,0,218,9,118,101, + 114,98,111,115,105,116,121,114,29,0,0,0,99,1,0,0, + 0,1,0,0,0,3,0,0,0,4,0,0,0,71,0,0, + 0,115,75,0,0,0,116,0,0,106,1,0,106,2,0,124, + 1,0,107,5,0,114,71,0,124,0,0,106,3,0,100,6, + 0,131,1,0,115,43,0,100,3,0,124,0,0,23,125,0, + 0,116,4,0,124,0,0,106,5,0,124,2,0,140,0,0, + 100,4,0,116,0,0,106,6,0,131,1,1,1,100,5,0, + 83,41,7,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,250,1,35,250,7,105,109,112,111,114,116,32,122,2, + 35,32,114,54,0,0,0,78,41,2,114,99,0,0,0,114, + 100,0,0,0,41,7,114,7,0,0,0,114,67,0,0,0, + 218,7,118,101,114,98,111,115,101,114,9,0,0,0,218,5, + 112,114,105,110,116,114,47,0,0,0,218,6,115,116,100,101, + 114,114,41,3,114,75,0,0,0,114,98,0,0,0,218,4, + 97,114,103,115,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,16,95,118,101,114,98,111,115,101,95,109,101, + 115,115,97,103,101,105,1,0,0,115,8,0,0,0,0,2, + 18,1,15,1,10,1,114,105,0,0,0,99,1,0,0,0, + 0,0,0,0,3,0,0,0,11,0,0,0,3,0,0,0, + 115,84,0,0,0,100,1,0,135,0,0,102,1,0,100,2, + 0,100,3,0,134,1,0,125,1,0,121,13,0,116,0,0, + 106,1,0,125,2,0,87,110,30,0,4,116,2,0,107,10, + 0,114,66,0,1,1,1,100,4,0,100,5,0,132,0,0, + 125,2,0,89,110,1,0,88,124,2,0,124,1,0,136,0, + 0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31,0,0,0,115, + 80,0,0,0,124,1,0,100,0,0,107,8,0,114,24,0, + 124,0,0,106,0,0,125,1,0,110,37,0,124,0,0,106, + 0,0,124,1,0,107,3,0,114,61,0,116,1,0,100,1, + 0,124,1,0,22,100,2,0,124,1,0,131,1,1,130,1, + 0,136,0,0,124,0,0,124,1,0,124,2,0,124,3,0, + 142,2,0,83,41,3,78,122,23,108,111,97,100,101,114,32, + 99,97,110,110,111,116,32,104,97,110,100,108,101,32,37,115, + 218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0,90,6,107,119, + 97,114,103,115,41,1,218,6,109,101,116,104,111,100,114,4, + 0,0,0,114,5,0,0,0,218,19,95,99,104,101,99,107, + 95,110,97,109,101,95,119,114,97,112,112,101,114,121,1,0, + 0,115,10,0,0,0,0,1,12,1,12,1,15,1,22,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, + 92,0,0,0,120,66,0,100,1,0,100,2,0,100,3,0, + 100,4,0,103,4,0,68,93,46,0,125,2,0,116,0,0, + 124,1,0,124,2,0,131,2,0,114,19,0,116,1,0,124, + 0,0,124,2,0,116,2,0,124,1,0,124,2,0,131,2, + 0,131,3,0,1,113,19,0,87,124,0,0,106,3,0,106, + 4,0,124,1,0,106,3,0,131,1,0,1,100,0,0,83, + 41,5,78,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, + 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,114,52,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 5,95,119,114,97,112,131,1,0,0,115,8,0,0,0,0, + 1,25,1,15,1,29,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,3,218,10,95,98,111,111,116,115,116,114,97, + 112,114,120,0,0,0,218,9,78,97,109,101,69,114,114,111, + 114,41,3,114,109,0,0,0,114,110,0,0,0,114,120,0, + 0,0,114,4,0,0,0,41,1,114,109,0,0,0,114,5, + 0,0,0,218,11,95,99,104,101,99,107,95,110,97,109,101, + 113,1,0,0,115,14,0,0,0,0,8,21,6,3,1,13, + 1,13,2,17,5,13,1,114,123,0,0,0,99,2,0,0, + 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, + 0,115,84,0,0,0,124,0,0,106,0,0,124,1,0,131, + 1,0,92,2,0,125,2,0,125,3,0,124,2,0,100,1, + 0,107,8,0,114,80,0,116,1,0,124,3,0,131,1,0, + 114,80,0,100,2,0,125,4,0,116,2,0,106,3,0,124, + 4,0,106,4,0,124,3,0,100,3,0,25,131,1,0,116, + 5,0,131,2,0,1,124,2,0,83,41,4,122,155,84,114, + 121,32,116,111,32,102,105,110,100,32,97,32,108,111,97,100, + 101,114,32,102,111,114,32,116,104,101,32,115,112,101,99,105, + 102,105,101,100,32,109,111,100,117,108,101,32,98,121,32,100, + 101,108,101,103,97,116,105,110,103,32,116,111,10,32,32,32, + 32,115,101,108,102,46,102,105,110,100,95,108,111,97,100,101, + 114,40,41,46,10,10,32,32,32,32,84,104,105,115,32,109, + 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,32,105,110,32,102,97,118,111,114,32,111,102,32, + 102,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, + 40,41,46,10,10,32,32,32,32,78,122,44,78,111,116,32, + 105,109,112,111,114,116,105,110,103,32,100,105,114,101,99,116, + 111,114,121,32,123,125,58,32,109,105,115,115,105,110,103,32, + 95,95,105,110,105,116,95,95,114,59,0,0,0,41,6,218, + 11,102,105,110,100,95,108,111,97,100,101,114,114,31,0,0, + 0,114,60,0,0,0,114,61,0,0,0,114,47,0,0,0, + 218,13,73,109,112,111,114,116,87,97,114,110,105,110,103,41, + 5,114,108,0,0,0,218,8,102,117,108,108,110,97,109,101, + 218,6,108,111,97,100,101,114,218,8,112,111,114,116,105,111, + 110,115,218,3,109,115,103,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,17,95,102,105,110,100,95,109,111, + 100,117,108,101,95,115,104,105,109,140,1,0,0,115,10,0, + 0,0,0,10,21,1,24,1,6,1,29,1,114,130,0,0, + 0,99,4,0,0,0,0,0,0,0,11,0,0,0,19,0, + 0,0,67,0,0,0,115,228,1,0,0,105,0,0,125,4, + 0,124,2,0,100,1,0,107,9,0,114,31,0,124,2,0, + 124,4,0,100,2,0,60,110,6,0,100,3,0,125,2,0, + 124,3,0,100,1,0,107,9,0,114,59,0,124,3,0,124, + 4,0,100,4,0,60,124,0,0,100,1,0,100,5,0,133, + 2,0,25,125,5,0,124,0,0,100,5,0,100,6,0,133, + 2,0,25,125,6,0,124,0,0,100,6,0,100,7,0,133, + 2,0,25,125,7,0,124,5,0,116,0,0,107,3,0,114, + 165,0,100,8,0,106,1,0,124,2,0,124,5,0,131,2, + 0,125,8,0,116,2,0,124,8,0,131,1,0,1,116,3, + 0,124,8,0,124,4,0,141,1,0,130,1,0,110,113,0, + 116,4,0,124,6,0,131,1,0,100,5,0,107,3,0,114, + 223,0,100,9,0,106,1,0,124,2,0,131,1,0,125,8, + 0,116,2,0,124,8,0,131,1,0,1,116,5,0,124,8, + 0,131,1,0,130,1,0,110,55,0,116,4,0,124,7,0, + 131,1,0,100,5,0,107,3,0,114,22,1,100,10,0,106, + 1,0,124,2,0,131,1,0,125,8,0,116,2,0,124,8, + 0,131,1,0,1,116,5,0,124,8,0,131,1,0,130,1, + 0,124,1,0,100,1,0,107,9,0,114,214,1,121,20,0, + 116,6,0,124,1,0,100,11,0,25,131,1,0,125,9,0, + 87,110,18,0,4,116,7,0,107,10,0,114,74,1,1,1, + 1,89,110,59,0,88,116,8,0,124,6,0,131,1,0,124, + 9,0,107,3,0,114,133,1,100,12,0,106,1,0,124,2, + 0,131,1,0,125,8,0,116,2,0,124,8,0,131,1,0, + 1,116,3,0,124,8,0,124,4,0,141,1,0,130,1,0, + 121,18,0,124,1,0,100,13,0,25,100,14,0,64,125,10, + 0,87,110,18,0,4,116,7,0,107,10,0,114,171,1,1, + 1,1,89,110,43,0,88,116,8,0,124,7,0,131,1,0, + 124,10,0,107,3,0,114,214,1,116,3,0,100,12,0,106, + 1,0,124,2,0,131,1,0,124,4,0,141,1,0,130,1, + 0,124,0,0,100,7,0,100,1,0,133,2,0,25,83,41, + 15,97,122,1,0,0,86,97,108,105,100,97,116,101,32,116, + 104,101,32,104,101,97,100,101,114,32,111,102,32,116,104,101, + 32,112,97,115,115,101,100,45,105,110,32,98,121,116,101,99, + 111,100,101,32,97,103,97,105,110,115,116,32,115,111,117,114, + 99,101,95,115,116,97,116,115,32,40,105,102,10,32,32,32, + 32,103,105,118,101,110,41,32,97,110,100,32,114,101,116,117, + 114,110,105,110,103,32,116,104,101,32,98,121,116,101,99,111, + 100,101,32,116,104,97,116,32,99,97,110,32,98,101,32,99, + 111,109,112,105,108,101,100,32,98,121,32,99,111,109,112,105, + 108,101,40,41,46,10,10,32,32,32,32,65,108,108,32,111, + 116,104,101,114,32,97,114,103,117,109,101,110,116,115,32,97, + 114,101,32,117,115,101,100,32,116,111,32,101,110,104,97,110, + 99,101,32,101,114,114,111,114,32,114,101,112,111,114,116,105, + 110,103,46,10,10,32,32,32,32,73,109,112,111,114,116,69, + 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,119, + 104,101,110,32,116,104,101,32,109,97,103,105,99,32,110,117, + 109,98,101,114,32,105,115,32,105,110,99,111,114,114,101,99, + 116,32,111,114,32,116,104,101,32,98,121,116,101,99,111,100, + 101,32,105,115,10,32,32,32,32,102,111,117,110,100,32,116, + 111,32,98,101,32,115,116,97,108,101,46,32,69,79,70,69, + 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,119, + 104,101,110,32,116,104,101,32,100,97,116,97,32,105,115,32, + 102,111,117,110,100,32,116,111,32,98,101,10,32,32,32,32, + 116,114,117,110,99,97,116,101,100,46,10,10,32,32,32,32, + 78,114,106,0,0,0,122,10,60,98,121,116,101,99,111,100, + 101,62,114,35,0,0,0,114,12,0,0,0,233,8,0,0, + 0,233,12,0,0,0,122,30,98,97,100,32,109,97,103,105, + 99,32,110,117,109,98,101,114,32,105,110,32,123,33,114,125, + 58,32,123,33,114,125,122,43,114,101,97,99,104,101,100,32, + 69,79,70,32,119,104,105,108,101,32,114,101,97,100,105,110, + 103,32,116,105,109,101,115,116,97,109,112,32,105,110,32,123, + 33,114,125,122,48,114,101,97,99,104,101,100,32,69,79,70, + 32,119,104,105,108,101,32,114,101,97,100,105,110,103,32,115, + 105,122,101,32,111,102,32,115,111,117,114,99,101,32,105,110, + 32,123,33,114,125,218,5,109,116,105,109,101,122,26,98,121, + 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,32, + 102,111,114,32,123,33,114,125,218,4,115,105,122,101,108,3, + 0,0,0,255,127,255,127,3,0,41,9,218,12,77,65,71, + 73,67,95,78,85,77,66,69,82,114,47,0,0,0,114,105, + 0,0,0,114,107,0,0,0,114,31,0,0,0,218,8,69, + 79,70,69,114,114,111,114,114,14,0,0,0,218,8,75,101, + 121,69,114,114,111,114,114,19,0,0,0,41,11,114,53,0, + 0,0,218,12,115,111,117,114,99,101,95,115,116,97,116,115, + 114,106,0,0,0,114,35,0,0,0,90,11,101,120,99,95, + 100,101,116,97,105,108,115,90,5,109,97,103,105,99,90,13, + 114,97,119,95,116,105,109,101,115,116,97,109,112,90,8,114, + 97,119,95,115,105,122,101,114,75,0,0,0,218,12,115,111, + 117,114,99,101,95,109,116,105,109,101,218,11,115,111,117,114, + 99,101,95,115,105,122,101,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,25,95,118,97,108,105,100,97,116, + 101,95,98,121,116,101,99,111,100,101,95,104,101,97,100,101, + 114,157,1,0,0,115,76,0,0,0,0,11,6,1,12,1, + 13,3,6,1,12,1,10,1,16,1,16,1,16,1,12,1, + 18,1,10,1,18,1,18,1,15,1,10,1,15,1,18,1, + 15,1,10,1,12,1,12,1,3,1,20,1,13,1,5,2, + 18,1,15,1,10,1,15,1,3,1,18,1,13,1,5,2, + 18,1,15,1,9,1,114,141,0,0,0,99,4,0,0,0, + 0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,0, + 115,112,0,0,0,116,0,0,106,1,0,124,0,0,131,1, + 0,125,4,0,116,2,0,124,4,0,116,3,0,131,2,0, + 114,75,0,116,4,0,100,1,0,124,2,0,131,2,0,1, + 124,3,0,100,2,0,107,9,0,114,71,0,116,5,0,106, + 6,0,124,4,0,124,3,0,131,2,0,1,124,4,0,83, + 116,7,0,100,3,0,106,8,0,124,2,0,131,1,0,100, + 4,0,124,1,0,100,5,0,124,2,0,131,1,2,130,1, + 0,100,2,0,83,41,6,122,60,67,111,109,112,105,108,101, + 32,98,121,116,101,99,111,100,101,32,97,115,32,114,101,116, + 117,114,110,101,100,32,98,121,32,95,118,97,108,105,100,97, + 116,101,95,98,121,116,101,99,111,100,101,95,104,101,97,100, + 101,114,40,41,46,122,21,99,111,100,101,32,111,98,106,101, + 99,116,32,102,114,111,109,32,123,33,114,125,78,122,23,78, + 111,110,45,99,111,100,101,32,111,98,106,101,99,116,32,105, + 110,32,123,33,114,125,114,106,0,0,0,114,35,0,0,0, + 41,9,218,7,109,97,114,115,104,97,108,90,5,108,111,97, + 100,115,218,10,105,115,105,110,115,116,97,110,99,101,218,10, + 95,99,111,100,101,95,116,121,112,101,114,105,0,0,0,218, + 4,95,105,109,112,90,16,95,102,105,120,95,99,111,95,102, + 105,108,101,110,97,109,101,114,107,0,0,0,114,47,0,0, + 0,41,5,114,53,0,0,0,114,106,0,0,0,114,89,0, + 0,0,114,90,0,0,0,218,4,99,111,100,101,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,17,95,99, + 111,109,112,105,108,101,95,98,121,116,101,99,111,100,101,212, + 1,0,0,115,16,0,0,0,0,2,15,1,15,1,13,1, + 12,1,16,1,4,2,18,1,114,147,0,0,0,114,59,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,76,0,0,0,116,0,0,116, + 1,0,131,1,0,125,3,0,124,3,0,106,2,0,116,3, + 0,124,1,0,131,1,0,131,1,0,1,124,3,0,106,2, + 0,116,3,0,124,2,0,131,1,0,131,1,0,1,124,3, + 0,106,2,0,116,4,0,106,5,0,124,0,0,131,1,0, + 131,1,0,1,124,3,0,83,41,1,122,80,67,111,109,112, + 105,108,101,32,97,32,99,111,100,101,32,111,98,106,101,99, + 116,32,105,110,116,111,32,98,121,116,101,99,111,100,101,32, + 102,111,114,32,119,114,105,116,105,110,103,32,111,117,116,32, + 116,111,32,97,32,98,121,116,101,45,99,111,109,112,105,108, + 101,100,10,32,32,32,32,102,105,108,101,46,41,6,218,9, + 98,121,116,101,97,114,114,97,121,114,135,0,0,0,218,6, + 101,120,116,101,110,100,114,17,0,0,0,114,142,0,0,0, + 90,5,100,117,109,112,115,41,4,114,146,0,0,0,114,133, + 0,0,0,114,140,0,0,0,114,53,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,17,95,99, + 111,100,101,95,116,111,95,98,121,116,101,99,111,100,101,224, + 1,0,0,115,10,0,0,0,0,3,12,1,19,1,19,1, + 22,1,114,150,0,0,0,99,1,0,0,0,0,0,0,0, + 5,0,0,0,4,0,0,0,67,0,0,0,115,89,0,0, + 0,100,1,0,100,2,0,108,0,0,125,1,0,116,1,0, + 106,2,0,124,0,0,131,1,0,106,3,0,125,2,0,124, + 1,0,106,4,0,124,2,0,131,1,0,125,3,0,116,1, + 0,106,5,0,100,2,0,100,3,0,131,2,0,125,4,0, + 124,4,0,106,6,0,124,0,0,106,6,0,124,3,0,100, + 1,0,25,131,1,0,131,1,0,83,41,4,122,121,68,101, + 99,111,100,101,32,98,121,116,101,115,32,114,101,112,114,101, + 115,101,110,116,105,110,103,32,115,111,117,114,99,101,32,99, + 111,100,101,32,97,110,100,32,114,101,116,117,114,110,32,116, + 104,101,32,115,116,114,105,110,103,46,10,10,32,32,32,32, + 85,110,105,118,101,114,115,97,108,32,110,101,119,108,105,110, + 101,32,115,117,112,112,111,114,116,32,105,115,32,117,115,101, + 100,32,105,110,32,116,104,101,32,100,101,99,111,100,105,110, + 103,46,10,32,32,32,32,114,59,0,0,0,78,84,41,7, + 218,8,116,111,107,101,110,105,122,101,114,49,0,0,0,90, + 7,66,121,116,101,115,73,79,90,8,114,101,97,100,108,105, + 110,101,90,15,100,101,116,101,99,116,95,101,110,99,111,100, + 105,110,103,90,25,73,110,99,114,101,109,101,110,116,97,108, + 78,101,119,108,105,110,101,68,101,99,111,100,101,114,218,6, + 100,101,99,111,100,101,41,5,218,12,115,111,117,114,99,101, + 95,98,121,116,101,115,114,151,0,0,0,90,21,115,111,117, + 114,99,101,95,98,121,116,101,115,95,114,101,97,100,108,105, + 110,101,218,8,101,110,99,111,100,105,110,103,90,15,110,101, + 119,108,105,110,101,95,100,101,99,111,100,101,114,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,13,100,101, + 99,111,100,101,95,115,111,117,114,99,101,234,1,0,0,115, + 10,0,0,0,0,5,12,1,18,1,15,1,18,1,114,155, + 0,0,0,114,127,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,19,0,0,0,67,0,0,0,115,89,1,0,0,124,1, + 0,100,1,0,107,8,0,114,73,0,100,2,0,125,1,0, + 116,0,0,124,2,0,100,3,0,131,2,0,114,73,0,121, + 19,0,124,2,0,106,1,0,124,0,0,131,1,0,125,1, + 0,87,110,18,0,4,116,2,0,107,10,0,114,72,0,1, + 1,1,89,110,1,0,88,116,3,0,106,4,0,124,0,0, + 124,2,0,100,4,0,124,1,0,131,2,1,125,4,0,100, + 5,0,124,4,0,95,5,0,124,2,0,100,1,0,107,8, + 0,114,194,0,120,73,0,116,6,0,131,0,0,68,93,58, + 0,92,2,0,125,5,0,125,6,0,124,1,0,106,7,0, + 116,8,0,124,6,0,131,1,0,131,1,0,114,128,0,124, + 5,0,124,0,0,124,1,0,131,2,0,125,2,0,124,2, + 0,124,4,0,95,9,0,80,113,128,0,87,100,1,0,83, + 124,3,0,116,10,0,107,8,0,114,23,1,116,0,0,124, + 2,0,100,6,0,131,2,0,114,32,1,121,19,0,124,2, + 0,106,11,0,124,0,0,131,1,0,125,7,0,87,110,18, + 0,4,116,2,0,107,10,0,114,4,1,1,1,1,89,113, + 32,1,88,124,7,0,114,32,1,103,0,0,124,4,0,95, + 12,0,110,9,0,124,3,0,124,4,0,95,12,0,124,4, + 0,106,12,0,103,0,0,107,2,0,114,85,1,124,1,0, + 114,85,1,116,13,0,124,1,0,131,1,0,100,7,0,25, + 125,8,0,124,4,0,106,12,0,106,14,0,124,8,0,131, + 1,0,1,124,4,0,83,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,218,6,111,114,105,103,105,110,84,218,10, + 105,115,95,112,97,99,107,97,103,101,114,59,0,0,0,41, + 15,114,115,0,0,0,114,157,0,0,0,114,107,0,0,0, + 114,121,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,92,0, + 0,0,114,93,0,0,0,114,127,0,0,0,218,9,95,80, + 79,80,85,76,65,84,69,114,159,0,0,0,114,156,0,0, + 0,114,38,0,0,0,218,6,97,112,112,101,110,100,41,9, + 114,106,0,0,0,90,8,108,111,99,97,116,105,111,110,114, + 127,0,0,0,114,156,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,159,0,0,0,90,7,100,105, + 114,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114, + 5,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,251,1,0, + 0,115,60,0,0,0,0,12,12,4,6,1,15,2,3,1, + 19,1,13,1,5,8,24,1,9,3,12,1,22,1,21,1, + 15,1,9,1,5,2,4,3,12,2,15,1,3,1,19,1, + 13,1,5,2,6,1,12,2,9,1,15,1,6,1,16,1, + 16,2,114,167,0,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,64,0,0,0,115,121,0,0, + 0,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, + 90,3,0,100,2,0,90,4,0,100,3,0,90,5,0,100, + 4,0,90,6,0,101,7,0,100,5,0,100,6,0,132,0, + 0,131,1,0,90,8,0,101,7,0,100,7,0,100,8,0, + 132,0,0,131,1,0,90,9,0,101,7,0,100,9,0,100, + 9,0,100,10,0,100,11,0,132,2,0,131,1,0,90,10, + 0,101,7,0,100,9,0,100,12,0,100,13,0,132,1,0, + 131,1,0,90,11,0,100,9,0,83,41,14,218,21,87,105, + 110,100,111,119,115,82,101,103,105,115,116,114,121,70,105,110, + 100,101,114,122,62,77,101,116,97,32,112,97,116,104,32,102, + 105,110,100,101,114,32,102,111,114,32,109,111,100,117,108,101, + 115,32,100,101,99,108,97,114,101,100,32,105,110,32,116,104, + 101,32,87,105,110,100,111,119,115,32,114,101,103,105,115,116, + 114,121,46,122,59,83,111,102,116,119,97,114,101,92,80,121, + 116,104,111,110,92,80,121,116,104,111,110,67,111,114,101,92, + 123,115,121,115,95,118,101,114,115,105,111,110,125,92,77,111, + 100,117,108,101,115,92,123,102,117,108,108,110,97,109,101,125, + 122,65,83,111,102,116,119,97,114,101,92,80,121,116,104,111, + 110,92,80,121,116,104,111,110,67,111,114,101,92,123,115,121, + 115,95,118,101,114,115,105,111,110,125,92,77,111,100,117,108, + 101,115,92,123,102,117,108,108,110,97,109,101,125,92,68,101, + 98,117,103,70,99,2,0,0,0,0,0,0,0,2,0,0, + 0,11,0,0,0,67,0,0,0,115,67,0,0,0,121,23, + 0,116,0,0,106,1,0,116,0,0,106,2,0,124,1,0, + 131,2,0,83,87,110,37,0,4,116,3,0,107,10,0,114, + 62,0,1,1,1,116,0,0,106,1,0,116,0,0,106,4, + 0,124,1,0,131,2,0,83,89,110,1,0,88,100,0,0, + 83,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,218,3,107,101,121, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 14,95,111,112,101,110,95,114,101,103,105,115,116,114,121,73, + 2,0,0,115,8,0,0,0,0,2,3,1,23,1,13,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,16,0,0,0,67,0,0,0,115,143,0,0,0, + 124,0,0,106,0,0,114,21,0,124,0,0,106,1,0,125, + 2,0,110,9,0,124,0,0,106,2,0,125,2,0,124,2, + 0,106,3,0,100,1,0,124,1,0,100,2,0,116,4,0, + 106,5,0,100,0,0,100,3,0,133,2,0,25,131,0,2, + 125,3,0,121,47,0,124,0,0,106,6,0,124,3,0,131, + 1,0,143,25,0,125,4,0,116,7,0,106,8,0,124,4, + 0,100,4,0,131,2,0,125,5,0,87,100,0,0,81,82, + 88,87,110,22,0,4,116,9,0,107,10,0,114,138,0,1, + 1,1,100,0,0,83,89,110,1,0,88,124,5,0,83,41, + 5,78,114,126,0,0,0,90,11,115,121,115,95,118,101,114, + 115,105,111,110,114,80,0,0,0,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, + 47,0,0,0,114,7,0,0,0,218,7,118,101,114,115,105, + 111,110,114,172,0,0,0,114,169,0,0,0,90,10,81,117, + 101,114,121,86,97,108,117,101,114,40,0,0,0,41,6,114, + 170,0,0,0,114,126,0,0,0,90,12,114,101,103,105,115, + 116,114,121,95,107,101,121,114,171,0,0,0,90,4,104,107, + 101,121,218,8,102,105,108,101,112,97,116,104,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,16,95,115,101, + 97,114,99,104,95,114,101,103,105,115,116,114,121,80,2,0, + 0,115,22,0,0,0,0,2,9,1,12,2,9,1,15,1, + 22,1,3,1,18,1,29,1,13,1,9,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,14,0,0,0,67,0,0,0,115,158,0,0,0,124, + 0,0,106,0,0,124,1,0,131,1,0,125,4,0,124,4, + 0,100,0,0,107,8,0,114,31,0,100,0,0,83,121,14, + 0,116,1,0,124,4,0,131,1,0,1,87,110,22,0,4, + 116,2,0,107,10,0,114,69,0,1,1,1,100,0,0,83, + 89,110,1,0,88,120,81,0,116,3,0,131,0,0,68,93, + 70,0,92,2,0,125,5,0,125,6,0,124,4,0,106,4, + 0,116,5,0,124,6,0,131,1,0,131,1,0,114,80,0, + 116,6,0,106,7,0,124,1,0,124,5,0,124,1,0,124, + 4,0,131,2,0,100,1,0,124,4,0,131,2,1,125,7, + 0,124,7,0,83,113,80,0,87,100,0,0,83,41,2,78, + 114,158,0,0,0,41,8,114,178,0,0,0,114,39,0,0, + 0,114,40,0,0,0,114,161,0,0,0,114,92,0,0,0, + 114,93,0,0,0,114,121,0,0,0,218,16,115,112,101,99, + 95,102,114,111,109,95,108,111,97,100,101,114,41,8,114,170, + 0,0,0,114,126,0,0,0,114,35,0,0,0,218,6,116, + 97,114,103,101,116,114,177,0,0,0,114,127,0,0,0,114, + 166,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,9,102,105,110,100,95,115, + 112,101,99,95,2,0,0,115,26,0,0,0,0,2,15,1, + 12,1,4,1,3,1,14,1,13,1,9,1,22,1,21,1, + 9,1,15,1,9,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,3,0,0,0,67,0,0,0,115,45,0,0, + 0,124,0,0,106,0,0,124,1,0,124,2,0,131,2,0, + 125,3,0,124,3,0,100,1,0,107,9,0,114,37,0,124, + 3,0,106,1,0,83,100,1,0,83,100,1,0,83,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,181,0,0,0,114,127,0,0,0,41,4,114,170,0, + 0,0,114,126,0,0,0,114,35,0,0,0,114,164,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,11,102,105,110,100,95,109,111,100,117,108,101,111,2,0, + 0,115,8,0,0,0,0,7,18,1,12,1,7,2,122,33, + 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, + 105,110,100,101,114,46,102,105,110,100,95,109,111,100,117,108, + 101,41,12,114,112,0,0,0,114,111,0,0,0,114,113,0, + 0,0,114,114,0,0,0,114,175,0,0,0,114,174,0,0, + 0,114,173,0,0,0,218,11,99,108,97,115,115,109,101,116, + 104,111,100,114,172,0,0,0,114,178,0,0,0,114,181,0, + 0,0,114,182,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,168,0,0,0, + 61,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, + 2,6,2,18,7,18,15,3,1,21,15,3,1,114,168,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,70,0,0,0,101,0,0,90, + 1,0,100,0,0,90,2,0,100,1,0,90,3,0,100,2, + 0,100,3,0,132,0,0,90,4,0,100,4,0,100,5,0, + 132,0,0,90,5,0,100,6,0,100,7,0,132,0,0,90, + 6,0,100,8,0,100,9,0,132,0,0,90,7,0,100,10, + 0,83,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,3,0,0,0,67,0,0,0,115,88,0, + 0,0,116,0,0,124,0,0,106,1,0,124,1,0,131,1, + 0,131,1,0,100,1,0,25,125,2,0,124,2,0,106,2, + 0,100,2,0,100,1,0,131,2,0,100,3,0,25,125,3, + 0,124,1,0,106,3,0,100,2,0,131,1,0,100,4,0, + 25,125,4,0,124,3,0,100,5,0,107,2,0,111,87,0, + 124,4,0,100,5,0,107,3,0,83,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,58,0,0,0,114,59,0,0,0,114,56,0,0,0,218, + 8,95,95,105,110,105,116,95,95,41,4,114,38,0,0,0, + 114,157,0,0,0,114,34,0,0,0,114,32,0,0,0,41, + 5,114,108,0,0,0,114,126,0,0,0,114,94,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,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,159,0,0,0,130,2, + 0,0,115,8,0,0,0,0,3,25,1,22,1,19,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,0,83,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,4,0,0,0,41,2,114,108,0, + 0,0,114,164,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,13,99,114,101,97,116,101,95,109, + 111,100,117,108,101,138,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,4,0,0,0,67,0,0,0, + 115,80,0,0,0,124,0,0,106,0,0,124,1,0,106,1, + 0,131,1,0,125,2,0,124,2,0,100,1,0,107,8,0, + 114,54,0,116,2,0,100,2,0,106,3,0,124,1,0,106, + 1,0,131,1,0,131,1,0,130,1,0,116,4,0,106,5, + 0,116,6,0,124,2,0,124,1,0,106,7,0,131,3,0, + 1,100,1,0,83,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, + 112,0,0,0,114,107,0,0,0,114,47,0,0,0,114,121, + 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,118,0,0,0,41,3,114,108,0,0,0, + 218,6,109,111,100,117,108,101,114,146,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,11,101,120, + 101,99,95,109,111,100,117,108,101,141,2,0,0,115,10,0, + 0,0,0,2,18,1,12,1,9,1,15,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,3,0,0,0,67,0,0,0,115,16,0,0, + 0,116,0,0,106,1,0,124,0,0,124,1,0,131,2,0, + 83,41,1,78,41,2,114,121,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,11,108,111,97,100,95, + 109,111,100,117,108,101,149,2,0,0,115,2,0,0,0,0, + 1,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, + 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, + 0,0,0,114,159,0,0,0,114,186,0,0,0,114,191,0, + 0,0,114,193,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,184,0,0,0, + 125,2,0,0,115,10,0,0,0,12,3,6,2,12,8,12, + 3,12,8,114,184,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,106,0, + 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, + 0,100,2,0,132,0,0,90,3,0,100,3,0,100,4,0, + 132,0,0,90,4,0,100,5,0,100,6,0,132,0,0,90, + 5,0,100,7,0,100,8,0,132,0,0,90,6,0,100,9, + 0,100,10,0,132,0,0,90,7,0,100,11,0,100,18,0, + 100,13,0,100,14,0,132,0,1,90,8,0,100,15,0,100, + 16,0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0,83, + 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,73,79,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,218,7,73,79,69,114,114, + 111,114,41,2,114,108,0,0,0,114,35,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,112, + 97,116,104,95,109,116,105,109,101,155,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,3,0,0,0,67,0, + 0,0,115,19,0,0,0,124,0,0,106,0,0,124,1,0, + 131,1,0,100,1,0,105,1,0,83,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,73,79,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,133,0,0,0, + 41,1,114,196,0,0,0,41,2,114,108,0,0,0,114,35, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,10,112,97,116,104,95,115,116,97,116,115,163,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,3, + 0,0,0,67,0,0,0,115,16,0,0,0,124,0,0,106, + 0,0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99,97, + 99,104,101,95,112,97,116,104,114,53,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,15,95,99, + 97,99,104,101,95,98,121,116,101,99,111,100,101,176,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,0,83,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, + 4,0,0,0,41,3,114,108,0,0,0,114,35,0,0,0, + 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,198,0,0,0,186,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,16,0,0,0,67,0,0,0,115,105, + 0,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, + 2,0,121,19,0,124,0,0,106,1,0,124,2,0,131,1, + 0,125,3,0,87,110,58,0,4,116,2,0,107,10,0,114, + 94,0,1,125,4,0,1,122,26,0,116,3,0,100,1,0, + 100,2,0,124,1,0,131,1,1,124,4,0,130,2,0,87, + 89,100,3,0,100,3,0,125,4,0,126,4,0,88,110,1, + 0,88,116,4,0,124,3,0,131,1,0,83,41,4,122,52, + 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, + 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, + 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, + 103,104,32,103,101,116,95,100,97,116,97,40,41,114,106,0, + 0,0,78,41,5,114,157,0,0,0,218,8,103,101,116,95, + 100,97,116,97,114,40,0,0,0,114,107,0,0,0,114,155, + 0,0,0,41,5,114,108,0,0,0,114,126,0,0,0,114, + 35,0,0,0,114,153,0,0,0,218,3,101,120,99,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,103, + 101,116,95,115,111,117,114,99,101,193,2,0,0,115,14,0, + 0,0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105, + 109,105,122,101,114,29,0,0,0,99,3,0,0,0,1,0, + 0,0,4,0,0,0,9,0,0,0,67,0,0,0,115,34, + 0,0,0,116,0,0,106,1,0,116,2,0,124,1,0,124, + 2,0,100,1,0,100,2,0,100,3,0,100,4,0,124,3, + 0,131,4,2,83,41,5,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,189,0,0,0, + 218,12,100,111,110,116,95,105,110,104,101,114,105,116,84,114, + 68,0,0,0,41,3,114,121,0,0,0,114,188,0,0,0, + 218,7,99,111,109,112,105,108,101,41,4,114,108,0,0,0, + 114,53,0,0,0,114,35,0,0,0,114,203,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,14, + 115,111,117,114,99,101,95,116,111,95,99,111,100,101,203,2, + 0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174,1, + 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, + 0,100,1,0,125,3,0,121,16,0,116,1,0,124,2,0, + 131,1,0,125,4,0,87,110,24,0,4,116,2,0,107,10, + 0,114,63,0,1,1,1,100,1,0,125,4,0,89,110,202, + 0,88,121,19,0,124,0,0,106,3,0,124,2,0,131,1, + 0,125,5,0,87,110,18,0,4,116,4,0,107,10,0,114, + 103,0,1,1,1,89,110,162,0,88,116,5,0,124,5,0, + 100,2,0,25,131,1,0,125,3,0,121,19,0,124,0,0, + 106,6,0,124,4,0,131,1,0,125,6,0,87,110,18,0, + 4,116,7,0,107,10,0,114,159,0,1,1,1,89,110,106, + 0,88,121,34,0,116,8,0,124,6,0,100,3,0,124,5, + 0,100,4,0,124,1,0,100,5,0,124,4,0,131,1,3, + 125,7,0,87,110,24,0,4,116,9,0,116,10,0,102,2, + 0,107,10,0,114,220,0,1,1,1,89,110,45,0,88,116, + 11,0,100,6,0,124,4,0,124,2,0,131,3,0,1,116, + 12,0,124,7,0,100,4,0,124,1,0,100,7,0,124,4, + 0,100,8,0,124,2,0,131,1,3,83,124,0,0,106,6, + 0,124,2,0,131,1,0,125,8,0,124,0,0,106,13,0, + 124,8,0,124,2,0,131,2,0,125,9,0,116,11,0,100, + 9,0,124,2,0,131,2,0,1,116,14,0,106,15,0,12, + 114,170,1,124,4,0,100,1,0,107,9,0,114,170,1,124, + 3,0,100,1,0,107,9,0,114,170,1,116,16,0,124,9, + 0,124,3,0,116,17,0,124,8,0,131,1,0,131,3,0, + 125,6,0,121,36,0,124,0,0,106,18,0,124,2,0,124, + 4,0,124,6,0,131,3,0,1,116,11,0,100,10,0,124, + 4,0,131,2,0,1,87,110,18,0,4,116,2,0,107,10, + 0,114,169,1,1,1,1,89,110,1,0,88,124,9,0,83, + 41,11,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,114,133,0,0,0,114,138,0,0,0,114,106,0, + 0,0,114,35,0,0,0,122,13,123,125,32,109,97,116,99, + 104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,157,0,0,0,114,79,0,0,0,114,66,0, + 0,0,114,197,0,0,0,114,195,0,0,0,114,14,0,0, + 0,114,200,0,0,0,114,40,0,0,0,114,141,0,0,0, + 114,107,0,0,0,114,136,0,0,0,114,105,0,0,0,114, + 147,0,0,0,114,206,0,0,0,114,7,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,150,0,0,0,114,31,0,0,0,114,199,0, + 0,0,41,10,114,108,0,0,0,114,126,0,0,0,114,90, + 0,0,0,114,139,0,0,0,114,89,0,0,0,218,2,115, + 116,114,53,0,0,0,218,10,98,121,116,101,115,95,100,97, + 116,97,114,153,0,0,0,90,11,99,111,100,101,95,111,98, + 106,101,99,116,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,187,0,0,0,211,2,0,0,115,78,0,0, + 0,0,7,15,1,6,1,3,1,16,1,13,1,11,2,3, + 1,19,1,13,1,5,2,16,1,3,1,19,1,13,1,5, + 2,3,1,9,1,12,1,13,1,19,1,5,2,9,1,7, + 1,15,1,6,1,7,1,15,1,18,1,13,1,22,1,12, + 1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112, + 0,0,0,114,111,0,0,0,114,113,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,187,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,6,0,0,0,34,0, - 0,0,115,2,0,0,0,0,2,41,4,218,3,115,121,115, - 218,8,112,108,97,116,102,111,114,109,218,10,115,116,97,114, - 116,115,119,105,116,104,218,27,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,41,1,114,6,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,16,95,109,97,107,101, - 95,114,101,108,97,120,95,99,97,115,101,28,0,0,0,115, - 8,0,0,0,0,1,18,1,15,4,12,3,114,11,0,0, - 0,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,26,0,0,0,116,0,0,124,0, - 0,131,1,0,100,1,0,64,106,1,0,100,2,0,100,3, - 0,131,2,0,83,41,4,122,42,67,111,110,118,101,114,116, - 32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101, - 114,32,116,111,32,108,105,116,116,108,101,45,101,110,100,105, - 97,110,46,108,3,0,0,0,255,127,255,127,3,0,233,4, - 0,0,0,218,6,108,105,116,116,108,101,41,2,218,3,105, - 110,116,218,8,116,111,95,98,121,116,101,115,41,1,218,1, - 120,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,7,95,119,95,108,111,110,103,40,0,0,0,115,2,0, - 0,0,0,2,114,17,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,16, - 0,0,0,116,0,0,106,1,0,124,0,0,100,1,0,131, - 2,0,83,41,2,122,47,67,111,110,118,101,114,116,32,52, - 32,98,121,116,101,115,32,105,110,32,108,105,116,116,108,101, - 45,101,110,100,105,97,110,32,116,111,32,97,110,32,105,110, - 116,101,103,101,114,46,114,13,0,0,0,41,2,114,14,0, - 0,0,218,10,102,114,111,109,95,98,121,116,101,115,41,1, - 90,9,105,110,116,95,98,121,116,101,115,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,7,95,114,95,108, - 111,110,103,45,0,0,0,115,2,0,0,0,0,2,114,19, - 0,0,0,99,0,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,71,0,0,0,115,26,0,0,0,116,0,0, - 106,1,0,100,1,0,100,2,0,132,0,0,124,0,0,68, - 131,1,0,131,1,0,83,41,3,122,31,82,101,112,108,97, - 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, - 116,104,46,106,111,105,110,40,41,46,99,1,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,83,0,0,0,115, - 37,0,0,0,103,0,0,124,0,0,93,27,0,125,1,0, - 124,1,0,114,6,0,124,1,0,106,0,0,116,1,0,131, - 1,0,145,2,0,113,6,0,83,114,4,0,0,0,41,2, - 218,6,114,115,116,114,105,112,218,15,112,97,116,104,95,115, - 101,112,97,114,97,116,111,114,115,41,2,218,2,46,48,218, - 4,112,97,114,116,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,250,10,60,108,105,115,116,99,111,109,112,62, - 52,0,0,0,115,2,0,0,0,9,1,122,30,95,112,97, - 116,104,95,106,111,105,110,46,60,108,111,99,97,108,115,62, - 46,60,108,105,115,116,99,111,109,112,62,41,2,218,8,112, - 97,116,104,95,115,101,112,218,4,106,111,105,110,41,1,218, - 10,112,97,116,104,95,112,97,114,116,115,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,10,95,112,97,116, - 104,95,106,111,105,110,50,0,0,0,115,4,0,0,0,0, - 2,15,1,114,28,0,0,0,99,1,0,0,0,0,0,0, - 0,5,0,0,0,5,0,0,0,67,0,0,0,115,134,0, - 0,0,116,0,0,116,1,0,131,1,0,100,1,0,107,2, - 0,114,52,0,124,0,0,106,2,0,116,3,0,131,1,0, - 92,3,0,125,1,0,125,2,0,125,3,0,124,1,0,124, - 3,0,102,2,0,83,120,69,0,116,4,0,124,0,0,131, - 1,0,68,93,55,0,125,4,0,124,4,0,116,1,0,107, - 6,0,114,65,0,124,0,0,106,5,0,124,4,0,100,2, - 0,100,1,0,131,1,1,92,2,0,125,1,0,125,3,0, - 124,1,0,124,3,0,102,2,0,83,113,65,0,87,100,3, - 0,124,0,0,102,2,0,83,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,90,8,109,97,120,115,112,108,105,116,218,0,41,6,218, - 3,108,101,110,114,21,0,0,0,218,10,114,112,97,114,116, - 105,116,105,111,110,114,25,0,0,0,218,8,114,101,118,101, - 114,115,101,100,218,6,114,115,112,108,105,116,41,5,218,4, - 112,97,116,104,90,5,102,114,111,110,116,218,1,95,218,4, - 116,97,105,108,114,16,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,11,95,112,97,116,104,95, - 115,112,108,105,116,56,0,0,0,115,16,0,0,0,0,2, - 18,1,24,1,10,1,19,1,12,1,27,1,14,1,114,38, - 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,13,0,0,0,116,0,0, - 106,1,0,124,0,0,131,1,0,83,41,1,122,126,83,116, - 97,116,32,116,104,101,32,112,97,116,104,46,10,10,32,32, - 32,32,77,97,100,101,32,97,32,115,101,112,97,114,97,116, - 101,32,102,117,110,99,116,105,111,110,32,116,111,32,109,97, - 107,101,32,105,116,32,101,97,115,105,101,114,32,116,111,32, - 111,118,101,114,114,105,100,101,32,105,110,32,101,120,112,101, - 114,105,109,101,110,116,115,10,32,32,32,32,40,101,46,103, - 46,32,99,97,99,104,101,32,115,116,97,116,32,114,101,115, - 117,108,116,115,41,46,10,10,32,32,32,32,41,2,114,3, - 0,0,0,90,4,115,116,97,116,41,1,114,35,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 10,95,112,97,116,104,95,115,116,97,116,68,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,11,0,0,0,67,0,0,0, - 115,58,0,0,0,121,16,0,116,0,0,124,0,0,131,1, - 0,125,2,0,87,110,22,0,4,116,1,0,107,10,0,114, - 40,0,1,1,1,100,1,0,83,89,110,1,0,88,124,2, - 0,106,2,0,100,2,0,64,124,1,0,107,2,0,83,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,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,18,95,112,97,116, - 104,95,105,115,95,109,111,100,101,95,116,121,112,101,78,0, - 0,0,115,10,0,0,0,0,2,3,1,16,1,13,1,9, - 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,13,0,0,0, - 116,0,0,124,0,0,100,1,0,131,2,0,83,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, + 5,0,0,0,114,194,0,0,0,153,2,0,0,115,14,0, + 0,0,12,2,12,8,12,13,12,10,12,7,12,10,18,8, + 114,194,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,112,0,0,0,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, + 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, + 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, + 0,0,90,6,0,101,7,0,135,0,0,102,1,0,100,8, + 0,100,9,0,134,0,0,131,1,0,90,8,0,101,7,0, + 100,10,0,100,11,0,132,0,0,131,1,0,90,9,0,100, + 12,0,100,13,0,132,0,0,90,10,0,135,0,0,83,41, + 14,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,22,0,0,0, + 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, + 1,0,100,1,0,83,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,106,0,0,0,114,35,0, + 0,0,41,3,114,108,0,0,0,114,126,0,0,0,114,35, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,12,95,112,97,116,104,95,105,115,102,105,108,101, - 87,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,31,0,0,0,124,0,0,115,18,0, - 116,0,0,106,1,0,131,0,0,125,0,0,116,2,0,124, - 0,0,100,1,0,131,2,0,83,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,3,0,0,0,218,6,103,101,116,99,119,100,114, - 43,0,0,0,41,1,114,35,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,11,95,112,97,116, - 104,95,105,115,100,105,114,92,0,0,0,115,6,0,0,0, - 0,2,6,1,12,1,114,46,0,0,0,105,182,1,0,0, - 99,3,0,0,0,0,0,0,0,6,0,0,0,17,0,0, - 0,67,0,0,0,115,193,0,0,0,100,1,0,106,0,0, - 124,0,0,116,1,0,124,0,0,131,1,0,131,2,0,125, - 3,0,116,2,0,106,3,0,124,3,0,116,2,0,106,4, - 0,116,2,0,106,5,0,66,116,2,0,106,6,0,66,124, - 2,0,100,2,0,64,131,3,0,125,4,0,121,61,0,116, - 7,0,106,8,0,124,4,0,100,3,0,131,2,0,143,20, - 0,125,5,0,124,5,0,106,9,0,124,1,0,131,1,0, - 1,87,100,4,0,81,82,88,116,2,0,106,10,0,124,3, - 0,124,0,0,131,2,0,1,87,110,59,0,4,116,11,0, - 107,10,0,114,188,0,1,1,1,121,17,0,116,2,0,106, - 12,0,124,3,0,131,1,0,1,87,110,18,0,4,116,11, - 0,107,10,0,114,180,0,1,1,1,89,110,1,0,88,130, - 0,0,89,110,1,0,88,100,4,0,83,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,3,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,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,13,95,119,114,105,116,101,95,97,116, - 111,109,105,99,99,0,0,0,115,26,0,0,0,0,5,24, - 1,9,1,33,1,3,3,21,1,20,1,20,1,13,1,3, - 1,17,1,13,1,5,1,114,55,0,0,0,105,2,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,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,87,1,0,0,124,1,0,100,1,0,107, - 9,0,114,76,0,116,0,0,106,1,0,100,2,0,116,2, - 0,131,2,0,1,124,2,0,100,1,0,107,9,0,114,58, - 0,100,3,0,125,3,0,116,3,0,124,3,0,131,1,0, - 130,1,0,124,1,0,114,70,0,100,4,0,110,3,0,100, - 5,0,125,2,0,116,4,0,124,0,0,131,1,0,92,2, - 0,125,4,0,125,5,0,124,5,0,106,5,0,100,6,0, - 131,1,0,92,3,0,125,6,0,125,7,0,125,8,0,116, - 6,0,106,7,0,106,8,0,125,9,0,124,9,0,100,1, - 0,107,8,0,114,154,0,116,9,0,100,7,0,131,1,0, - 130,1,0,100,4,0,106,10,0,124,6,0,114,172,0,124, - 6,0,110,3,0,124,8,0,124,7,0,124,9,0,103,3, - 0,131,1,0,125,10,0,124,2,0,100,1,0,107,8,0, - 114,241,0,116,6,0,106,11,0,106,12,0,100,8,0,107, - 2,0,114,229,0,100,4,0,125,2,0,110,12,0,116,6, - 0,106,11,0,106,12,0,125,2,0,116,13,0,124,2,0, - 131,1,0,125,2,0,124,2,0,100,4,0,107,3,0,114, - 63,1,124,2,0,106,14,0,131,0,0,115,42,1,116,15, - 0,100,9,0,106,16,0,124,2,0,131,1,0,131,1,0, - 130,1,0,100,10,0,106,16,0,124,10,0,116,17,0,124, - 2,0,131,3,0,125,10,0,116,18,0,124,4,0,116,19, - 0,124,10,0,116,20,0,100,8,0,25,23,131,3,0,83, - 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,21,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, - 38,0,0,0,114,32,0,0,0,114,7,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,47, - 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,57,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,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,17,99,97,99,104,101,95,102,114,111,109,95,115,111, - 117,114,99,101,241,0,0,0,115,46,0,0,0,0,18,12, - 1,9,1,7,1,12,1,6,1,12,1,18,1,18,1,24, - 1,12,1,12,1,12,1,36,1,12,1,18,1,9,2,12, - 1,12,1,12,1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0, - 106,2,0,100,1,0,107,8,0,114,30,0,116,3,0,100, - 2,0,131,1,0,130,1,0,116,4,0,124,0,0,131,1, - 0,92,2,0,125,1,0,125,2,0,116,4,0,124,1,0, - 131,1,0,92,2,0,125,1,0,125,3,0,124,3,0,116, - 5,0,107,3,0,114,102,0,116,6,0,100,3,0,106,7, - 0,116,5,0,124,0,0,131,2,0,131,1,0,130,1,0, - 124,2,0,106,8,0,100,4,0,131,1,0,125,4,0,124, - 4,0,100,11,0,107,7,0,114,153,0,116,6,0,100,7, - 0,106,7,0,124,2,0,131,1,0,131,1,0,130,1,0, - 110,125,0,124,4,0,100,6,0,107,2,0,114,22,1,124, - 2,0,106,9,0,100,4,0,100,5,0,131,2,0,100,12, - 0,25,125,5,0,124,5,0,106,10,0,116,11,0,131,1, - 0,115,223,0,116,6,0,100,8,0,106,7,0,116,11,0, - 131,1,0,131,1,0,130,1,0,124,5,0,116,12,0,116, - 11,0,131,1,0,100,1,0,133,2,0,25,125,6,0,124, - 6,0,106,13,0,131,0,0,115,22,1,116,6,0,100,9, - 0,106,7,0,124,5,0,131,1,0,131,1,0,130,1,0, - 124,2,0,106,14,0,100,4,0,131,1,0,100,10,0,25, - 125,7,0,116,15,0,124,1,0,124,7,0,116,16,0,100, - 10,0,25,23,131,2,0,83,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,58,0,0,0, - 114,56,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,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,59, - 0,0,0,62,2,0,0,0,114,56,0,0,0,114,80,0, - 0,0,233,254,255,255,255,41,17,114,7,0,0,0,114,64, - 0,0,0,114,65,0,0,0,114,66,0,0,0,114,38,0, - 0,0,114,73,0,0,0,114,71,0,0,0,114,47,0,0, - 0,218,5,99,111,117,110,116,114,34,0,0,0,114,9,0, - 0,0,114,72,0,0,0,114,31,0,0,0,114,70,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,76,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,57,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,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,17,115,111,117,114,99,101,95,102,114,111,109,95, - 99,97,99,104,101,29,1,0,0,115,44,0,0,0,0,9, - 18,1,12,1,18,1,18,1,12,1,9,1,15,1,15,1, - 12,1,9,1,15,1,12,1,22,1,15,1,9,1,12,1, - 22,1,12,1,9,1,12,1,19,1,114,85,0,0,0,99, - 1,0,0,0,0,0,0,0,5,0,0,0,12,0,0,0, - 67,0,0,0,115,164,0,0,0,116,0,0,124,0,0,131, - 1,0,100,1,0,107,2,0,114,22,0,100,2,0,83,124, - 0,0,106,1,0,100,3,0,131,1,0,92,3,0,125,1, - 0,125,2,0,125,3,0,124,1,0,12,115,81,0,124,3, - 0,106,2,0,131,0,0,100,7,0,100,8,0,133,2,0, - 25,100,6,0,107,3,0,114,85,0,124,0,0,83,121,16, - 0,116,3,0,124,0,0,131,1,0,125,4,0,87,110,40, - 0,4,116,4,0,116,5,0,102,2,0,107,10,0,114,143, - 0,1,1,1,124,0,0,100,2,0,100,9,0,133,2,0, - 25,125,4,0,89,110,1,0,88,116,6,0,124,4,0,131, - 1,0,114,160,0,124,4,0,83,124,0,0,83,41,10,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,59,0, - 0,0,78,114,58,0,0,0,114,80,0,0,0,114,29,0, - 0,0,90,2,112,121,233,253,255,255,255,233,255,255,255,255, - 114,87,0,0,0,41,7,114,31,0,0,0,114,32,0,0, - 0,218,5,108,111,119,101,114,114,85,0,0,0,114,66,0, - 0,0,114,71,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,78,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, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,15, - 95,103,101,116,95,115,111,117,114,99,101,102,105,108,101,62, - 1,0,0,115,20,0,0,0,0,7,18,1,4,1,24,1, - 35,1,4,1,3,1,16,1,19,1,21,1,114,91,0,0, - 0,99,1,0,0,0,0,0,0,0,1,0,0,0,11,0, - 0,0,67,0,0,0,115,92,0,0,0,124,0,0,106,0, - 0,116,1,0,116,2,0,131,1,0,131,1,0,114,59,0, - 121,14,0,116,3,0,124,0,0,131,1,0,83,87,113,88, - 0,4,116,4,0,107,10,0,114,55,0,1,1,1,89,113, - 88,0,88,110,29,0,124,0,0,106,0,0,116,1,0,116, - 5,0,131,1,0,131,1,0,114,84,0,124,0,0,83,100, - 0,0,83,100,0,0,83,41,1,78,41,6,218,8,101,110, - 100,115,119,105,116,104,218,5,116,117,112,108,101,114,84,0, - 0,0,114,79,0,0,0,114,66,0,0,0,114,74,0,0, - 0,41,1,218,8,102,105,108,101,110,97,109,101,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,11,95,103, - 101,116,95,99,97,99,104,101,100,81,1,0,0,115,16,0, - 0,0,0,1,21,1,3,1,14,1,13,1,8,1,21,1, - 4,2,114,95,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,60,0,0, - 0,121,19,0,116,0,0,124,0,0,131,1,0,106,1,0, - 125,1,0,87,110,24,0,4,116,2,0,107,10,0,114,45, - 0,1,1,1,100,1,0,125,1,0,89,110,1,0,88,124, - 1,0,100,2,0,79,125,1,0,124,1,0,83,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,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,10,95,99,97,108, - 99,95,109,111,100,101,93,1,0,0,115,12,0,0,0,0, - 2,3,1,19,1,13,1,11,3,10,1,114,97,0,0,0, - 218,9,118,101,114,98,111,115,105,116,121,114,29,0,0,0, - 99,1,0,0,0,1,0,0,0,3,0,0,0,4,0,0, - 0,71,0,0,0,115,75,0,0,0,116,0,0,106,1,0, - 106,2,0,124,1,0,107,5,0,114,71,0,124,0,0,106, - 3,0,100,6,0,131,1,0,115,43,0,100,3,0,124,0, - 0,23,125,0,0,116,4,0,124,0,0,106,5,0,124,2, - 0,140,0,0,100,4,0,116,0,0,106,6,0,131,1,1, - 1,100,5,0,83,41,7,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,250,1,35,250,7,105,109,112,111,114, - 116,32,122,2,35,32,114,54,0,0,0,78,41,2,114,99, - 0,0,0,114,100,0,0,0,41,7,114,7,0,0,0,114, - 67,0,0,0,218,7,118,101,114,98,111,115,101,114,9,0, - 0,0,218,5,112,114,105,110,116,114,47,0,0,0,218,6, - 115,116,100,101,114,114,41,3,114,75,0,0,0,114,98,0, - 0,0,218,4,97,114,103,115,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,16,95,118,101,114,98,111,115, - 101,95,109,101,115,115,97,103,101,105,1,0,0,115,8,0, - 0,0,0,2,18,1,15,1,10,1,114,105,0,0,0,99, - 1,0,0,0,0,0,0,0,3,0,0,0,11,0,0,0, - 3,0,0,0,115,84,0,0,0,100,1,0,135,0,0,102, - 1,0,100,2,0,100,3,0,134,1,0,125,1,0,121,13, - 0,116,0,0,106,1,0,125,2,0,87,110,30,0,4,116, - 2,0,107,10,0,114,66,0,1,1,1,100,4,0,100,5, - 0,132,0,0,125,2,0,89,110,1,0,88,124,2,0,124, - 1,0,136,0,0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31, - 0,0,0,115,80,0,0,0,124,1,0,100,0,0,107,8, - 0,114,24,0,124,0,0,106,0,0,125,1,0,110,37,0, - 124,0,0,106,0,0,124,1,0,107,3,0,114,61,0,116, - 1,0,100,1,0,124,1,0,22,100,2,0,124,1,0,131, - 1,1,130,1,0,136,0,0,124,0,0,124,1,0,124,2, - 0,124,3,0,142,2,0,83,41,3,78,122,23,108,111,97, - 100,101,114,32,99,97,110,110,111,116,32,104,97,110,100,108, - 101,32,37,115,218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0, - 90,6,107,119,97,114,103,115,41,1,218,6,109,101,116,104, - 111,100,114,4,0,0,0,114,5,0,0,0,218,19,95,99, - 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, - 114,121,1,0,0,115,10,0,0,0,0,1,12,1,12,1, - 15,1,22,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,92,0,0,0,120,66,0,100,1,0,100,2, - 0,100,3,0,100,4,0,103,4,0,68,93,46,0,125,2, - 0,116,0,0,124,1,0,124,2,0,131,2,0,114,19,0, - 116,1,0,124,0,0,124,2,0,116,2,0,124,1,0,124, - 2,0,131,2,0,131,3,0,1,113,19,0,87,124,0,0, - 106,3,0,106,4,0,124,1,0,106,3,0,131,1,0,1, - 100,0,0,83,41,5,78,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,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,114, - 52,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,5,95,119,114,97,112,131,1,0,0,115,8, - 0,0,0,0,1,25,1,15,1,29,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,3,218,10,95,98,111,111,116, - 115,116,114,97,112,114,120,0,0,0,218,9,78,97,109,101, - 69,114,114,111,114,41,3,114,109,0,0,0,114,110,0,0, - 0,114,120,0,0,0,114,4,0,0,0,41,1,114,109,0, - 0,0,114,5,0,0,0,218,11,95,99,104,101,99,107,95, - 110,97,109,101,113,1,0,0,115,14,0,0,0,0,8,21, - 6,3,1,13,1,13,2,17,5,13,1,114,123,0,0,0, - 99,2,0,0,0,0,0,0,0,5,0,0,0,4,0,0, - 0,67,0,0,0,115,84,0,0,0,124,0,0,106,0,0, - 124,1,0,131,1,0,92,2,0,125,2,0,125,3,0,124, - 2,0,100,1,0,107,8,0,114,80,0,116,1,0,124,3, - 0,131,1,0,114,80,0,100,2,0,125,4,0,116,2,0, - 106,3,0,124,4,0,106,4,0,124,3,0,100,3,0,25, - 131,1,0,116,5,0,131,2,0,1,124,2,0,83,41,4, - 122,155,84,114,121,32,116,111,32,102,105,110,100,32,97,32, - 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,32, - 98,121,32,100,101,108,101,103,97,116,105,110,103,32,116,111, - 10,32,32,32,32,115,101,108,102,46,102,105,110,100,95,108, - 111,97,100,101,114,40,41,46,10,10,32,32,32,32,84,104, - 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,32,105,110,32,102,97,118,111,114, - 32,111,102,32,102,105,110,100,101,114,46,102,105,110,100,95, - 115,112,101,99,40,41,46,10,10,32,32,32,32,78,122,44, - 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, - 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, - 105,110,103,32,95,95,105,110,105,116,95,95,114,59,0,0, - 0,41,6,218,11,102,105,110,100,95,108,111,97,100,101,114, - 114,31,0,0,0,114,60,0,0,0,114,61,0,0,0,114, - 47,0,0,0,218,13,73,109,112,111,114,116,87,97,114,110, - 105,110,103,41,5,114,108,0,0,0,218,8,102,117,108,108, - 110,97,109,101,218,6,108,111,97,100,101,114,218,8,112,111, - 114,116,105,111,110,115,218,3,109,115,103,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,17,95,102,105,110, - 100,95,109,111,100,117,108,101,95,115,104,105,109,140,1,0, - 0,115,10,0,0,0,0,10,21,1,24,1,6,1,29,1, - 114,130,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,87,0,0,0,116, - 0,0,124,1,0,124,0,0,131,2,0,125,2,0,124,1, - 0,116,1,0,106,2,0,107,6,0,114,70,0,116,1,0, - 106,2,0,124,1,0,25,125,3,0,116,3,0,106,4,0, - 124,2,0,124,3,0,131,2,0,1,116,1,0,106,2,0, - 124,1,0,25,83,116,3,0,106,5,0,124,2,0,131,1, - 0,83,100,1,0,83,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,6,218,16,115, - 112,101,99,95,102,114,111,109,95,108,111,97,100,101,114,114, - 7,0,0,0,218,7,109,111,100,117,108,101,115,114,121,0, - 0,0,90,5,95,101,120,101,99,90,5,95,108,111,97,100, - 41,4,114,108,0,0,0,114,126,0,0,0,218,4,115,112, - 101,99,218,6,109,111,100,117,108,101,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,17,95,108,111,97,100, - 95,109,111,100,117,108,101,95,115,104,105,109,158,1,0,0, - 115,12,0,0,0,0,6,15,1,15,1,13,1,16,1,11, - 2,114,135,0,0,0,99,4,0,0,0,0,0,0,0,11, - 0,0,0,19,0,0,0,67,0,0,0,115,228,1,0,0, - 105,0,0,125,4,0,124,2,0,100,1,0,107,9,0,114, - 31,0,124,2,0,124,4,0,100,2,0,60,110,6,0,100, - 3,0,125,2,0,124,3,0,100,1,0,107,9,0,114,59, - 0,124,3,0,124,4,0,100,4,0,60,124,0,0,100,1, - 0,100,5,0,133,2,0,25,125,5,0,124,0,0,100,5, - 0,100,6,0,133,2,0,25,125,6,0,124,0,0,100,6, - 0,100,7,0,133,2,0,25,125,7,0,124,5,0,116,0, - 0,107,3,0,114,165,0,100,8,0,106,1,0,124,2,0, - 124,5,0,131,2,0,125,8,0,116,2,0,124,8,0,131, - 1,0,1,116,3,0,124,8,0,124,4,0,141,1,0,130, - 1,0,110,113,0,116,4,0,124,6,0,131,1,0,100,5, - 0,107,3,0,114,223,0,100,9,0,106,1,0,124,2,0, - 131,1,0,125,8,0,116,2,0,124,8,0,131,1,0,1, - 116,5,0,124,8,0,131,1,0,130,1,0,110,55,0,116, - 4,0,124,7,0,131,1,0,100,5,0,107,3,0,114,22, - 1,100,10,0,106,1,0,124,2,0,131,1,0,125,8,0, - 116,2,0,124,8,0,131,1,0,1,116,5,0,124,8,0, - 131,1,0,130,1,0,124,1,0,100,1,0,107,9,0,114, - 214,1,121,20,0,116,6,0,124,1,0,100,11,0,25,131, - 1,0,125,9,0,87,110,18,0,4,116,7,0,107,10,0, - 114,74,1,1,1,1,89,110,59,0,88,116,8,0,124,6, - 0,131,1,0,124,9,0,107,3,0,114,133,1,100,12,0, - 106,1,0,124,2,0,131,1,0,125,8,0,116,2,0,124, - 8,0,131,1,0,1,116,3,0,124,8,0,124,4,0,141, - 1,0,130,1,0,121,18,0,124,1,0,100,13,0,25,100, - 14,0,64,125,10,0,87,110,18,0,4,116,7,0,107,10, - 0,114,171,1,1,1,1,89,110,43,0,88,116,8,0,124, - 7,0,131,1,0,124,10,0,107,3,0,114,214,1,116,3, - 0,100,12,0,106,1,0,124,2,0,131,1,0,124,4,0, - 141,1,0,130,1,0,124,0,0,100,7,0,100,1,0,133, - 2,0,25,83,41,15,97,122,1,0,0,86,97,108,105,100, - 97,116,101,32,116,104,101,32,104,101,97,100,101,114,32,111, - 102,32,116,104,101,32,112,97,115,115,101,100,45,105,110,32, - 98,121,116,101,99,111,100,101,32,97,103,97,105,110,115,116, - 32,115,111,117,114,99,101,95,115,116,97,116,115,32,40,105, - 102,10,32,32,32,32,103,105,118,101,110,41,32,97,110,100, - 32,114,101,116,117,114,110,105,110,103,32,116,104,101,32,98, - 121,116,101,99,111,100,101,32,116,104,97,116,32,99,97,110, - 32,98,101,32,99,111,109,112,105,108,101,100,32,98,121,32, - 99,111,109,112,105,108,101,40,41,46,10,10,32,32,32,32, - 65,108,108,32,111,116,104,101,114,32,97,114,103,117,109,101, - 110,116,115,32,97,114,101,32,117,115,101,100,32,116,111,32, - 101,110,104,97,110,99,101,32,101,114,114,111,114,32,114,101, - 112,111,114,116,105,110,103,46,10,10,32,32,32,32,73,109, - 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, - 115,101,100,32,119,104,101,110,32,116,104,101,32,109,97,103, - 105,99,32,110,117,109,98,101,114,32,105,115,32,105,110,99, - 111,114,114,101,99,116,32,111,114,32,116,104,101,32,98,121, - 116,101,99,111,100,101,32,105,115,10,32,32,32,32,102,111, - 117,110,100,32,116,111,32,98,101,32,115,116,97,108,101,46, - 32,69,79,70,69,114,114,111,114,32,105,115,32,114,97,105, - 115,101,100,32,119,104,101,110,32,116,104,101,32,100,97,116, - 97,32,105,115,32,102,111,117,110,100,32,116,111,32,98,101, - 10,32,32,32,32,116,114,117,110,99,97,116,101,100,46,10, - 10,32,32,32,32,78,114,106,0,0,0,122,10,60,98,121, - 116,101,99,111,100,101,62,114,35,0,0,0,114,12,0,0, - 0,233,8,0,0,0,233,12,0,0,0,122,30,98,97,100, - 32,109,97,103,105,99,32,110,117,109,98,101,114,32,105,110, - 32,123,33,114,125,58,32,123,33,114,125,122,43,114,101,97, - 99,104,101,100,32,69,79,70,32,119,104,105,108,101,32,114, - 101,97,100,105,110,103,32,116,105,109,101,115,116,97,109,112, - 32,105,110,32,123,33,114,125,122,48,114,101,97,99,104,101, - 100,32,69,79,70,32,119,104,105,108,101,32,114,101,97,100, - 105,110,103,32,115,105,122,101,32,111,102,32,115,111,117,114, - 99,101,32,105,110,32,123,33,114,125,218,5,109,116,105,109, - 101,122,26,98,121,116,101,99,111,100,101,32,105,115,32,115, - 116,97,108,101,32,102,111,114,32,123,33,114,125,218,4,115, - 105,122,101,108,3,0,0,0,255,127,255,127,3,0,41,9, - 218,12,77,65,71,73,67,95,78,85,77,66,69,82,114,47, - 0,0,0,114,105,0,0,0,114,107,0,0,0,114,31,0, - 0,0,218,8,69,79,70,69,114,114,111,114,114,14,0,0, - 0,218,8,75,101,121,69,114,114,111,114,114,19,0,0,0, - 41,11,114,53,0,0,0,218,12,115,111,117,114,99,101,95, - 115,116,97,116,115,114,106,0,0,0,114,35,0,0,0,90, - 11,101,120,99,95,100,101,116,97,105,108,115,90,5,109,97, - 103,105,99,90,13,114,97,119,95,116,105,109,101,115,116,97, - 109,112,90,8,114,97,119,95,115,105,122,101,114,75,0,0, - 0,218,12,115,111,117,114,99,101,95,109,116,105,109,101,218, - 11,115,111,117,114,99,101,95,115,105,122,101,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,25,95,118,97, - 108,105,100,97,116,101,95,98,121,116,101,99,111,100,101,95, - 104,101,97,100,101,114,173,1,0,0,115,76,0,0,0,0, - 11,6,1,12,1,13,3,6,1,12,1,10,1,16,1,16, - 1,16,1,12,1,18,1,10,1,18,1,18,1,15,1,10, - 1,15,1,18,1,15,1,10,1,12,1,12,1,3,1,20, - 1,13,1,5,2,18,1,15,1,10,1,15,1,3,1,18, - 1,13,1,5,2,18,1,15,1,9,1,114,146,0,0,0, - 99,4,0,0,0,0,0,0,0,5,0,0,0,6,0,0, - 0,67,0,0,0,115,112,0,0,0,116,0,0,106,1,0, - 124,0,0,131,1,0,125,4,0,116,2,0,124,4,0,116, - 3,0,131,2,0,114,75,0,116,4,0,100,1,0,124,2, - 0,131,2,0,1,124,3,0,100,2,0,107,9,0,114,71, - 0,116,5,0,106,6,0,124,4,0,124,3,0,131,2,0, - 1,124,4,0,83,116,7,0,100,3,0,106,8,0,124,2, - 0,131,1,0,100,4,0,124,1,0,100,5,0,124,2,0, - 131,1,2,130,1,0,100,2,0,83,41,6,122,60,67,111, - 109,112,105,108,101,32,98,121,116,101,99,111,100,101,32,97, - 115,32,114,101,116,117,114,110,101,100,32,98,121,32,95,118, - 97,108,105,100,97,116,101,95,98,121,116,101,99,111,100,101, - 95,104,101,97,100,101,114,40,41,46,122,21,99,111,100,101, - 32,111,98,106,101,99,116,32,102,114,111,109,32,123,33,114, - 125,78,122,23,78,111,110,45,99,111,100,101,32,111,98,106, - 101,99,116,32,105,110,32,123,33,114,125,114,106,0,0,0, - 114,35,0,0,0,41,9,218,7,109,97,114,115,104,97,108, - 90,5,108,111,97,100,115,218,10,105,115,105,110,115,116,97, - 110,99,101,218,10,95,99,111,100,101,95,116,121,112,101,114, - 105,0,0,0,218,4,95,105,109,112,90,16,95,102,105,120, - 95,99,111,95,102,105,108,101,110,97,109,101,114,107,0,0, - 0,114,47,0,0,0,41,5,114,53,0,0,0,114,106,0, - 0,0,114,89,0,0,0,114,90,0,0,0,218,4,99,111, - 100,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,17,95,99,111,109,112,105,108,101,95,98,121,116,101, - 99,111,100,101,228,1,0,0,115,16,0,0,0,0,2,15, - 1,15,1,13,1,12,1,16,1,4,2,18,1,114,152,0, - 0,0,114,59,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,76,0,0, - 0,116,0,0,116,1,0,131,1,0,125,3,0,124,3,0, - 106,2,0,116,3,0,124,1,0,131,1,0,131,1,0,1, - 124,3,0,106,2,0,116,3,0,124,2,0,131,1,0,131, - 1,0,1,124,3,0,106,2,0,116,4,0,106,5,0,124, - 0,0,131,1,0,131,1,0,1,124,3,0,83,41,1,122, - 80,67,111,109,112,105,108,101,32,97,32,99,111,100,101,32, - 111,98,106,101,99,116,32,105,110,116,111,32,98,121,116,101, - 99,111,100,101,32,102,111,114,32,119,114,105,116,105,110,103, - 32,111,117,116,32,116,111,32,97,32,98,121,116,101,45,99, - 111,109,112,105,108,101,100,10,32,32,32,32,102,105,108,101, - 46,41,6,218,9,98,121,116,101,97,114,114,97,121,114,140, - 0,0,0,218,6,101,120,116,101,110,100,114,17,0,0,0, - 114,147,0,0,0,90,5,100,117,109,112,115,41,4,114,151, - 0,0,0,114,138,0,0,0,114,145,0,0,0,114,53,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,17,95,99,111,100,101,95,116,111,95,98,121,116,101, - 99,111,100,101,240,1,0,0,115,10,0,0,0,0,3,12, - 1,19,1,19,1,22,1,114,155,0,0,0,99,1,0,0, - 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, - 0,115,89,0,0,0,100,1,0,100,2,0,108,0,0,125, - 1,0,116,1,0,106,2,0,124,0,0,131,1,0,106,3, - 0,125,2,0,124,1,0,106,4,0,124,2,0,131,1,0, - 125,3,0,116,1,0,106,5,0,100,2,0,100,3,0,131, - 2,0,125,4,0,124,4,0,106,6,0,124,0,0,106,6, - 0,124,3,0,100,1,0,25,131,1,0,131,1,0,83,41, - 4,122,121,68,101,99,111,100,101,32,98,121,116,101,115,32, - 114,101,112,114,101,115,101,110,116,105,110,103,32,115,111,117, - 114,99,101,32,99,111,100,101,32,97,110,100,32,114,101,116, - 117,114,110,32,116,104,101,32,115,116,114,105,110,103,46,10, - 10,32,32,32,32,85,110,105,118,101,114,115,97,108,32,110, - 101,119,108,105,110,101,32,115,117,112,112,111,114,116,32,105, - 115,32,117,115,101,100,32,105,110,32,116,104,101,32,100,101, - 99,111,100,105,110,103,46,10,32,32,32,32,114,59,0,0, - 0,78,84,41,7,218,8,116,111,107,101,110,105,122,101,114, - 49,0,0,0,90,7,66,121,116,101,115,73,79,90,8,114, - 101,97,100,108,105,110,101,90,15,100,101,116,101,99,116,95, - 101,110,99,111,100,105,110,103,90,25,73,110,99,114,101,109, - 101,110,116,97,108,78,101,119,108,105,110,101,68,101,99,111, - 100,101,114,218,6,100,101,99,111,100,101,41,5,218,12,115, - 111,117,114,99,101,95,98,121,116,101,115,114,156,0,0,0, - 90,21,115,111,117,114,99,101,95,98,121,116,101,115,95,114, - 101,97,100,108,105,110,101,218,8,101,110,99,111,100,105,110, - 103,90,15,110,101,119,108,105,110,101,95,100,101,99,111,100, - 101,114,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,13,100,101,99,111,100,101,95,115,111,117,114,99,101, - 250,1,0,0,115,10,0,0,0,0,5,12,1,18,1,15, - 1,18,1,114,160,0,0,0,218,6,111,114,105,103,105,110, - 218,10,105,115,95,112,97,99,107,97,103,101,99,2,0,0, - 0,2,0,0,0,5,0,0,0,15,0,0,0,67,0,0, - 0,115,193,0,0,0,116,0,0,124,1,0,100,1,0,131, - 2,0,114,83,0,124,3,0,100,2,0,107,8,0,114,43, - 0,116,1,0,124,0,0,100,3,0,124,1,0,131,1,1, - 83,124,3,0,114,55,0,103,0,0,110,3,0,100,2,0, - 125,4,0,116,1,0,124,0,0,100,3,0,124,1,0,100, - 4,0,124,4,0,131,1,2,83,124,3,0,100,2,0,107, - 8,0,114,165,0,116,0,0,124,1,0,100,5,0,131,2, - 0,114,159,0,121,19,0,124,1,0,106,2,0,124,0,0, - 131,1,0,125,3,0,87,113,165,0,4,116,3,0,107,10, - 0,114,155,0,1,1,1,100,2,0,125,3,0,89,113,165, - 0,88,110,6,0,100,6,0,125,3,0,116,4,0,106,5, - 0,124,0,0,124,1,0,100,7,0,124,2,0,100,5,0, - 124,3,0,131,2,2,83,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, - 218,12,103,101,116,95,102,105,108,101,110,97,109,101,78,114, - 127,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, - 114,162,0,0,0,70,114,161,0,0,0,41,6,114,115,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,162,0,0,0, - 114,107,0,0,0,114,121,0,0,0,218,10,77,111,100,117, - 108,101,83,112,101,99,41,5,114,106,0,0,0,114,127,0, - 0,0,114,161,0,0,0,114,162,0,0,0,90,6,115,101, - 97,114,99,104,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,131,0,0,0,8,2,0,0,115,28,0,0, - 0,0,2,15,1,12,1,16,1,18,1,15,1,7,2,12, - 1,15,1,3,1,19,1,13,1,14,3,6,2,114,131,0, - 0,0,114,127,0,0,0,114,164,0,0,0,99,2,0,0, - 0,2,0,0,0,9,0,0,0,19,0,0,0,67,0,0, - 0,115,89,1,0,0,124,1,0,100,1,0,107,8,0,114, - 73,0,100,2,0,125,1,0,116,0,0,124,2,0,100,3, - 0,131,2,0,114,73,0,121,19,0,124,2,0,106,1,0, - 124,0,0,131,1,0,125,1,0,87,110,18,0,4,116,2, - 0,107,10,0,114,72,0,1,1,1,89,110,1,0,88,116, - 3,0,106,4,0,124,0,0,124,2,0,100,4,0,124,1, - 0,131,2,1,125,4,0,100,5,0,124,4,0,95,5,0, - 124,2,0,100,1,0,107,8,0,114,194,0,120,73,0,116, - 6,0,131,0,0,68,93,58,0,92,2,0,125,5,0,125, - 6,0,124,1,0,106,7,0,116,8,0,124,6,0,131,1, - 0,131,1,0,114,128,0,124,5,0,124,0,0,124,1,0, - 131,2,0,125,2,0,124,2,0,124,4,0,95,9,0,80, - 113,128,0,87,100,1,0,83,124,3,0,116,10,0,107,8, - 0,114,23,1,116,0,0,124,2,0,100,6,0,131,2,0, - 114,32,1,121,19,0,124,2,0,106,11,0,124,0,0,131, - 1,0,125,7,0,87,110,18,0,4,116,2,0,107,10,0, - 114,4,1,1,1,1,89,113,32,1,88,124,7,0,114,32, - 1,103,0,0,124,4,0,95,12,0,110,9,0,124,3,0, - 124,4,0,95,12,0,124,4,0,106,12,0,103,0,0,107, - 2,0,114,85,1,124,1,0,114,85,1,116,13,0,124,1, - 0,131,1,0,100,7,0,25,125,8,0,124,4,0,106,12, - 0,106,14,0,124,8,0,131,1,0,1,124,4,0,83,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,114, - 163,0,0,0,114,161,0,0,0,84,114,162,0,0,0,114, - 59,0,0,0,41,15,114,115,0,0,0,114,163,0,0,0, - 114,107,0,0,0,114,121,0,0,0,114,166,0,0,0,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,92,0,0,0, - 114,93,0,0,0,114,127,0,0,0,218,9,95,80,79,80, - 85,76,65,84,69,114,162,0,0,0,114,164,0,0,0,114, - 38,0,0,0,218,6,97,112,112,101,110,100,41,9,114,106, - 0,0,0,90,8,108,111,99,97,116,105,111,110,114,127,0, - 0,0,114,164,0,0,0,114,133,0,0,0,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,162,0,0,0,90,7,100,105,114,110,97, - 109,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,165,0,0,0,33,2,0,0,115,60,0,0,0,0, - 12,12,4,6,1,15,2,3,1,19,1,13,1,5,8,24, - 1,9,3,12,1,22,1,21,1,15,1,9,1,5,2,4, - 3,12,2,15,1,3,1,19,1,13,1,5,2,6,1,12, - 2,9,1,15,1,6,1,16,1,16,2,114,165,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0, - 0,64,0,0,0,115,121,0,0,0,101,0,0,90,1,0, - 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,90, - 4,0,100,3,0,90,5,0,100,4,0,90,6,0,101,7, - 0,100,5,0,100,6,0,132,0,0,131,1,0,90,8,0, - 101,7,0,100,7,0,100,8,0,132,0,0,131,1,0,90, - 9,0,101,7,0,100,9,0,100,9,0,100,10,0,100,11, - 0,132,2,0,131,1,0,90,10,0,101,7,0,100,9,0, - 100,12,0,100,13,0,132,1,0,131,1,0,90,11,0,100, - 9,0,83,41,14,218,21,87,105,110,100,111,119,115,82,101, - 103,105,115,116,114,121,70,105,110,100,101,114,122,62,77,101, - 116,97,32,112,97,116,104,32,102,105,110,100,101,114,32,102, - 111,114,32,109,111,100,117,108,101,115,32,100,101,99,108,97, - 114,101,100,32,105,110,32,116,104,101,32,87,105,110,100,111, - 119,115,32,114,101,103,105,115,116,114,121,46,122,59,83,111, - 102,116,119,97,114,101,92,80,121,116,104,111,110,92,80,121, - 116,104,111,110,67,111,114,101,92,123,115,121,115,95,118,101, - 114,115,105,111,110,125,92,77,111,100,117,108,101,115,92,123, - 102,117,108,108,110,97,109,101,125,122,65,83,111,102,116,119, - 97,114,101,92,80,121,116,104,111,110,92,80,121,116,104,111, - 110,67,111,114,101,92,123,115,121,115,95,118,101,114,115,105, - 111,110,125,92,77,111,100,117,108,101,115,92,123,102,117,108, - 108,110,97,109,101,125,92,68,101,98,117,103,70,99,2,0, - 0,0,0,0,0,0,2,0,0,0,11,0,0,0,67,0, - 0,0,115,67,0,0,0,121,23,0,116,0,0,106,1,0, - 116,0,0,106,2,0,124,1,0,131,2,0,83,87,110,37, - 0,4,116,3,0,107,10,0,114,62,0,1,1,1,116,0, - 0,106,1,0,116,0,0,106,4,0,124,1,0,131,2,0, - 83,89,110,1,0,88,100,0,0,83,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,218,3,107,101,121,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,14,95,111,112,101,110,95, - 114,101,103,105,115,116,114,121,111,2,0,0,115,8,0,0, - 0,0,2,3,1,23,1,13,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,16,0,0,0, - 67,0,0,0,115,143,0,0,0,124,0,0,106,0,0,114, - 21,0,124,0,0,106,1,0,125,2,0,110,9,0,124,0, - 0,106,2,0,125,2,0,124,2,0,106,3,0,100,1,0, - 124,1,0,100,2,0,116,4,0,106,5,0,100,0,0,100, - 3,0,133,2,0,25,131,0,2,125,3,0,121,47,0,124, - 0,0,106,6,0,124,3,0,131,1,0,143,25,0,125,4, - 0,116,7,0,106,8,0,124,4,0,100,4,0,131,2,0, - 125,5,0,87,100,0,0,81,82,88,87,110,22,0,4,116, - 9,0,107,10,0,114,138,0,1,1,1,100,0,0,83,89, - 110,1,0,88,124,5,0,83,41,5,78,114,126,0,0,0, - 90,11,115,121,115,95,118,101,114,115,105,111,110,114,80,0, - 0,0,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,47,0,0,0,114,7,0, - 0,0,218,7,118,101,114,115,105,111,110,114,176,0,0,0, - 114,173,0,0,0,90,10,81,117,101,114,121,86,97,108,117, - 101,114,40,0,0,0,41,6,114,174,0,0,0,114,126,0, - 0,0,90,12,114,101,103,105,115,116,114,121,95,107,101,121, - 114,175,0,0,0,90,4,104,107,101,121,218,8,102,105,108, - 101,112,97,116,104,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,218,16,95,115,101,97,114,99,104,95,114,101, - 103,105,115,116,114,121,118,2,0,0,115,22,0,0,0,0, - 2,9,1,12,2,9,1,15,1,22,1,3,1,18,1,29, - 1,13,1,9,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,14,0,0,0,67, - 0,0,0,115,155,0,0,0,124,0,0,106,0,0,124,1, - 0,131,1,0,125,4,0,124,4,0,100,0,0,107,8,0, - 114,31,0,100,0,0,83,121,14,0,116,1,0,124,4,0, - 131,1,0,1,87,110,22,0,4,116,2,0,107,10,0,114, - 69,0,1,1,1,100,0,0,83,89,110,1,0,88,120,78, - 0,116,3,0,131,0,0,68,93,67,0,92,2,0,125,5, - 0,125,6,0,124,4,0,106,4,0,116,5,0,124,6,0, - 131,1,0,131,1,0,114,80,0,116,6,0,124,1,0,124, - 5,0,124,1,0,124,4,0,131,2,0,100,1,0,124,4, - 0,131,2,1,125,7,0,124,7,0,83,113,80,0,87,100, - 0,0,83,41,2,78,114,161,0,0,0,41,7,114,182,0, - 0,0,114,39,0,0,0,114,40,0,0,0,114,167,0,0, - 0,114,92,0,0,0,114,93,0,0,0,114,131,0,0,0, - 41,8,114,174,0,0,0,114,126,0,0,0,114,35,0,0, - 0,218,6,116,97,114,103,101,116,114,181,0,0,0,114,127, - 0,0,0,114,171,0,0,0,114,133,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,9,102,105, - 110,100,95,115,112,101,99,133,2,0,0,115,24,0,0,0, - 0,2,15,1,12,1,4,1,3,1,14,1,13,1,9,1, - 22,1,21,1,21,1,9,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,3,0,0,0,67,0,0,0,115,45, - 0,0,0,124,0,0,106,0,0,124,1,0,124,2,0,131, - 2,0,125,3,0,124,3,0,100,1,0,107,9,0,114,37, - 0,124,3,0,106,1,0,83,100,1,0,83,100,1,0,83, - 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, + 0,0,114,185,0,0,0,12,3,0,0,115,4,0,0,0, + 0,3,9,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,34, + 0,0,0,124,0,0,106,0,0,124,1,0,106,0,0,107, + 2,0,111,33,0,124,0,0,106,1,0,124,1,0,106,1, + 0,107,2,0,83,41,1,78,41,2,218,9,95,95,99,108, + 97,115,115,95,95,114,118,0,0,0,41,2,114,108,0,0, + 0,218,5,111,116,104,101,114,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,6,95,95,101,113,95,95,18, + 3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106, + 1,0,131,1,0,116,0,0,124,0,0,106,2,0,131,1, + 0,65,83,41,1,78,41,3,218,4,104,97,115,104,114,106, + 0,0,0,114,35,0,0,0,41,1,114,108,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,8, + 95,95,104,97,115,104,95,95,22,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,22,0, + 0,0,116,0,0,116,1,0,124,0,0,131,2,0,106,2, + 0,124,1,0,131,1,0,83,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, - 78,41,2,114,184,0,0,0,114,127,0,0,0,41,4,114, - 174,0,0,0,114,126,0,0,0,114,35,0,0,0,114,133, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,148, - 2,0,0,115,8,0,0,0,0,7,18,1,12,1,7,2, - 122,33,87,105,110,100,111,119,115,82,101,103,105,115,116,114, - 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, - 117,108,101,41,12,114,112,0,0,0,114,111,0,0,0,114, - 113,0,0,0,114,114,0,0,0,114,179,0,0,0,114,178, - 0,0,0,114,177,0,0,0,218,11,99,108,97,115,115,109, - 101,116,104,111,100,114,176,0,0,0,114,182,0,0,0,114, - 184,0,0,0,114,185,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,172,0, - 0,0,99,2,0,0,115,20,0,0,0,12,2,6,3,6, - 3,6,2,6,2,18,7,18,15,3,1,21,14,3,1,114, - 172,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,64,0,0,0,101,0, - 0,90,1,0,100,0,0,90,2,0,100,1,0,90,3,0, - 100,2,0,100,3,0,132,0,0,90,4,0,100,4,0,100, - 5,0,132,0,0,90,5,0,100,6,0,100,7,0,132,0, - 0,90,6,0,101,7,0,90,8,0,100,8,0,83,41,9, - 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, + 41,3,218,5,115,117,112,101,114,114,210,0,0,0,114,193, + 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,41, + 1,114,211,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,193,0,0,0,25,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,7,0, + 0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,157,0,0,0,37,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,42,0,0,0,116,0,0,106, + 1,0,124,1,0,100,1,0,131,2,0,143,17,0,125,2, + 0,124,2,0,106,2,0,131,0,0,83,87,100,2,0,81, + 82,88,100,2,0,83,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,49,0,0,0,114,50,0,0, + 0,90,4,114,101,97,100,41,3,114,108,0,0,0,114,35, + 0,0,0,114,54,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,200,0,0,0,42,3,0,0, + 115,4,0,0,0,0,2,21,1,122,19,70,105,108,101,76, + 111,97,100,101,114,46,103,101,116,95,100,97,116,97,41,11, + 114,112,0,0,0,114,111,0,0,0,114,113,0,0,0,114, + 114,0,0,0,114,185,0,0,0,114,213,0,0,0,114,215, + 0,0,0,114,123,0,0,0,114,193,0,0,0,114,157,0, + 0,0,114,200,0,0,0,114,4,0,0,0,114,4,0,0, + 0,41,1,114,211,0,0,0,114,5,0,0,0,114,210,0, + 0,0,7,3,0,0,115,14,0,0,0,12,3,6,2,12, + 6,12,4,12,3,24,12,18,5,114,210,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,64,0,0,0,101,0,0,90,1,0,100,0, + 0,90,2,0,100,1,0,90,3,0,100,2,0,100,3,0, + 132,0,0,90,4,0,100,4,0,100,5,0,132,0,0,90, + 5,0,100,6,0,100,7,0,100,8,0,100,9,0,132,0, + 1,90,6,0,100,10,0,83,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,5,0,0,0,67,0,0, + 0,115,34,0,0,0,116,0,0,124,1,0,131,1,0,125, + 2,0,124,2,0,106,1,0,100,1,0,124,2,0,106,2, + 0,100,2,0,105,2,0,83,41,3,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,114,133,0, + 0,0,114,134,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,108,0,0,0,114,35,0,0,0,114,208,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,197,0,0,0,52,3,0,0,115,4,0,0,0,0, + 2,12,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,34,0,0,0,116,0,0,124,1,0, + 131,1,0,125,4,0,124,0,0,106,1,0,124,2,0,124, + 3,0,100,1,0,124,4,0,131,2,1,83,41,2,78,218, + 5,95,109,111,100,101,41,2,114,97,0,0,0,114,198,0, + 0,0,41,5,114,108,0,0,0,114,90,0,0,0,114,89, + 0,0,0,114,53,0,0,0,114,42,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,199,0,0, + 0,57,3,0,0,115,4,0,0,0,0,2,12,1,122,32, + 83,111,117,114,99,101,70,105,108,101,76,111,97,100,101,114, + 46,95,99,97,99,104,101,95,98,121,116,101,99,111,100,101, + 114,220,0,0,0,105,182,1,0,0,99,3,0,0,0,1, + 0,0,0,9,0,0,0,17,0,0,0,67,0,0,0,115, + 53,1,0,0,116,0,0,124,1,0,131,1,0,92,2,0, + 125,4,0,125,5,0,103,0,0,125,6,0,120,54,0,124, + 4,0,114,80,0,116,1,0,124,4,0,131,1,0,12,114, + 80,0,116,0,0,124,4,0,131,1,0,92,2,0,125,4, + 0,125,7,0,124,6,0,106,2,0,124,7,0,131,1,0, + 1,113,27,0,87,120,132,0,116,3,0,124,6,0,131,1, + 0,68,93,118,0,125,7,0,116,4,0,124,4,0,124,7, + 0,131,2,0,125,4,0,121,17,0,116,5,0,106,6,0, + 124,4,0,131,1,0,1,87,113,94,0,4,116,7,0,107, + 10,0,114,155,0,1,1,1,119,94,0,89,113,94,0,4, + 116,8,0,107,10,0,114,211,0,1,125,8,0,1,122,25, + 0,116,9,0,100,1,0,124,4,0,124,8,0,131,3,0, + 1,100,2,0,83,87,89,100,2,0,100,2,0,125,8,0, + 126,8,0,88,113,94,0,88,113,94,0,87,121,33,0,116, + 10,0,124,1,0,124,2,0,124,3,0,131,3,0,1,116, + 9,0,100,3,0,124,1,0,131,2,0,1,87,110,53,0, + 4,116,8,0,107,10,0,114,48,1,1,125,8,0,1,122, + 21,0,116,9,0,100,1,0,124,1,0,124,8,0,131,3, + 0,1,87,89,100,2,0,100,2,0,125,8,0,126,8,0, + 88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0,0, + 114,163,0,0,0,114,33,0,0,0,114,28,0,0,0,114, + 3,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,105,0,0,0,114,55,0,0,0,41,9,114,108,0, + 0,0,114,35,0,0,0,114,53,0,0,0,114,220,0,0, + 0,218,6,112,97,114,101,110,116,114,94,0,0,0,114,27, + 0,0,0,114,23,0,0,0,114,201,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, + 0,62,3,0,0,115,38,0,0,0,0,2,18,1,6,2, + 22,1,18,1,17,2,19,1,15,1,3,1,17,1,13,2, + 7,1,18,3,16,1,27,1,3,1,16,1,17,1,18,2, + 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,112, + 0,0,0,114,111,0,0,0,114,113,0,0,0,114,114,0, + 0,0,114,197,0,0,0,114,199,0,0,0,114,198,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,114,218,0,0,0,48,3,0,0,115,8, + 0,0,0,12,2,6,2,12,5,12,5,114,218,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,46,0,0,0,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,100, + 3,0,132,0,0,90,4,0,100,4,0,100,5,0,132,0, + 0,90,5,0,100,6,0,83,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,6,0,0,0, + 67,0,0,0,115,76,0,0,0,124,0,0,106,0,0,124, + 1,0,131,1,0,125,2,0,124,0,0,106,1,0,124,2, + 0,131,1,0,125,3,0,116,2,0,124,3,0,100,1,0, + 124,1,0,100,2,0,124,2,0,131,1,2,125,4,0,116, + 3,0,124,4,0,100,1,0,124,1,0,100,3,0,124,2, + 0,131,1,2,83,41,4,78,114,106,0,0,0,114,35,0, + 0,0,114,89,0,0,0,41,4,114,157,0,0,0,114,200, + 0,0,0,114,141,0,0,0,114,147,0,0,0,41,5,114, + 108,0,0,0,114,126,0,0,0,114,35,0,0,0,114,53, + 0,0,0,114,209,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,187,0,0,0,95,3,0,0, + 115,8,0,0,0,0,1,15,1,15,1,24,1,122,29,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,3,0,0,0,67,0,0,0,115,88,0,0,0,116,0, - 0,124,0,0,106,1,0,124,1,0,131,1,0,131,1,0, - 100,1,0,25,125,2,0,124,2,0,106,2,0,100,2,0, - 100,1,0,131,2,0,100,3,0,25,125,3,0,124,1,0, - 106,3,0,100,2,0,131,1,0,100,4,0,25,125,4,0, - 124,3,0,100,5,0,107,2,0,111,87,0,124,4,0,100, - 5,0,107,3,0,83,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,58,0,0, - 0,114,59,0,0,0,114,56,0,0,0,218,8,95,95,105, - 110,105,116,95,95,41,4,114,38,0,0,0,114,163,0,0, - 0,114,34,0,0,0,114,32,0,0,0,41,5,114,108,0, - 0,0,114,126,0,0,0,114,94,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,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,162,0,0,0,167,2,0,0,115,8, - 0,0,0,0,3,25,1,22,1,19,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0,114,133, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,13,99,114,101,97,116,101,95,109,111,100,117,108, - 101,175,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,4,0,0,0,67,0,0,0,115,80,0,0, - 0,124,0,0,106,0,0,124,1,0,106,1,0,131,1,0, - 125,2,0,124,2,0,100,1,0,107,8,0,114,54,0,116, - 2,0,100,2,0,106,3,0,124,1,0,106,1,0,131,1, - 0,131,1,0,130,1,0,116,4,0,106,5,0,116,6,0, - 124,2,0,124,1,0,106,7,0,131,3,0,1,100,1,0, - 83,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,112,0,0,0, - 114,107,0,0,0,114,47,0,0,0,114,121,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,118,0,0,0,41,3,114,108,0,0,0,114,134,0,0, - 0,114,151,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,11,101,120,101,99,95,109,111,100,117, - 108,101,178,2,0,0,115,10,0,0,0,0,2,18,1,12, - 1,9,1,15,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, - 78,41,9,114,112,0,0,0,114,111,0,0,0,114,113,0, - 0,0,114,114,0,0,0,114,162,0,0,0,114,189,0,0, - 0,114,193,0,0,0,114,135,0,0,0,218,11,108,111,97, - 100,95,109,111,100,117,108,101,114,4,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,187,0,0, - 0,162,2,0,0,115,10,0,0,0,12,3,6,2,12,8, - 12,3,12,8,114,187,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,106, - 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, - 1,0,100,2,0,132,0,0,90,3,0,100,3,0,100,4, - 0,132,0,0,90,4,0,100,5,0,100,6,0,132,0,0, - 90,5,0,100,7,0,100,8,0,132,0,0,90,6,0,100, - 9,0,100,10,0,132,0,0,90,7,0,100,11,0,100,18, - 0,100,13,0,100,14,0,132,0,1,90,8,0,100,15,0, - 100,16,0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0, - 83,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,73,79,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,218,7,73,79,69,114, - 114,111,114,41,2,114,108,0,0,0,114,35,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,10, - 112,97,116,104,95,109,116,105,109,101,191,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,3,0,0,0,67, - 0,0,0,115,19,0,0,0,124,0,0,106,0,0,124,1, - 0,131,1,0,100,1,0,105,1,0,83,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,73,79,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,138,0,0, - 0,41,1,114,197,0,0,0,41,2,114,108,0,0,0,114, - 35,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,10,112,97,116,104,95,115,116,97,116,115,199, - 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, - 3,0,0,0,67,0,0,0,115,16,0,0,0,124,0,0, - 106,0,0,124,2,0,124,3,0,131,2,0,83,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,108,0,0,0,114,90,0,0,0,90,10,99, - 97,99,104,101,95,112,97,116,104,114,53,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,15,95, - 99,97,99,104,101,95,98,121,116,101,99,111,100,101,212,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,0,83,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,4,0,0,0,41,3,114,108,0,0,0,114,35,0,0, - 0,114,53,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,199,0,0,0,222,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,16,0,0,0,67,0,0,0,115, - 105,0,0,0,124,0,0,106,0,0,124,1,0,131,1,0, - 125,2,0,121,19,0,124,0,0,106,1,0,124,2,0,131, - 1,0,125,3,0,87,110,58,0,4,116,2,0,107,10,0, - 114,94,0,1,125,4,0,1,122,26,0,116,3,0,100,1, - 0,100,2,0,124,1,0,131,1,1,124,4,0,130,2,0, - 87,89,100,3,0,100,3,0,125,4,0,126,4,0,88,110, - 1,0,88,116,4,0,124,3,0,131,1,0,83,41,4,122, - 52,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,111,102,32,73,110,115,112, - 101,99,116,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,46,122,39,115,111,117,114,99,101,32,110,111, - 116,32,97,118,97,105,108,97,98,108,101,32,116,104,114,111, - 117,103,104,32,103,101,116,95,100,97,116,97,40,41,114,106, - 0,0,0,78,41,5,114,163,0,0,0,218,8,103,101,116, - 95,100,97,116,97,114,40,0,0,0,114,107,0,0,0,114, - 160,0,0,0,41,5,114,108,0,0,0,114,126,0,0,0, - 114,35,0,0,0,114,158,0,0,0,218,3,101,120,99,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,10, - 103,101,116,95,115,111,117,114,99,101,229,2,0,0,115,14, - 0,0,0,0,2,15,1,3,1,19,1,18,1,9,1,31, - 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,218,9,95,111,112,116, - 105,109,105,122,101,114,29,0,0,0,99,3,0,0,0,1, - 0,0,0,4,0,0,0,9,0,0,0,67,0,0,0,115, - 34,0,0,0,116,0,0,106,1,0,116,2,0,124,1,0, - 124,2,0,100,1,0,100,2,0,100,3,0,100,4,0,124, - 3,0,131,4,2,83,41,5,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,192,0,0, - 0,218,12,100,111,110,116,95,105,110,104,101,114,105,116,84, - 114,68,0,0,0,41,3,114,121,0,0,0,114,191,0,0, - 0,218,7,99,111,109,112,105,108,101,41,4,114,108,0,0, - 0,114,53,0,0,0,114,35,0,0,0,114,204,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 14,115,111,117,114,99,101,95,116,111,95,99,111,100,101,239, - 2,0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174, - 1,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, - 2,0,100,1,0,125,3,0,121,16,0,116,1,0,124,2, - 0,131,1,0,125,4,0,87,110,24,0,4,116,2,0,107, - 10,0,114,63,0,1,1,1,100,1,0,125,4,0,89,110, - 202,0,88,121,19,0,124,0,0,106,3,0,124,2,0,131, - 1,0,125,5,0,87,110,18,0,4,116,4,0,107,10,0, - 114,103,0,1,1,1,89,110,162,0,88,116,5,0,124,5, - 0,100,2,0,25,131,1,0,125,3,0,121,19,0,124,0, - 0,106,6,0,124,4,0,131,1,0,125,6,0,87,110,18, - 0,4,116,7,0,107,10,0,114,159,0,1,1,1,89,110, - 106,0,88,121,34,0,116,8,0,124,6,0,100,3,0,124, - 5,0,100,4,0,124,1,0,100,5,0,124,4,0,131,1, - 3,125,7,0,87,110,24,0,4,116,9,0,116,10,0,102, - 2,0,107,10,0,114,220,0,1,1,1,89,110,45,0,88, - 116,11,0,100,6,0,124,4,0,124,2,0,131,3,0,1, - 116,12,0,124,7,0,100,4,0,124,1,0,100,7,0,124, - 4,0,100,8,0,124,2,0,131,1,3,83,124,0,0,106, - 6,0,124,2,0,131,1,0,125,8,0,124,0,0,106,13, - 0,124,8,0,124,2,0,131,2,0,125,9,0,116,11,0, - 100,9,0,124,2,0,131,2,0,1,116,14,0,106,15,0, - 12,114,170,1,124,4,0,100,1,0,107,9,0,114,170,1, - 124,3,0,100,1,0,107,9,0,114,170,1,116,16,0,124, - 9,0,124,3,0,116,17,0,124,8,0,131,1,0,131,3, - 0,125,6,0,121,36,0,124,0,0,106,18,0,124,2,0, - 124,4,0,124,6,0,131,3,0,1,116,11,0,100,10,0, - 124,4,0,131,2,0,1,87,110,18,0,4,116,2,0,107, - 10,0,114,169,1,1,1,1,89,110,1,0,88,124,9,0, - 83,41,11,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,114,138,0,0,0,114,143,0,0,0,114,106, - 0,0,0,114,35,0,0,0,122,13,123,125,32,109,97,116, - 99,104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,163,0,0,0,114,79,0,0,0,114,66, - 0,0,0,114,198,0,0,0,114,196,0,0,0,114,14,0, - 0,0,114,201,0,0,0,114,40,0,0,0,114,146,0,0, - 0,114,107,0,0,0,114,141,0,0,0,114,105,0,0,0, - 114,152,0,0,0,114,207,0,0,0,114,7,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,155,0,0,0,114,31,0,0,0,114,200, - 0,0,0,41,10,114,108,0,0,0,114,126,0,0,0,114, - 90,0,0,0,114,144,0,0,0,114,89,0,0,0,218,2, - 115,116,114,53,0,0,0,218,10,98,121,116,101,115,95,100, - 97,116,97,114,158,0,0,0,90,11,99,111,100,101,95,111, - 98,106,101,99,116,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,190,0,0,0,247,2,0,0,115,78,0, - 0,0,0,7,15,1,6,1,3,1,16,1,13,1,11,2, - 3,1,19,1,13,1,5,2,16,1,3,1,19,1,13,1, - 5,2,3,1,9,1,12,1,13,1,19,1,5,2,9,1, - 7,1,15,1,6,1,7,1,15,1,18,1,13,1,22,1, - 12,1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114, - 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,197, - 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, - 0,0,114,203,0,0,0,114,207,0,0,0,114,190,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,195,0,0,0,189,2,0,0,115,14, - 0,0,0,12,2,12,8,12,13,12,10,12,7,12,10,18, - 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,112,0,0,0, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, - 132,0,0,90,6,0,101,7,0,135,0,0,102,1,0,100, - 8,0,100,9,0,134,0,0,131,1,0,90,8,0,101,7, - 0,100,10,0,100,11,0,132,0,0,131,1,0,90,9,0, - 100,12,0,100,13,0,132,0,0,90,10,0,135,0,0,83, - 41,14,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, + 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,0,83,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,4,0,0,0,41,2,114,108,0, + 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,202,0,0,0,101,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,112,0,0,0,114, + 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,187, + 0,0,0,114,202,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,223,0,0, + 0,91,3,0,0,115,6,0,0,0,12,2,6,2,12,6, + 114,223,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,130,0,0,0,101, + 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, + 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, + 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, + 0,0,90,6,0,101,7,0,100,8,0,100,9,0,132,0, + 0,131,1,0,90,8,0,100,10,0,100,11,0,132,0,0, + 90,9,0,100,12,0,100,13,0,132,0,0,90,10,0,100, + 14,0,100,15,0,132,0,0,90,11,0,101,7,0,100,16, + 0,100,17,0,132,0,0,131,1,0,90,12,0,100,18,0, + 83,41,19,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,22,0,0, 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, - 95,1,0,100,1,0,83,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,106,0,0,0,114,35, - 0,0,0,41,3,114,108,0,0,0,114,126,0,0,0,114, - 35,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,188,0,0,0,48,3,0,0,115,4,0,0, - 0,0,3,9,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, - 34,0,0,0,124,0,0,106,0,0,124,1,0,106,0,0, - 107,2,0,111,33,0,124,0,0,106,1,0,124,1,0,106, - 1,0,107,2,0,83,41,1,78,41,2,218,9,95,95,99, - 108,97,115,115,95,95,114,118,0,0,0,41,2,114,108,0, - 0,0,218,5,111,116,104,101,114,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,6,95,95,101,113,95,95, - 54,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0, - 106,1,0,131,1,0,116,0,0,124,0,0,106,2,0,131, - 1,0,65,83,41,1,78,41,3,218,4,104,97,115,104,114, - 106,0,0,0,114,35,0,0,0,41,1,114,108,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 8,95,95,104,97,115,104,95,95,58,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,22, - 0,0,0,116,0,0,116,1,0,124,0,0,131,2,0,106, - 2,0,124,1,0,131,1,0,83,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,211,0,0,0,114, - 194,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, - 41,1,114,212,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,194,0,0,0,61,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,7, - 0,0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,163,0,0,0,73, - 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,42,0,0,0,116,0,0, - 106,1,0,124,1,0,100,1,0,131,2,0,143,17,0,125, - 2,0,124,2,0,106,2,0,131,0,0,83,87,100,2,0, - 81,82,88,100,2,0,83,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,49,0,0,0,114,50,0, - 0,0,90,4,114,101,97,100,41,3,114,108,0,0,0,114, - 35,0,0,0,114,54,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,201,0,0,0,78,3,0, - 0,115,4,0,0,0,0,2,21,1,122,19,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41, - 11,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, - 114,114,0,0,0,114,188,0,0,0,114,214,0,0,0,114, - 216,0,0,0,114,123,0,0,0,114,194,0,0,0,114,163, - 0,0,0,114,201,0,0,0,114,4,0,0,0,114,4,0, - 0,0,41,1,114,212,0,0,0,114,5,0,0,0,114,211, - 0,0,0,43,3,0,0,115,14,0,0,0,12,3,6,2, - 12,6,12,4,12,3,24,12,18,5,114,211,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,64,0,0,0,101,0,0,90,1,0,100, + 95,1,0,100,0,0,83,41,1,78,41,2,114,106,0,0, + 0,114,35,0,0,0,41,3,114,108,0,0,0,114,106,0, + 0,0,114,35,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,185,0,0,0,118,3,0,0,115, + 4,0,0,0,0,1,9,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,34,0,0,0, + 124,0,0,106,0,0,124,1,0,106,0,0,107,2,0,111, + 33,0,124,0,0,106,1,0,124,1,0,106,1,0,107,2, + 0,83,41,1,78,41,2,114,211,0,0,0,114,118,0,0, + 0,41,2,114,108,0,0,0,114,212,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,213,0,0, + 0,122,3,0,0,115,4,0,0,0,0,1,18,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, + 26,0,0,0,116,0,0,124,0,0,106,1,0,131,1,0, + 116,0,0,124,0,0,106,2,0,131,1,0,65,83,41,1, + 78,41,3,114,214,0,0,0,114,106,0,0,0,114,35,0, + 0,0,41,1,114,108,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,215,0,0,0,126,3,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,4, + 0,0,0,11,0,0,0,67,0,0,0,115,184,0,0,0, + 116,0,0,106,1,0,124,1,0,131,1,0,143,32,0,1, + 116,0,0,106,2,0,116,3,0,106,4,0,124,1,0,124, + 0,0,106,5,0,131,3,0,125,2,0,87,100,1,0,81, + 82,88,116,6,0,100,2,0,124,0,0,106,5,0,131,2, + 0,1,124,0,0,106,7,0,124,1,0,131,1,0,125,3, + 0,124,3,0,114,128,0,116,8,0,124,2,0,100,3,0, + 131,2,0,12,114,128,0,116,9,0,124,0,0,106,5,0, + 131,1,0,100,4,0,25,103,1,0,124,2,0,95,10,0, + 124,0,0,124,2,0,95,11,0,124,2,0,106,12,0,124, + 2,0,95,13,0,124,3,0,115,180,0,124,2,0,106,13, + 0,106,14,0,100,5,0,131,1,0,100,4,0,25,124,2, + 0,95,13,0,124,2,0,83,41,6,122,25,76,111,97,100, + 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,46,78,122,33,101,120,116,101,110,115,105,111, + 110,32,109,111,100,117,108,101,32,108,111,97,100,101,100,32, + 102,114,111,109,32,123,33,114,125,218,8,95,95,112,97,116, + 104,95,95,114,59,0,0,0,114,58,0,0,0,41,15,114, + 121,0,0,0,90,13,95,77,97,110,97,103,101,82,101,108, + 111,97,100,114,188,0,0,0,114,145,0,0,0,90,12,108, + 111,97,100,95,100,121,110,97,109,105,99,114,35,0,0,0, + 114,105,0,0,0,114,159,0,0,0,114,115,0,0,0,114, + 38,0,0,0,114,225,0,0,0,218,10,95,95,108,111,97, + 100,101,114,95,95,114,112,0,0,0,218,11,95,95,112,97, + 99,107,97,103,101,95,95,114,32,0,0,0,41,4,114,108, + 0,0,0,114,126,0,0,0,114,190,0,0,0,114,159,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,193,0,0,0,129,3,0,0,115,24,0,0,0,0, + 5,16,1,12,1,22,1,16,1,15,1,22,1,25,1,9, + 1,12,1,6,1,25,1,122,31,69,120,116,101,110,115,105, + 111,110,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,4,0,0,0,3,0,0,0,115,48,0, + 0,0,116,0,0,124,0,0,106,1,0,131,1,0,100,1, + 0,25,137,0,0,116,2,0,135,0,0,102,1,0,100,2, + 0,100,3,0,134,0,0,116,3,0,68,131,1,0,131,1, + 0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0,136, + 0,0,100,0,0,124,1,0,23,107,2,0,86,1,113,3, + 0,100,1,0,83,41,2,114,185,0,0,0,78,114,4,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,4, + 0,0,0,114,5,0,0,0,250,9,60,103,101,110,101,120, + 112,114,62,150,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0, + 0,0,114,4,0,0,0,41,1,114,229,0,0,0,114,5, + 0,0,0,114,159,0,0,0,147,3,0,0,115,6,0,0, + 0,0,2,19,1,18,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,0,83,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,4,0,0,0,41,2, + 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,153,3, + 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,0,83,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, + 4,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 202,0,0,0,157,3,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,7,0,0,0,124,0,0,106,0,0,83, + 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,108,0,0,0,114,126,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,157,0,0,0,161,3,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,13,114,112,0,0,0,114,111,0,0,0,114, + 113,0,0,0,114,114,0,0,0,114,185,0,0,0,114,213, + 0,0,0,114,215,0,0,0,114,123,0,0,0,114,193,0, + 0,0,114,159,0,0,0,114,187,0,0,0,114,202,0,0, + 0,114,157,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,224,0,0,0,110, + 3,0,0,115,18,0,0,0,12,6,6,2,12,4,12,4, + 12,3,18,18,12,6,12,4,12,4,114,224,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,130,0,0,0,101,0,0,90,1,0,100, 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, 0,132,0,0,90,4,0,100,4,0,100,5,0,132,0,0, - 90,5,0,100,6,0,100,7,0,100,8,0,100,9,0,132, - 0,1,90,6,0,100,10,0,83,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,5,0,0,0,67,0, - 0,0,115,34,0,0,0,116,0,0,124,1,0,131,1,0, - 125,2,0,124,2,0,106,1,0,100,1,0,124,2,0,106, - 2,0,100,2,0,105,2,0,83,41,3,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,114,138, - 0,0,0,114,139,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,108,0,0,0,114,35,0,0,0,114,209, + 90,5,0,100,6,0,100,7,0,132,0,0,90,6,0,100, + 8,0,100,9,0,132,0,0,90,7,0,100,10,0,100,11, + 0,132,0,0,90,8,0,100,12,0,100,13,0,132,0,0, + 90,9,0,100,14,0,100,15,0,132,0,0,90,10,0,100, + 16,0,100,17,0,132,0,0,90,11,0,100,18,0,100,19, + 0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0, + 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, + 0,95,1,0,116,2,0,124,0,0,106,3,0,131,0,0, + 131,1,0,124,0,0,95,4,0,124,3,0,124,0,0,95, + 5,0,100,0,0,83,41,1,78,41,6,218,5,95,110,97, + 109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0, + 0,0,218,11,112,97,116,104,95,102,105,110,100,101,114,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,185, + 0,0,0,174,3,0,0,115,8,0,0,0,0,1,9,1, + 9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1,0, + 100,1,0,131,1,0,92,3,0,125,1,0,125,2,0,125, + 3,0,124,2,0,100,2,0,107,2,0,114,43,0,100,6, + 0,83,124,1,0,100,5,0,102,2,0,83,41,7,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,58, + 0,0,0,114,30,0,0,0,114,7,0,0,0,114,35,0, + 0,0,114,225,0,0,0,41,2,122,3,115,121,115,122,4, + 112,97,116,104,41,2,114,234,0,0,0,114,32,0,0,0, + 41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111, + 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, + 5,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,180,3,0, + 0,115,8,0,0,0,0,2,27,1,12,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,38,0,0,0, + 124,0,0,106,0,0,131,0,0,92,2,0,125,1,0,125, + 2,0,116,1,0,116,2,0,106,3,0,124,1,0,25,124, + 2,0,131,2,0,83,41,1,78,41,4,114,241,0,0,0, + 114,117,0,0,0,114,7,0,0,0,218,7,109,111,100,117, + 108,101,115,41,3,114,108,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,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,236,0, + 0,0,190,3,0,0,115,4,0,0,0,0,1,18,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,3,0,0, + 0,67,0,0,0,115,118,0,0,0,116,0,0,124,0,0, + 106,1,0,131,0,0,131,1,0,125,1,0,124,1,0,124, + 0,0,106,2,0,107,3,0,114,111,0,124,0,0,106,3, + 0,124,0,0,106,4,0,124,1,0,131,2,0,125,2,0, + 124,2,0,100,0,0,107,9,0,114,102,0,124,2,0,106, + 5,0,100,0,0,107,8,0,114,102,0,124,2,0,106,6, + 0,114,102,0,124,2,0,106,6,0,124,0,0,95,7,0, + 124,1,0,124,0,0,95,2,0,124,0,0,106,7,0,83, + 41,1,78,41,8,114,93,0,0,0,114,236,0,0,0,114, + 237,0,0,0,114,238,0,0,0,114,234,0,0,0,114,127, + 0,0,0,114,156,0,0,0,114,235,0,0,0,41,3,114, + 108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, + 104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108, + 97,116,101,194,3,0,0,115,16,0,0,0,0,2,18,1, + 15,1,21,3,27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16, + 0,0,0,116,0,0,124,0,0,106,1,0,131,0,0,131, + 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,243, + 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101, + 114,95,95,207,3,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,1,0,0,0,0,0,0,0, + 1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0, + 0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0, + 83,41,1,78,41,2,114,31,0,0,0,114,243,0,0,0, + 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,210, + 3,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,2, + 0,0,0,67,0,0,0,115,16,0,0,0,100,1,0,106, + 0,0,124,0,0,106,1,0,131,1,0,83,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,47,0,0,0,114,235,0,0, + 0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95, + 95,213,3,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,2,0,0,0,67,0,0,0,115,16,0,0,0,124, + 1,0,124,0,0,106,0,0,131,0,0,107,6,0,83,41, + 1,78,41,1,114,243,0,0,0,41,2,114,108,0,0,0, + 218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110, + 115,95,95,216,3,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,2,0,0,0,67,0,0,0, + 115,20,0,0,0,124,0,0,106,0,0,106,1,0,124,1, + 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,235, + 0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114, + 248,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,163,0,0,0,219,3,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,13,114,112,0, + 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, + 0,114,185,0,0,0,114,241,0,0,0,114,236,0,0,0, + 114,243,0,0,0,114,245,0,0,0,114,246,0,0,0,114, + 247,0,0,0,114,249,0,0,0,114,163,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,198,0,0,0,88,3,0,0,115,4,0,0,0, - 0,2,12,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,34,0,0,0,116,0,0,124,1, - 0,131,1,0,125,4,0,124,0,0,106,1,0,124,2,0, - 124,3,0,100,1,0,124,4,0,131,2,1,83,41,2,78, - 218,5,95,109,111,100,101,41,2,114,97,0,0,0,114,199, - 0,0,0,41,5,114,108,0,0,0,114,90,0,0,0,114, - 89,0,0,0,114,53,0,0,0,114,42,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,200,0, - 0,0,93,3,0,0,115,4,0,0,0,0,2,12,1,122, - 32,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, - 114,46,95,99,97,99,104,101,95,98,121,116,101,99,111,100, - 101,114,221,0,0,0,105,182,1,0,0,99,3,0,0,0, - 1,0,0,0,9,0,0,0,17,0,0,0,67,0,0,0, - 115,53,1,0,0,116,0,0,124,1,0,131,1,0,92,2, - 0,125,4,0,125,5,0,103,0,0,125,6,0,120,54,0, - 124,4,0,114,80,0,116,1,0,124,4,0,131,1,0,12, - 114,80,0,116,0,0,124,4,0,131,1,0,92,2,0,125, - 4,0,125,7,0,124,6,0,106,2,0,124,7,0,131,1, - 0,1,113,27,0,87,120,132,0,116,3,0,124,6,0,131, - 1,0,68,93,118,0,125,7,0,116,4,0,124,4,0,124, - 7,0,131,2,0,125,4,0,121,17,0,116,5,0,106,6, - 0,124,4,0,131,1,0,1,87,113,94,0,4,116,7,0, - 107,10,0,114,155,0,1,1,1,119,94,0,89,113,94,0, - 4,116,8,0,107,10,0,114,211,0,1,125,8,0,1,122, - 25,0,116,9,0,100,1,0,124,4,0,124,8,0,131,3, - 0,1,100,2,0,83,87,89,100,2,0,100,2,0,125,8, - 0,126,8,0,88,113,94,0,88,113,94,0,87,121,33,0, - 116,10,0,124,1,0,124,2,0,124,3,0,131,3,0,1, - 116,9,0,100,3,0,124,1,0,131,2,0,1,87,110,53, - 0,4,116,8,0,107,10,0,114,48,1,1,125,8,0,1, - 122,21,0,116,9,0,100,1,0,124,1,0,124,8,0,131, - 3,0,1,87,89,100,2,0,100,2,0,125,8,0,126,8, - 0,88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0, - 0,114,169,0,0,0,114,33,0,0,0,114,28,0,0,0, - 114,3,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,105,0,0,0,114,55,0,0,0,41,9,114,108, - 0,0,0,114,35,0,0,0,114,53,0,0,0,114,221,0, - 0,0,218,6,112,97,114,101,110,116,114,94,0,0,0,114, - 27,0,0,0,114,23,0,0,0,114,202,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,199,0, - 0,0,98,3,0,0,115,38,0,0,0,0,2,18,1,6, - 2,22,1,18,1,17,2,19,1,15,1,3,1,17,1,13, - 2,7,1,18,3,16,1,27,1,3,1,16,1,17,1,18, - 2,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, + 0,0,114,233,0,0,0,167,3,0,0,115,20,0,0,0, + 12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3, + 12,3,12,3,114,233,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,118, + 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, + 1,0,100,2,0,132,0,0,90,3,0,101,4,0,100,3, + 0,100,4,0,132,0,0,131,1,0,90,5,0,100,5,0, + 100,6,0,132,0,0,90,6,0,100,7,0,100,8,0,132, + 0,0,90,7,0,100,9,0,100,10,0,132,0,0,90,8, + 0,100,11,0,100,12,0,132,0,0,90,9,0,100,13,0, + 100,14,0,132,0,0,90,10,0,100,15,0,100,16,0,132, + 0,0,90,11,0,100,17,0,83,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,25,0,0,0,116,0,0,124,1,0,124,2,0, + 124,3,0,131,3,0,124,0,0,95,1,0,100,0,0,83, + 41,1,78,41,2,114,233,0,0,0,114,235,0,0,0,41, + 4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0, + 114,239,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,185,0,0,0,225,3,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,2,0,0,0, + 67,0,0,0,115,16,0,0,0,100,1,0,106,0,0,124, + 1,0,106,1,0,131,1,0,83,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,47,0, + 0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,228, + 3,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,0,83,41,2,78,84,114,4,0,0,0,41, + 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,237, + 3,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,0,83,41,2,78,114,30,0,0,0,114,4,0, + 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0, + 0,0,240,3,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, + 22,0,0,0,116,0,0,100,1,0,100,2,0,100,3,0, + 100,4,0,100,5,0,131,3,1,83,41,6,78,114,30,0, + 0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0, + 0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2, + 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,243,3, + 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, + 0,83,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,4,0,0,0,41,2,114,108,0,0,0,114,164,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,186,0,0,0,246,3,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,0,83,41,1,78, + 114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 114,191,0,0,0,249,3,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,3,0,0,0,67, + 0,0,0,115,32,0,0,0,116,0,0,100,1,0,124,0, + 0,106,1,0,131,2,0,1,116,2,0,106,3,0,124,0, + 0,124,1,0,131,2,0,83,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,105,0,0,0,114,235,0, + 0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108, + 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,193,0,0,0,252,3,0,0, + 115,4,0,0,0,0,7,16,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,112,0,0,0,114, + 111,0,0,0,114,113,0,0,0,114,185,0,0,0,114,183, + 0,0,0,114,251,0,0,0,114,159,0,0,0,114,202,0, + 0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0, + 0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,250,0,0,0,224, + 3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3, + 12,3,12,3,12,3,12,3,114,250,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0, + 0,0,115,160,0,0,0,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,101,4,0,100,2,0,100, + 3,0,132,0,0,131,1,0,90,5,0,101,4,0,100,4, + 0,100,5,0,132,0,0,131,1,0,90,6,0,101,4,0, + 100,6,0,100,7,0,132,0,0,131,1,0,90,7,0,101, + 4,0,100,8,0,100,9,0,132,0,0,131,1,0,90,8, + 0,101,4,0,100,10,0,100,11,0,100,12,0,132,1,0, + 131,1,0,90,9,0,101,4,0,100,10,0,100,10,0,100, + 13,0,100,14,0,132,2,0,131,1,0,90,10,0,101,4, + 0,100,10,0,100,15,0,100,16,0,132,1,0,131,1,0, + 90,11,0,100,10,0,83,41,17,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,55,0,0,0,120, + 48,0,116,0,0,106,1,0,106,2,0,131,0,0,68,93, + 31,0,125,1,0,116,3,0,124,1,0,100,1,0,131,2, + 0,114,16,0,124,1,0,106,4,0,131,0,0,1,113,16, + 0,87,100,2,0,83,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,7,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, + 115,0,0,0,114,253,0,0,0,41,2,114,170,0,0,0, + 218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,253,0,0,0,13,4,0,0, + 115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67,0,0,0,115,107, + 0,0,0,116,0,0,106,1,0,100,1,0,107,9,0,114, + 41,0,116,0,0,106,1,0,12,114,41,0,116,2,0,106, + 3,0,100,2,0,116,4,0,131,2,0,1,120,59,0,116, + 0,0,106,1,0,68,93,44,0,125,2,0,121,14,0,124, + 2,0,124,1,0,131,1,0,83,87,113,51,0,4,116,5, + 0,107,10,0,114,94,0,1,1,1,119,51,0,89,113,51, + 0,88,113,51,0,87,100,1,0,83,100,1,0,83,41,3, + 122,113,83,101,97,114,99,104,32,115,101,113,117,101,110,99, + 101,32,111,102,32,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,10,10,32,32,32,32,32,32,32,32,73,102,32, + 39,104,111,111,107,115,39,32,105,115,32,102,97,108,115,101, + 32,116,104,101,110,32,117,115,101,32,115,121,115,46,112,97, + 116,104,95,104,111,111,107,115,46,10,10,32,32,32,32,32, + 32,32,32,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, + 7,0,0,0,218,10,112,97,116,104,95,104,111,111,107,115, + 114,60,0,0,0,114,61,0,0,0,114,125,0,0,0,114, + 107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0, + 90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111, + 107,115,21,4,0,0,115,16,0,0,0,0,7,25,1,16, + 1,16,1,3,1,14,1,13,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, + 19,0,0,0,67,0,0,0,115,123,0,0,0,124,1,0, + 100,1,0,107,2,0,114,53,0,121,16,0,116,0,0,106, + 1,0,131,0,0,125,1,0,87,110,22,0,4,116,2,0, + 107,10,0,114,52,0,1,1,1,100,2,0,83,89,110,1, + 0,88,121,17,0,116,3,0,106,4,0,124,1,0,25,125, + 2,0,87,110,46,0,4,116,5,0,107,10,0,114,118,0, + 1,1,1,124,0,0,106,6,0,124,1,0,131,1,0,125, + 2,0,124,2,0,116,3,0,106,4,0,124,1,0,60,89, + 110,1,0,88,124,2,0,83,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,3,0,0,0,114,45,0,0,0, + 218,17,70,105,108,101,78,111,116,70,111,117,110,100,69,114, + 114,111,114,114,7,0,0,0,114,254,0,0,0,114,137,0, + 0,0,114,2,1,0,0,41,3,114,170,0,0,0,114,35, + 0,0,0,114,0,1,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,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,38,4,0, + 0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3, + 9,1,3,1,17,1,13,1,15,1,18,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,3,0,0,0,67,0, + 0,0,115,119,0,0,0,116,0,0,124,2,0,100,1,0, + 131,2,0,114,39,0,124,2,0,106,1,0,124,1,0,131, + 1,0,92,2,0,125,3,0,125,4,0,110,21,0,124,2, + 0,106,2,0,124,1,0,131,1,0,125,3,0,103,0,0, + 125,4,0,124,3,0,100,0,0,107,9,0,114,88,0,116, + 3,0,106,4,0,124,1,0,124,3,0,131,2,0,83,116, + 3,0,106,5,0,124,1,0,100,0,0,131,2,0,125,5, + 0,124,4,0,124,5,0,95,6,0,124,5,0,83,41,2, + 78,114,124,0,0,0,41,7,114,115,0,0,0,114,124,0, + 0,0,114,182,0,0,0,114,121,0,0,0,114,179,0,0, + 0,114,160,0,0,0,114,156,0,0,0,41,6,114,170,0, + 0,0,114,126,0,0,0,114,0,1,0,0,114,127,0,0, + 0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103, + 97,99,121,95,103,101,116,95,115,112,101,99,60,4,0,0, + 115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12, + 1,16,1,18,1,9,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,243,0,0,0,103, + 0,0,125,4,0,120,230,0,124,2,0,68,93,191,0,125, + 5,0,116,0,0,124,5,0,116,1,0,116,2,0,102,2, + 0,131,2,0,115,43,0,113,13,0,124,0,0,106,3,0, + 124,5,0,131,1,0,125,6,0,124,6,0,100,1,0,107, + 9,0,114,13,0,116,4,0,124,6,0,100,2,0,131,2, + 0,114,106,0,124,6,0,106,5,0,124,1,0,124,3,0, + 131,2,0,125,7,0,110,18,0,124,0,0,106,6,0,124, + 1,0,124,6,0,131,2,0,125,7,0,124,7,0,100,1, + 0,107,8,0,114,139,0,113,13,0,124,7,0,106,7,0, + 100,1,0,107,9,0,114,158,0,124,7,0,83,124,7,0, + 106,8,0,125,8,0,124,8,0,100,1,0,107,8,0,114, + 191,0,116,9,0,100,3,0,131,1,0,130,1,0,124,4, + 0,106,10,0,124,8,0,131,1,0,1,113,13,0,87,116, + 11,0,106,12,0,124,1,0,100,1,0,131,2,0,125,7, + 0,124,4,0,124,7,0,95,8,0,124,7,0,83,100,1, + 0,83,41,4,122,63,70,105,110,100,32,116,104,101,32,108, + 111,97,100,101,114,32,111,114,32,110,97,109,101,115,112,97, + 99,101,95,112,97,116,104,32,102,111,114,32,116,104,105,115, + 32,109,111,100,117,108,101,47,112,97,99,107,97,103,101,32, + 110,97,109,101,46,78,114,181,0,0,0,122,19,115,112,101, + 99,32,109,105,115,115,105,110,103,32,108,111,97,100,101,114, + 41,13,114,143,0,0,0,114,69,0,0,0,218,5,98,121, + 116,101,115,114,4,1,0,0,114,115,0,0,0,114,181,0, + 0,0,114,5,1,0,0,114,127,0,0,0,114,156,0,0, + 0,114,107,0,0,0,114,149,0,0,0,114,121,0,0,0, + 114,160,0,0,0,41,9,114,170,0,0,0,114,126,0,0, + 0,114,35,0,0,0,114,180,0,0,0,218,14,110,97,109, + 101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116, + 114,121,114,0,1,0,0,114,164,0,0,0,114,128,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,9,95,103,101,116,95,115,112,101,99,75,4,0,0,115, + 40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1, + 12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1, + 9,1,12,1,12,5,17,2,18,1,9,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,4, + 0,0,0,67,0,0,0,115,140,0,0,0,124,2,0,100, + 1,0,107,8,0,114,21,0,116,0,0,106,1,0,125,2, + 0,124,0,0,106,2,0,124,1,0,124,2,0,124,3,0, + 131,3,0,125,4,0,124,4,0,100,1,0,107,8,0,114, + 58,0,100,1,0,83,124,4,0,106,3,0,100,1,0,107, + 8,0,114,132,0,124,4,0,106,4,0,125,5,0,124,5, + 0,114,125,0,100,2,0,124,4,0,95,5,0,116,6,0, + 124,1,0,124,5,0,124,0,0,106,2,0,131,3,0,124, + 4,0,95,4,0,124,4,0,83,100,1,0,83,110,4,0, + 124,4,0,83,100,1,0,83,41,3,122,98,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,78,90, + 9,110,97,109,101,115,112,97,99,101,41,7,114,7,0,0, + 0,114,35,0,0,0,114,8,1,0,0,114,127,0,0,0, + 114,156,0,0,0,114,158,0,0,0,114,233,0,0,0,41, + 6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0, + 114,180,0,0,0,114,164,0,0,0,114,7,1,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181, + 0,0,0,107,4,0,0,115,26,0,0,0,0,4,12,1, + 9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1, + 24,1,4,2,7,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,41,0,0,0,124,0,0,106,0,0,124,1,0,124, + 2,0,131,2,0,125,3,0,124,3,0,100,1,0,107,8, + 0,114,34,0,100,1,0,83,124,3,0,106,1,0,83,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,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0, + 0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 182,0,0,0,129,4,0,0,115,8,0,0,0,0,8,18, + 1,12,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,12,114, 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, - 0,0,0,114,198,0,0,0,114,200,0,0,0,114,199,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,219,0,0,0,84,3,0,0,115, - 8,0,0,0,12,2,6,2,12,5,12,5,114,219,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,46,0,0,0,101,0,0,90,1, - 0,100,0,0,90,2,0,100,1,0,90,3,0,100,2,0, - 100,3,0,132,0,0,90,4,0,100,4,0,100,5,0,132, - 0,0,90,5,0,100,6,0,83,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,6,0,0, - 0,67,0,0,0,115,76,0,0,0,124,0,0,106,0,0, - 124,1,0,131,1,0,125,2,0,124,0,0,106,1,0,124, - 2,0,131,1,0,125,3,0,116,2,0,124,3,0,100,1, - 0,124,1,0,100,2,0,124,2,0,131,1,2,125,4,0, - 116,3,0,124,4,0,100,1,0,124,1,0,100,3,0,124, - 2,0,131,1,2,83,41,4,78,114,106,0,0,0,114,35, - 0,0,0,114,89,0,0,0,41,4,114,163,0,0,0,114, - 201,0,0,0,114,146,0,0,0,114,152,0,0,0,41,5, - 114,108,0,0,0,114,126,0,0,0,114,35,0,0,0,114, - 53,0,0,0,114,210,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,190,0,0,0,131,3,0, - 0,115,8,0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108, - 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,203,0,0,0,137,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,112,0,0,0, - 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, - 190,0,0,0,114,203,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,224,0, - 0,0,127,3,0,0,115,6,0,0,0,12,2,6,2,12, - 6,114,224,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,130,0,0,0, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, - 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, - 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, - 132,0,0,90,6,0,101,7,0,100,8,0,100,9,0,132, - 0,0,131,1,0,90,8,0,100,10,0,100,11,0,132,0, - 0,90,9,0,100,12,0,100,13,0,132,0,0,90,10,0, - 100,14,0,100,15,0,132,0,0,90,11,0,101,7,0,100, - 16,0,100,17,0,132,0,0,131,1,0,90,12,0,100,18, - 0,83,41,19,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,22,0, - 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, - 0,95,1,0,100,0,0,83,41,1,78,41,2,114,106,0, - 0,0,114,35,0,0,0,41,3,114,108,0,0,0,114,106, - 0,0,0,114,35,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,188,0,0,0,154,3,0,0, - 115,4,0,0,0,0,1,9,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,34,0,0, - 0,124,0,0,106,0,0,124,1,0,106,0,0,107,2,0, - 111,33,0,124,0,0,106,1,0,124,1,0,106,1,0,107, - 2,0,83,41,1,78,41,2,114,212,0,0,0,114,118,0, - 0,0,41,2,114,108,0,0,0,114,213,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,214,0, - 0,0,158,3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106,1,0,131,1, - 0,116,0,0,124,0,0,106,2,0,131,1,0,65,83,41, - 1,78,41,3,114,215,0,0,0,114,106,0,0,0,114,35, - 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,216,0,0,0,162,3, - 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, - 4,0,0,0,11,0,0,0,67,0,0,0,115,184,0,0, - 0,116,0,0,106,1,0,124,1,0,131,1,0,143,32,0, - 1,116,0,0,106,2,0,116,3,0,106,4,0,124,1,0, - 124,0,0,106,5,0,131,3,0,125,2,0,87,100,1,0, - 81,82,88,116,6,0,100,2,0,124,0,0,106,5,0,131, - 2,0,1,124,0,0,106,7,0,124,1,0,131,1,0,125, - 3,0,124,3,0,114,128,0,116,8,0,124,2,0,100,3, - 0,131,2,0,12,114,128,0,116,9,0,124,0,0,106,5, - 0,131,1,0,100,4,0,25,103,1,0,124,2,0,95,10, - 0,124,0,0,124,2,0,95,11,0,124,2,0,106,12,0, - 124,2,0,95,13,0,124,3,0,115,180,0,124,2,0,106, - 13,0,106,14,0,100,5,0,131,1,0,100,4,0,25,124, - 2,0,95,13,0,124,2,0,83,41,6,122,25,76,111,97, - 100,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,46,78,122,33,101,120,116,101,110,115,105, - 111,110,32,109,111,100,117,108,101,32,108,111,97,100,101,100, - 32,102,114,111,109,32,123,33,114,125,218,8,95,95,112,97, - 116,104,95,95,114,59,0,0,0,114,58,0,0,0,41,15, - 114,121,0,0,0,90,13,95,77,97,110,97,103,101,82,101, - 108,111,97,100,114,191,0,0,0,114,150,0,0,0,90,12, - 108,111,97,100,95,100,121,110,97,109,105,99,114,35,0,0, - 0,114,105,0,0,0,114,162,0,0,0,114,115,0,0,0, - 114,38,0,0,0,114,226,0,0,0,218,10,95,95,108,111, - 97,100,101,114,95,95,114,112,0,0,0,218,11,95,95,112, - 97,99,107,97,103,101,95,95,114,32,0,0,0,41,4,114, - 108,0,0,0,114,126,0,0,0,114,134,0,0,0,114,162, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,194,0,0,0,165,3,0,0,115,24,0,0,0, - 0,5,16,1,12,1,22,1,16,1,15,1,22,1,25,1, - 9,1,12,1,6,1,25,1,122,31,69,120,116,101,110,115, - 105,111,110,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,4,0,0,0,3,0,0,0,115,48, - 0,0,0,116,0,0,124,0,0,106,1,0,131,1,0,100, - 1,0,25,137,0,0,116,2,0,135,0,0,102,1,0,100, - 2,0,100,3,0,134,0,0,116,3,0,68,131,1,0,131, - 1,0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0, - 136,0,0,100,0,0,124,1,0,23,107,2,0,86,1,113, - 3,0,100,1,0,83,41,2,114,188,0,0,0,78,114,4, - 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, - 4,0,0,0,114,5,0,0,0,250,9,60,103,101,110,101, - 120,112,114,62,186,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126, - 0,0,0,114,4,0,0,0,41,1,114,230,0,0,0,114, - 5,0,0,0,114,162,0,0,0,183,3,0,0,115,6,0, - 0,0,0,2,19,1,18,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,0,83,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,4,0,0,0,41, - 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,190,0,0,0,189, - 3,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0,114,126,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,203,0,0,0,193,3,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,7,0,0,0,124,0,0,106,0,0, - 83,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,108,0,0,0,114,126,0, + 0,0,0,114,183,0,0,0,114,253,0,0,0,114,2,1, + 0,0,114,4,1,0,0,114,5,1,0,0,114,8,1,0, + 0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 252,0,0,0,9,4,0,0,115,22,0,0,0,12,2,6, + 2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21, + 21,3,1,114,252,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,133,0, + 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, + 0,90,3,0,100,2,0,100,3,0,132,0,0,90,4,0, + 100,4,0,100,5,0,132,0,0,90,5,0,101,6,0,90, + 7,0,100,6,0,100,7,0,132,0,0,90,8,0,100,8, + 0,100,9,0,132,0,0,90,9,0,100,10,0,100,11,0, + 100,12,0,132,1,0,90,10,0,100,13,0,100,14,0,132, + 0,0,90,11,0,101,12,0,100,15,0,100,16,0,132,0, + 0,131,1,0,90,13,0,100,17,0,100,18,0,132,0,0, + 90,14,0,100,10,0,83,41,19,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,122,0,0,0,103,0,0, + 125,3,0,120,52,0,124,2,0,68,93,44,0,92,2,0, + 137,0,0,125,4,0,124,3,0,106,0,0,135,0,0,102, + 1,0,100,1,0,100,2,0,134,0,0,124,4,0,68,131, + 1,0,131,1,0,1,113,13,0,87,124,3,0,124,0,0, + 95,1,0,124,1,0,112,79,0,100,3,0,124,0,0,95, + 2,0,100,6,0,124,0,0,95,3,0,116,4,0,131,0, + 0,124,0,0,95,5,0,116,4,0,131,0,0,124,0,0, + 95,6,0,100,5,0,83,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,27,0,0,0,124, + 0,0,93,17,0,125,1,0,124,1,0,136,0,0,102,2, + 0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0, + 0,0,41,2,114,22,0,0,0,114,228,0,0,0,41,1, + 114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 230,0,0,0,158,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0, + 0,78,114,87,0,0,0,41,7,114,149,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,108,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,166,0,0,0,114,4,0,0,0, + 41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0, + 0,152,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 36,1,9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0,0,95, + 0,0,100,2,0,83,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,29,0,0,0,78,114, + 87,0,0,0,41,1,114,11,1,0,0,41,1,114,108,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,163,0,0,0,197,3,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,13,114,112,0,0,0,114,111,0,0,0, - 114,113,0,0,0,114,114,0,0,0,114,188,0,0,0,114, - 214,0,0,0,114,216,0,0,0,114,123,0,0,0,114,194, - 0,0,0,114,162,0,0,0,114,190,0,0,0,114,203,0, - 0,0,114,163,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,225,0,0,0, - 146,3,0,0,115,18,0,0,0,12,6,6,2,12,4,12, - 4,12,3,18,18,12,6,12,4,12,4,114,225,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,130,0,0,0,101,0,0,90,1,0, - 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,100, - 3,0,132,0,0,90,4,0,100,4,0,100,5,0,132,0, - 0,90,5,0,100,6,0,100,7,0,132,0,0,90,6,0, - 100,8,0,100,9,0,132,0,0,90,7,0,100,10,0,100, - 11,0,132,0,0,90,8,0,100,12,0,100,13,0,132,0, - 0,90,9,0,100,14,0,100,15,0,132,0,0,90,10,0, - 100,16,0,100,17,0,132,0,0,90,11,0,100,18,0,100, - 19,0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52, - 0,0,0,124,1,0,124,0,0,95,0,0,124,2,0,124, - 0,0,95,1,0,116,2,0,124,0,0,106,3,0,131,0, - 0,131,1,0,124,0,0,95,4,0,124,3,0,124,0,0, - 95,5,0,100,0,0,83,41,1,78,41,6,218,5,95,110, - 97,109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35, - 0,0,0,218,11,112,97,116,104,95,102,105,110,100,101,114, + 0,114,253,0,0,0,166,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,59,0,0,0,124,0,0,106,0,0,124, + 1,0,131,1,0,125,2,0,124,2,0,100,1,0,107,8, + 0,114,37,0,100,1,0,103,0,0,102,2,0,83,124,2, + 0,106,1,0,124,2,0,106,2,0,112,55,0,103,0,0, + 102,2,0,83,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,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41, + 3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 188,0,0,0,210,3,0,0,115,8,0,0,0,0,1,9, - 1,9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1, - 0,100,1,0,131,1,0,92,3,0,125,1,0,125,2,0, - 125,3,0,124,2,0,100,2,0,107,2,0,114,43,0,100, - 6,0,83,124,1,0,100,5,0,102,2,0,83,41,7,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, - 58,0,0,0,114,30,0,0,0,114,7,0,0,0,114,35, - 0,0,0,114,226,0,0,0,41,2,122,3,115,121,115,122, - 4,112,97,116,104,41,2,114,235,0,0,0,114,32,0,0, - 0,41,4,114,108,0,0,0,114,223,0,0,0,218,3,100, - 111,116,90,2,109,101,114,4,0,0,0,114,4,0,0,0, - 114,5,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,216,3, - 0,0,115,8,0,0,0,0,2,27,1,12,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,38,0,0, - 0,124,0,0,106,0,0,131,0,0,92,2,0,125,1,0, - 125,2,0,116,1,0,116,2,0,106,3,0,124,1,0,25, - 124,2,0,131,2,0,83,41,1,78,41,4,114,242,0,0, - 0,114,117,0,0,0,114,7,0,0,0,114,132,0,0,0, - 41,3,114,108,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,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,237,0,0,0,226, - 3,0,0,115,4,0,0,0,0,1,18,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,3,0,0,0,67,0, - 0,0,115,118,0,0,0,116,0,0,124,0,0,106,1,0, - 131,0,0,131,1,0,125,1,0,124,1,0,124,0,0,106, - 2,0,107,3,0,114,111,0,124,0,0,106,3,0,124,0, - 0,106,4,0,124,1,0,131,2,0,125,2,0,124,2,0, - 100,0,0,107,9,0,114,102,0,124,2,0,106,5,0,100, - 0,0,107,8,0,114,102,0,124,2,0,106,6,0,114,102, - 0,124,2,0,106,6,0,124,0,0,95,7,0,124,1,0, - 124,0,0,95,2,0,124,0,0,106,7,0,83,41,1,78, - 41,8,114,93,0,0,0,114,237,0,0,0,114,238,0,0, - 0,114,239,0,0,0,114,235,0,0,0,114,127,0,0,0, - 114,164,0,0,0,114,236,0,0,0,41,3,114,108,0,0, - 0,90,11,112,97,114,101,110,116,95,112,97,116,104,114,133, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,12,95,114,101,99,97,108,99,117,108,97,116,101, - 230,3,0,0,115,16,0,0,0,0,2,18,1,15,1,21, - 3,27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16,0,0,0, - 116,0,0,124,0,0,106,1,0,131,0,0,131,1,0,83, - 41,1,78,41,2,218,4,105,116,101,114,114,243,0,0,0, - 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,8,95,95,105,116,101,114,95,95, - 243,3,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,1,0,0,0,0,0,0,0,1,0,0, - 0,2,0,0,0,67,0,0,0,115,16,0,0,0,116,0, - 0,124,0,0,106,1,0,131,0,0,131,1,0,83,41,1, - 78,41,2,114,31,0,0,0,114,243,0,0,0,41,1,114, + 124,0,0,0,172,4,0,0,115,8,0,0,0,0,7,15, + 1,12,1,10,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,7,0,0,0,67,0, + 0,0,115,40,0,0,0,124,1,0,124,2,0,124,3,0, + 131,2,0,125,6,0,116,0,0,124,2,0,124,3,0,100, + 1,0,124,6,0,100,2,0,124,4,0,131,2,2,83,41, + 3,78,114,127,0,0,0,114,156,0,0,0,41,1,114,167, + 0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114, + 126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, + 180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,8,1,0,0,184,4,0, + 0,115,6,0,0,0,0,1,15,1,18,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,234,1,0,0,100,1,0, + 125,3,0,124,1,0,106,0,0,100,2,0,131,1,0,100, + 3,0,25,125,4,0,121,34,0,116,1,0,124,0,0,106, + 2,0,112,49,0,116,3,0,106,4,0,131,0,0,131,1, + 0,106,5,0,125,5,0,87,110,24,0,4,116,6,0,107, + 10,0,114,85,0,1,1,1,100,10,0,125,5,0,89,110, + 1,0,88,124,5,0,124,0,0,106,7,0,107,3,0,114, + 120,0,124,0,0,106,8,0,131,0,0,1,124,5,0,124, + 0,0,95,7,0,116,9,0,131,0,0,114,153,0,124,0, + 0,106,10,0,125,6,0,124,4,0,106,11,0,131,0,0, + 125,7,0,110,15,0,124,0,0,106,12,0,125,6,0,124, + 4,0,125,7,0,124,7,0,124,6,0,107,6,0,114,45, + 1,116,13,0,124,0,0,106,2,0,124,4,0,131,2,0, + 125,8,0,120,100,0,124,0,0,106,14,0,68,93,77,0, + 92,2,0,125,9,0,125,10,0,100,5,0,124,9,0,23, + 125,11,0,116,13,0,124,8,0,124,11,0,131,2,0,125, + 12,0,116,15,0,124,12,0,131,1,0,114,208,0,124,0, + 0,106,16,0,124,10,0,124,1,0,124,12,0,124,8,0, + 103,1,0,124,2,0,131,5,0,83,113,208,0,87,116,17, + 0,124,8,0,131,1,0,125,3,0,120,123,0,124,0,0, + 106,14,0,68,93,112,0,92,2,0,125,9,0,125,10,0, + 116,13,0,124,0,0,106,2,0,124,4,0,124,9,0,23, + 131,2,0,125,12,0,116,18,0,100,6,0,106,19,0,124, + 12,0,131,1,0,100,7,0,100,3,0,131,1,1,1,124, + 7,0,124,9,0,23,124,6,0,107,6,0,114,55,1,116, + 15,0,124,12,0,131,1,0,114,55,1,124,0,0,106,16, + 0,124,10,0,124,1,0,124,12,0,100,8,0,124,2,0, + 131,5,0,83,113,55,1,87,124,3,0,114,230,1,116,18, + 0,100,9,0,106,19,0,124,8,0,131,1,0,131,1,0, + 1,116,20,0,106,21,0,124,1,0,100,8,0,131,2,0, + 125,13,0,124,8,0,103,1,0,124,13,0,95,22,0,124, + 13,0,83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0,114,56, + 0,0,0,114,29,0,0,0,114,185,0,0,0,122,9,116, + 114,121,105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0,41,23, + 114,32,0,0,0,114,39,0,0,0,114,35,0,0,0,114, + 3,0,0,0,114,45,0,0,0,114,219,0,0,0,114,40, + 0,0,0,114,11,1,0,0,218,11,95,102,105,108,108,95, + 99,97,99,104,101,114,6,0,0,0,114,14,1,0,0,114, + 88,0,0,0,114,13,1,0,0,114,28,0,0,0,114,10, + 1,0,0,114,44,0,0,0,114,8,1,0,0,114,46,0, + 0,0,114,105,0,0,0,114,47,0,0,0,114,121,0,0, + 0,114,160,0,0,0,114,156,0,0,0,41,14,114,108,0, + 0,0,114,126,0,0,0,114,180,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,133,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,228,0,0, + 0,114,165,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,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,181,0,0,0,189,4,0,0,115,68,0, + 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1, + 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2, + 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2, + 22,1,22,1,25,1,16,1,12,1,29,1,6,1,19,1, + 18,1,12,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,11,1,0,0,124,0,0,106,0,0,125,1,0,121, + 31,0,116,1,0,106,2,0,124,1,0,112,33,0,116,1, + 0,106,3,0,131,0,0,131,1,0,125,2,0,87,110,33, + 0,4,116,4,0,116,5,0,116,6,0,102,3,0,107,10, + 0,114,75,0,1,1,1,103,0,0,125,2,0,89,110,1, + 0,88,116,7,0,106,8,0,106,9,0,100,1,0,131,1, + 0,115,112,0,116,10,0,124,2,0,131,1,0,124,0,0, + 95,11,0,110,111,0,116,10,0,131,0,0,125,3,0,120, + 90,0,124,2,0,68,93,82,0,125,4,0,124,4,0,106, + 12,0,100,2,0,131,1,0,92,3,0,125,5,0,125,6, + 0,125,7,0,124,6,0,114,191,0,100,3,0,106,13,0, + 124,5,0,124,7,0,106,14,0,131,0,0,131,2,0,125, + 8,0,110,6,0,124,5,0,125,8,0,124,3,0,106,15, + 0,124,8,0,131,1,0,1,113,128,0,87,124,3,0,124, + 0,0,95,11,0,116,7,0,106,8,0,106,9,0,116,16, + 0,131,1,0,114,7,1,100,4,0,100,5,0,132,0,0, + 124,2,0,68,131,1,0,124,0,0,95,17,0,100,6,0, + 83,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,58, + 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, + 28,0,0,0,104,0,0,124,0,0,93,18,0,125,1,0, + 124,1,0,106,0,0,131,0,0,146,2,0,113,6,0,83, + 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22, + 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112, + 62,7,5,0,0,115,2,0,0,0,9,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, + 3,0,0,0,90,7,108,105,115,116,100,105,114,114,45,0, + 0,0,114,3,1,0,0,218,15,80,101,114,109,105,115,115, + 105,111,110,69,114,114,111,114,218,18,78,111,116,65,68,105, + 114,101,99,116,111,114,121,69,114,114,111,114,114,7,0,0, + 0,114,8,0,0,0,114,9,0,0,0,114,12,1,0,0, + 114,13,1,0,0,114,83,0,0,0,114,47,0,0,0,114, + 88,0,0,0,218,3,97,100,100,114,10,0,0,0,114,14, + 1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,240,0,0,0,114, + 228,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,16,1, + 0,0,234,4,0,0,115,34,0,0,0,0,2,9,1,3, + 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24, + 1,6,1,27,2,6,1,17,1,9,1,18,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,25,0,0,0,135, + 0,0,135,1,0,102,2,0,100,1,0,100,2,0,134,0, + 0,125,2,0,124,2,0,83,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,43,0,0,0,116,0,0, + 124,0,0,131,1,0,115,30,0,116,1,0,100,1,0,100, + 2,0,124,0,0,131,1,1,130,1,0,136,0,0,124,0, + 0,136,1,0,140,1,0,83,41,3,122,45,80,97,116,104, + 32,104,111,111,107,32,102,111,114,32,105,109,112,111,114,116, + 108,105,98,46,109,97,99,104,105,110,101,114,121,46,70,105, + 108,101,70,105,110,100,101,114,46,122,30,111,110,108,121,32, + 100,105,114,101,99,116,111,114,105,101,115,32,97,114,101,32, + 115,117,112,112,111,114,116,101,100,114,35,0,0,0,41,2, + 114,46,0,0,0,114,107,0,0,0,41,1,114,35,0,0, + 0,41,2,114,170,0,0,0,114,15,1,0,0,114,4,0, + 0,0,114,5,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,19,5,0,0,115,6,0,0,0,0,2,12,1,18,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, + 170,0,0,0,114,15,1,0,0,114,21,1,0,0,114,4, + 0,0,0,41,2,114,170,0,0,0,114,15,1,0,0,114, + 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,9, + 5,0,0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1,0,106, + 0,0,124,0,0,106,1,0,131,1,0,83,41,2,78,122, + 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, + 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114, 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,7,95,95,108,101,110,95,95,246,3,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,2,0,0,0, - 67,0,0,0,115,16,0,0,0,100,1,0,106,0,0,124, - 0,0,106,1,0,131,1,0,83,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,47,0,0,0,114,236,0,0,0,41,1, - 114,108,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,218,8,95,95,114,101,112,114,95,95,249,3, - 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,2, - 0,0,0,67,0,0,0,115,16,0,0,0,124,1,0,124, - 0,0,106,0,0,131,0,0,107,6,0,83,41,1,78,41, - 1,114,243,0,0,0,41,2,114,108,0,0,0,218,4,105, - 116,101,109,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,12,95,95,99,111,110,116,97,105,110,115,95,95, - 252,3,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,2,0,0,0,67,0,0,0,115,20,0, - 0,0,124,0,0,106,0,0,106,1,0,124,1,0,131,1, - 0,1,100,0,0,83,41,1,78,41,2,114,236,0,0,0, - 114,169,0,0,0,41,2,114,108,0,0,0,114,248,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,169,0,0,0,255,3,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,13,114,112,0,0,0,114, - 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,188, - 0,0,0,114,242,0,0,0,114,237,0,0,0,114,243,0, - 0,0,114,245,0,0,0,114,246,0,0,0,114,247,0,0, - 0,114,249,0,0,0,114,169,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 234,0,0,0,203,3,0,0,115,20,0,0,0,12,5,6, - 2,12,6,12,10,12,4,12,13,12,3,12,3,12,3,12, - 3,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,118,0,0,0, - 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,100, - 2,0,132,0,0,90,3,0,101,4,0,100,3,0,100,4, - 0,132,0,0,131,1,0,90,5,0,100,5,0,100,6,0, - 132,0,0,90,6,0,100,7,0,100,8,0,132,0,0,90, - 7,0,100,9,0,100,10,0,132,0,0,90,8,0,100,11, - 0,100,12,0,132,0,0,90,9,0,100,13,0,100,14,0, - 132,0,0,90,10,0,100,15,0,100,16,0,132,0,0,90, - 11,0,100,17,0,83,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, - 25,0,0,0,116,0,0,124,1,0,124,2,0,124,3,0, - 131,3,0,124,0,0,95,1,0,100,0,0,83,41,1,78, - 41,2,114,234,0,0,0,114,236,0,0,0,41,4,114,108, - 0,0,0,114,106,0,0,0,114,35,0,0,0,114,240,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,188,0,0,0,5,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,2,0,0,0,67,0,0, - 0,115,16,0,0,0,100,1,0,106,0,0,124,1,0,106, - 1,0,131,1,0,83,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,47,0,0,0,114, - 112,0,0,0,41,2,114,174,0,0,0,114,134,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 11,109,111,100,117,108,101,95,114,101,112,114,8,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,0,83,41,2,78,84,114,4,0,0,0,41,2,114,108, - 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,162,0,0,0,17,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, - 0,83,41,2,78,114,30,0,0,0,114,4,0,0,0,41, - 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,203,0,0,0,20, - 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,22,0,0, - 0,116,0,0,100,1,0,100,2,0,100,3,0,100,4,0, - 100,5,0,131,3,1,83,41,6,78,114,30,0,0,0,122, - 8,60,115,116,114,105,110,103,62,114,192,0,0,0,114,205, - 0,0,0,84,41,1,114,206,0,0,0,41,2,114,108,0, - 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,190,0,0,0,23,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,0,83,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,4, - 0,0,0,41,2,114,108,0,0,0,114,133,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,189, - 0,0,0,26,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,0,83,41,1,78,114,4,0, - 0,0,41,2,114,108,0,0,0,114,134,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,193,0, - 0,0,29,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,3,0,0,0,67,0,0,0, - 115,29,0,0,0,116,0,0,100,1,0,124,0,0,106,1, - 0,131,2,0,1,116,2,0,124,0,0,124,1,0,131,2, - 0,83,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,3,114,105,0,0,0,114,236,0,0,0,114,135,0,0, - 0,41,2,114,108,0,0,0,114,126,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, - 0,32,4,0,0,115,4,0,0,0,0,7,16,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, - 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,188, - 0,0,0,114,186,0,0,0,114,251,0,0,0,114,162,0, - 0,0,114,203,0,0,0,114,190,0,0,0,114,189,0,0, - 0,114,193,0,0,0,114,194,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 250,0,0,0,4,4,0,0,115,16,0,0,0,12,1,12, - 3,18,9,12,3,12,3,12,3,12,3,12,3,114,250,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,5, - 0,0,0,64,0,0,0,115,160,0,0,0,101,0,0,90, - 1,0,100,0,0,90,2,0,100,1,0,90,3,0,101,4, - 0,100,2,0,100,3,0,132,0,0,131,1,0,90,5,0, - 101,4,0,100,4,0,100,5,0,132,0,0,131,1,0,90, - 6,0,101,4,0,100,6,0,100,7,0,132,0,0,131,1, - 0,90,7,0,101,4,0,100,8,0,100,9,0,132,0,0, - 131,1,0,90,8,0,101,4,0,100,10,0,100,11,0,100, - 12,0,132,1,0,131,1,0,90,9,0,101,4,0,100,10, - 0,100,10,0,100,13,0,100,14,0,132,2,0,131,1,0, - 90,10,0,101,4,0,100,10,0,100,15,0,100,16,0,132, - 1,0,131,1,0,90,11,0,100,10,0,83,41,17,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, - 55,0,0,0,120,48,0,116,0,0,106,1,0,106,2,0, - 131,0,0,68,93,31,0,125,1,0,116,3,0,124,1,0, - 100,1,0,131,2,0,114,16,0,124,1,0,106,4,0,131, - 0,0,1,113,16,0,87,100,2,0,83,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,7,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,115,0,0,0,114,253,0,0,0,41,2, - 114,174,0,0,0,218,6,102,105,110,100,101,114,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,253,0,0, - 0,49,4,0,0,115,6,0,0,0,0,4,22,1,15,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,12,0,0,0,67, - 0,0,0,115,107,0,0,0,116,0,0,106,1,0,100,1, - 0,107,9,0,114,41,0,116,0,0,106,1,0,12,114,41, - 0,116,2,0,106,3,0,100,2,0,116,4,0,131,2,0, - 1,120,59,0,116,0,0,106,1,0,68,93,44,0,125,2, - 0,121,14,0,124,2,0,124,1,0,131,1,0,83,87,113, - 51,0,4,116,5,0,107,10,0,114,94,0,1,1,1,119, - 51,0,89,113,51,0,88,113,51,0,87,100,1,0,83,100, - 1,0,83,41,3,122,113,83,101,97,114,99,104,32,115,101, - 113,117,101,110,99,101,32,111,102,32,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,10,10,32,32,32,32,32,32, - 32,32,73,102,32,39,104,111,111,107,115,39,32,105,115,32, - 102,97,108,115,101,32,116,104,101,110,32,117,115,101,32,115, - 121,115,46,112,97,116,104,95,104,111,111,107,115,46,10,10, - 32,32,32,32,32,32,32,32,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,7,0,0,0,218,10,112,97,116,104,95, - 104,111,111,107,115,114,60,0,0,0,114,61,0,0,0,114, - 125,0,0,0,114,107,0,0,0,41,3,114,174,0,0,0, - 114,35,0,0,0,90,4,104,111,111,107,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,11,95,112,97,116, - 104,95,104,111,111,107,115,57,4,0,0,115,16,0,0,0, - 0,7,25,1,16,1,16,1,3,1,14,1,13,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,19,0,0,0,67,0,0,0,115,123,0, - 0,0,124,1,0,100,1,0,107,2,0,114,53,0,121,16, - 0,116,0,0,106,1,0,131,0,0,125,1,0,87,110,22, - 0,4,116,2,0,107,10,0,114,52,0,1,1,1,100,2, - 0,83,89,110,1,0,88,121,17,0,116,3,0,106,4,0, - 124,1,0,25,125,2,0,87,110,46,0,4,116,5,0,107, - 10,0,114,118,0,1,1,1,124,0,0,106,6,0,124,1, - 0,131,1,0,125,2,0,124,2,0,116,3,0,106,4,0, - 124,1,0,60,89,110,1,0,88,124,2,0,83,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,3,0,0,0, - 114,45,0,0,0,218,17,70,105,108,101,78,111,116,70,111, - 117,110,100,69,114,114,111,114,114,7,0,0,0,114,254,0, - 0,0,114,142,0,0,0,114,2,1,0,0,41,3,114,174, - 0,0,0,114,35,0,0,0,114,0,1,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,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,74,4,0,0,115,22,0,0,0,0,8,12,1,3, - 1,16,1,13,3,9,1,3,1,17,1,13,1,15,1,18, - 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,3, - 0,0,0,67,0,0,0,115,116,0,0,0,116,0,0,124, - 2,0,100,1,0,131,2,0,114,39,0,124,2,0,106,1, - 0,124,1,0,131,1,0,92,2,0,125,3,0,125,4,0, - 110,21,0,124,2,0,106,2,0,124,1,0,131,1,0,125, - 3,0,103,0,0,125,4,0,124,3,0,100,0,0,107,9, - 0,114,85,0,116,3,0,124,1,0,124,3,0,131,2,0, - 83,116,4,0,106,5,0,124,1,0,100,0,0,131,2,0, - 125,5,0,124,4,0,124,5,0,95,6,0,124,5,0,83, - 41,2,78,114,124,0,0,0,41,7,114,115,0,0,0,114, - 124,0,0,0,114,185,0,0,0,114,131,0,0,0,114,121, - 0,0,0,114,166,0,0,0,114,164,0,0,0,41,6,114, - 174,0,0,0,114,126,0,0,0,114,0,1,0,0,114,127, - 0,0,0,114,128,0,0,0,114,133,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,16,95,108, - 101,103,97,99,121,95,103,101,116,95,115,112,101,99,96,4, - 0,0,115,18,0,0,0,0,4,15,1,24,2,15,1,6, - 1,12,1,13,1,18,1,9,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,243,0,0, - 0,103,0,0,125,4,0,120,230,0,124,2,0,68,93,191, - 0,125,5,0,116,0,0,124,5,0,116,1,0,116,2,0, - 102,2,0,131,2,0,115,43,0,113,13,0,124,0,0,106, - 3,0,124,5,0,131,1,0,125,6,0,124,6,0,100,1, - 0,107,9,0,114,13,0,116,4,0,124,6,0,100,2,0, - 131,2,0,114,106,0,124,6,0,106,5,0,124,1,0,124, - 3,0,131,2,0,125,7,0,110,18,0,124,0,0,106,6, - 0,124,1,0,124,6,0,131,2,0,125,7,0,124,7,0, - 100,1,0,107,8,0,114,139,0,113,13,0,124,7,0,106, - 7,0,100,1,0,107,9,0,114,158,0,124,7,0,83,124, - 7,0,106,8,0,125,8,0,124,8,0,100,1,0,107,8, - 0,114,191,0,116,9,0,100,3,0,131,1,0,130,1,0, - 124,4,0,106,10,0,124,8,0,131,1,0,1,113,13,0, - 87,116,11,0,106,12,0,124,1,0,100,1,0,131,2,0, - 125,7,0,124,4,0,124,7,0,95,8,0,124,7,0,83, - 100,1,0,83,41,4,122,63,70,105,110,100,32,116,104,101, - 32,108,111,97,100,101,114,32,111,114,32,110,97,109,101,115, - 112,97,99,101,95,112,97,116,104,32,102,111,114,32,116,104, - 105,115,32,109,111,100,117,108,101,47,112,97,99,107,97,103, - 101,32,110,97,109,101,46,78,114,184,0,0,0,122,19,115, - 112,101,99,32,109,105,115,115,105,110,103,32,108,111,97,100, - 101,114,41,13,114,148,0,0,0,114,69,0,0,0,218,5, - 98,121,116,101,115,114,4,1,0,0,114,115,0,0,0,114, - 184,0,0,0,114,5,1,0,0,114,127,0,0,0,114,164, - 0,0,0,114,107,0,0,0,114,154,0,0,0,114,121,0, - 0,0,114,166,0,0,0,41,9,114,174,0,0,0,114,126, - 0,0,0,114,35,0,0,0,114,183,0,0,0,218,14,110, - 97,109,101,115,112,97,99,101,95,112,97,116,104,90,5,101, - 110,116,114,121,114,0,1,0,0,114,133,0,0,0,114,128, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,9,95,103,101,116,95,115,112,101,99,111,4,0, - 0,115,40,0,0,0,0,5,6,1,13,1,21,1,3,1, - 15,1,12,1,15,1,21,2,18,1,12,1,3,1,15,1, - 4,1,9,1,12,1,12,5,17,2,18,1,9,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,4,0,0,0,67,0,0,0,115,140,0,0,0,124,2, - 0,100,1,0,107,8,0,114,21,0,116,0,0,106,1,0, - 125,2,0,124,0,0,106,2,0,124,1,0,124,2,0,124, - 3,0,131,3,0,125,4,0,124,4,0,100,1,0,107,8, - 0,114,58,0,100,1,0,83,124,4,0,106,3,0,100,1, - 0,107,8,0,114,132,0,124,4,0,106,4,0,125,5,0, - 124,5,0,114,125,0,100,2,0,124,4,0,95,5,0,116, - 6,0,124,1,0,124,5,0,124,0,0,106,2,0,131,3, - 0,124,4,0,95,4,0,124,4,0,83,100,1,0,83,110, - 4,0,124,4,0,83,100,1,0,83,41,3,122,98,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, - 78,90,9,110,97,109,101,115,112,97,99,101,41,7,114,7, - 0,0,0,114,35,0,0,0,114,8,1,0,0,114,127,0, - 0,0,114,164,0,0,0,114,161,0,0,0,114,234,0,0, - 0,41,6,114,174,0,0,0,114,126,0,0,0,114,35,0, - 0,0,114,183,0,0,0,114,133,0,0,0,114,7,1,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,184,0,0,0,143,4,0,0,115,26,0,0,0,0,4, - 12,1,9,1,21,1,12,1,4,1,15,1,9,1,6,3, - 9,1,24,1,4,2,7,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,41,0,0,0,124,0,0,106,0,0,124,1, - 0,124,2,0,131,2,0,125,3,0,124,3,0,100,1,0, - 107,8,0,114,34,0,100,1,0,83,124,3,0,106,1,0, - 83,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,184,0,0,0,114,127,0,0,0,41,4,114,174, - 0,0,0,114,126,0,0,0,114,35,0,0,0,114,133,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,185,0,0,0,165,4,0,0,115,8,0,0,0,0, - 8,18,1,12,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, - 12,114,112,0,0,0,114,111,0,0,0,114,113,0,0,0, - 114,114,0,0,0,114,186,0,0,0,114,253,0,0,0,114, - 2,1,0,0,114,4,1,0,0,114,5,1,0,0,114,8, - 1,0,0,114,184,0,0,0,114,185,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,252,0,0,0,45,4,0,0,115,22,0,0,0,12, - 2,6,2,18,8,18,17,18,22,18,15,3,1,18,31,3, - 1,21,21,3,1,114,252,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, - 133,0,0,0,101,0,0,90,1,0,100,0,0,90,2,0, - 100,1,0,90,3,0,100,2,0,100,3,0,132,0,0,90, - 4,0,100,4,0,100,5,0,132,0,0,90,5,0,101,6, - 0,90,7,0,100,6,0,100,7,0,132,0,0,90,8,0, - 100,8,0,100,9,0,132,0,0,90,9,0,100,10,0,100, - 11,0,100,12,0,132,1,0,90,10,0,100,13,0,100,14, - 0,132,0,0,90,11,0,101,12,0,100,15,0,100,16,0, - 132,0,0,131,1,0,90,13,0,100,17,0,100,18,0,132, - 0,0,90,14,0,100,10,0,83,41,19,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,122,0,0,0,103, - 0,0,125,3,0,120,52,0,124,2,0,68,93,44,0,92, - 2,0,137,0,0,125,4,0,124,3,0,106,0,0,135,0, - 0,102,1,0,100,1,0,100,2,0,134,0,0,124,4,0, - 68,131,1,0,131,1,0,1,113,13,0,87,124,3,0,124, - 0,0,95,1,0,124,1,0,112,79,0,100,3,0,124,0, - 0,95,2,0,100,6,0,124,0,0,95,3,0,116,4,0, - 131,0,0,124,0,0,95,5,0,116,4,0,131,0,0,124, - 0,0,95,6,0,100,5,0,83,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,27,0,0, - 0,124,0,0,93,17,0,125,1,0,124,1,0,136,0,0, - 102,2,0,86,1,113,3,0,100,0,0,83,41,1,78,114, - 4,0,0,0,41,2,114,22,0,0,0,114,229,0,0,0, - 41,1,114,127,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,231,0,0,0,194,4,0,0,115,2,0,0,0,6, - 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,58,0,0,0,114,29, - 0,0,0,78,114,87,0,0,0,41,7,114,154,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,108,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,171,0,0,0,114,4,0, - 0,0,41,1,114,127,0,0,0,114,5,0,0,0,114,188, - 0,0,0,188,4,0,0,115,16,0,0,0,0,4,6,1, - 19,1,36,1,9,2,15,1,9,1,12,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,13,0,0,0,100,3,0,124,0, - 0,95,0,0,100,2,0,83,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,29,0,0,0, - 78,114,87,0,0,0,41,1,114,11,1,0,0,41,1,114, - 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,253,0,0,0,202,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,59,0,0,0,124,0,0,106,0, - 0,124,1,0,131,1,0,125,2,0,124,2,0,100,1,0, - 107,8,0,114,37,0,100,1,0,103,0,0,102,2,0,83, - 124,2,0,106,1,0,124,2,0,106,2,0,112,55,0,103, - 0,0,102,2,0,83,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,184,0,0,0,114,127,0,0,0,114,164,0,0, - 0,41,3,114,108,0,0,0,114,126,0,0,0,114,133,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,124,0,0,0,208,4,0,0,115,8,0,0,0,0, - 7,15,1,12,1,10,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,7,0,0,0, - 67,0,0,0,115,40,0,0,0,124,1,0,124,2,0,124, - 3,0,131,2,0,125,6,0,116,0,0,124,2,0,124,3, - 0,100,1,0,124,6,0,100,2,0,124,4,0,131,2,2, - 83,41,3,78,114,127,0,0,0,114,164,0,0,0,41,1, - 114,165,0,0,0,41,7,114,108,0,0,0,114,170,0,0, - 0,114,126,0,0,0,114,35,0,0,0,90,4,115,109,115, - 108,114,183,0,0,0,114,127,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,8,1,0,0,220, - 4,0,0,115,6,0,0,0,0,1,15,1,18,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,234,1,0,0,100, - 1,0,125,3,0,124,1,0,106,0,0,100,2,0,131,1, - 0,100,3,0,25,125,4,0,121,34,0,116,1,0,124,0, - 0,106,2,0,112,49,0,116,3,0,106,4,0,131,0,0, - 131,1,0,106,5,0,125,5,0,87,110,24,0,4,116,6, - 0,107,10,0,114,85,0,1,1,1,100,10,0,125,5,0, - 89,110,1,0,88,124,5,0,124,0,0,106,7,0,107,3, - 0,114,120,0,124,0,0,106,8,0,131,0,0,1,124,5, - 0,124,0,0,95,7,0,116,9,0,131,0,0,114,153,0, - 124,0,0,106,10,0,125,6,0,124,4,0,106,11,0,131, - 0,0,125,7,0,110,15,0,124,0,0,106,12,0,125,6, - 0,124,4,0,125,7,0,124,7,0,124,6,0,107,6,0, - 114,45,1,116,13,0,124,0,0,106,2,0,124,4,0,131, - 2,0,125,8,0,120,100,0,124,0,0,106,14,0,68,93, - 77,0,92,2,0,125,9,0,125,10,0,100,5,0,124,9, - 0,23,125,11,0,116,13,0,124,8,0,124,11,0,131,2, - 0,125,12,0,116,15,0,124,12,0,131,1,0,114,208,0, - 124,0,0,106,16,0,124,10,0,124,1,0,124,12,0,124, - 8,0,103,1,0,124,2,0,131,5,0,83,113,208,0,87, - 116,17,0,124,8,0,131,1,0,125,3,0,120,123,0,124, - 0,0,106,14,0,68,93,112,0,92,2,0,125,9,0,125, - 10,0,116,13,0,124,0,0,106,2,0,124,4,0,124,9, - 0,23,131,2,0,125,12,0,116,18,0,100,6,0,106,19, - 0,124,12,0,131,1,0,100,7,0,100,3,0,131,1,1, - 1,124,7,0,124,9,0,23,124,6,0,107,6,0,114,55, - 1,116,15,0,124,12,0,131,1,0,114,55,1,124,0,0, - 106,16,0,124,10,0,124,1,0,124,12,0,100,8,0,124, - 2,0,131,5,0,83,113,55,1,87,124,3,0,114,230,1, - 116,18,0,100,9,0,106,19,0,124,8,0,131,1,0,131, - 1,0,1,116,20,0,106,21,0,124,1,0,100,8,0,131, - 2,0,125,13,0,124,8,0,103,1,0,124,13,0,95,22, - 0,124,13,0,83,100,8,0,83,41,11,122,125,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,70,114,58,0,0,0, - 114,56,0,0,0,114,29,0,0,0,114,188,0,0,0,122, - 9,116,114,121,105,110,103,32,123,125,114,98,0,0,0,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,87,0,0,0, - 41,23,114,32,0,0,0,114,39,0,0,0,114,35,0,0, - 0,114,3,0,0,0,114,45,0,0,0,114,220,0,0,0, - 114,40,0,0,0,114,11,1,0,0,218,11,95,102,105,108, - 108,95,99,97,99,104,101,114,6,0,0,0,114,14,1,0, - 0,114,88,0,0,0,114,13,1,0,0,114,28,0,0,0, - 114,10,1,0,0,114,44,0,0,0,114,8,1,0,0,114, - 46,0,0,0,114,105,0,0,0,114,47,0,0,0,114,121, - 0,0,0,114,166,0,0,0,114,164,0,0,0,41,14,114, - 108,0,0,0,114,126,0,0,0,114,183,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,138,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,229, - 0,0,0,114,170,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,133,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,184,0,0,0,225,4,0,0,115, - 68,0,0,0,0,3,6,1,19,1,3,1,34,1,13,1, - 11,1,15,1,10,1,9,2,9,1,9,1,15,2,9,1, - 6,2,12,1,18,1,22,1,10,1,15,1,12,1,32,4, - 12,2,22,1,22,1,25,1,16,1,12,1,29,1,6,1, - 19,1,18,1,12,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,11,1,0,0,124,0,0,106,0,0,125,1, - 0,121,31,0,116,1,0,106,2,0,124,1,0,112,33,0, - 116,1,0,106,3,0,131,0,0,131,1,0,125,2,0,87, - 110,33,0,4,116,4,0,116,5,0,116,6,0,102,3,0, - 107,10,0,114,75,0,1,1,1,103,0,0,125,2,0,89, - 110,1,0,88,116,7,0,106,8,0,106,9,0,100,1,0, - 131,1,0,115,112,0,116,10,0,124,2,0,131,1,0,124, - 0,0,95,11,0,110,111,0,116,10,0,131,0,0,125,3, - 0,120,90,0,124,2,0,68,93,82,0,125,4,0,124,4, - 0,106,12,0,100,2,0,131,1,0,92,3,0,125,5,0, - 125,6,0,125,7,0,124,6,0,114,191,0,100,3,0,106, - 13,0,124,5,0,124,7,0,106,14,0,131,0,0,131,2, - 0,125,8,0,110,6,0,124,5,0,125,8,0,124,3,0, - 106,15,0,124,8,0,131,1,0,1,113,128,0,87,124,3, - 0,124,0,0,95,11,0,116,7,0,106,8,0,106,9,0, - 116,16,0,131,1,0,114,7,1,100,4,0,100,5,0,132, - 0,0,124,2,0,68,131,1,0,124,0,0,95,17,0,100, - 6,0,83,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,58,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,28,0,0,0,104,0,0,124,0,0,93,18,0,125, - 1,0,124,1,0,106,0,0,131,0,0,146,2,0,113,6, - 0,83,114,4,0,0,0,41,1,114,88,0,0,0,41,2, - 114,22,0,0,0,90,2,102,110,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,250,9,60,115,101,116,99,111, - 109,112,62,43,5,0,0,115,2,0,0,0,9,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,3,0,0,0,90,7,108,105,115,116,100,105,114,114, - 45,0,0,0,114,3,1,0,0,218,15,80,101,114,109,105, - 115,115,105,111,110,69,114,114,111,114,218,18,78,111,116,65, - 68,105,114,101,99,116,111,114,121,69,114,114,111,114,114,7, - 0,0,0,114,8,0,0,0,114,9,0,0,0,114,12,1, - 0,0,114,13,1,0,0,114,83,0,0,0,114,47,0,0, - 0,114,88,0,0,0,218,3,97,100,100,114,10,0,0,0, - 114,14,1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,241,0,0, - 0,114,229,0,0,0,90,8,110,101,119,95,110,97,109,101, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 16,1,0,0,14,5,0,0,115,34,0,0,0,0,2,9, - 1,3,1,31,1,22,3,11,3,18,1,18,7,9,1,13, - 1,24,1,6,1,27,2,6,1,17,1,9,1,18,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,25,0,0, - 0,135,0,0,135,1,0,102,2,0,100,1,0,100,2,0, - 134,0,0,125,2,0,124,2,0,83,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,43,0,0,0,116, - 0,0,124,0,0,131,1,0,115,30,0,116,1,0,100,1, - 0,100,2,0,124,0,0,131,1,1,130,1,0,136,0,0, - 124,0,0,136,1,0,140,1,0,83,41,3,122,45,80,97, - 116,104,32,104,111,111,107,32,102,111,114,32,105,109,112,111, - 114,116,108,105,98,46,109,97,99,104,105,110,101,114,121,46, - 70,105,108,101,70,105,110,100,101,114,46,122,30,111,110,108, - 121,32,100,105,114,101,99,116,111,114,105,101,115,32,97,114, - 101,32,115,117,112,112,111,114,116,101,100,114,35,0,0,0, - 41,2,114,46,0,0,0,114,107,0,0,0,41,1,114,35, - 0,0,0,41,2,114,174,0,0,0,114,15,1,0,0,114, - 4,0,0,0,114,5,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,55,5,0,0,115,6,0,0,0,0,2,12,1, - 18,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,174,0,0,0,114,15,1,0,0,114,21,1,0,0, - 114,4,0,0,0,41,2,114,174,0,0,0,114,15,1,0, - 0,114,5,0,0,0,218,9,112,97,116,104,95,104,111,111, - 107,45,5,0,0,115,4,0,0,0,0,10,21,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,16,0,0,0,100,1, - 0,106,0,0,124,0,0,106,1,0,131,1,0,83,41,2, - 78,122,16,70,105,108,101,70,105,110,100,101,114,40,123,33, - 114,125,41,41,2,114,47,0,0,0,114,35,0,0,0,41, - 1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,247,0,0,0,63,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,15,114,112,0,0, - 0,114,111,0,0,0,114,113,0,0,0,114,114,0,0,0, - 114,188,0,0,0,114,253,0,0,0,114,130,0,0,0,114, - 185,0,0,0,114,124,0,0,0,114,8,1,0,0,114,184, - 0,0,0,114,16,1,0,0,114,186,0,0,0,114,22,1, - 0,0,114,247,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,9,1,0,0, - 179,4,0,0,115,20,0,0,0,12,7,6,2,12,14,12, - 4,6,2,12,12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106, - 0,0,100,1,0,131,1,0,125,4,0,124,0,0,106,0, - 0,100,2,0,131,1,0,125,5,0,124,4,0,115,99,0, - 124,5,0,114,54,0,124,5,0,106,1,0,125,4,0,110, - 45,0,124,2,0,124,3,0,107,2,0,114,84,0,116,2, - 0,124,1,0,124,2,0,131,2,0,125,4,0,110,15,0, - 116,3,0,124,1,0,124,2,0,131,2,0,125,4,0,124, - 5,0,115,126,0,116,4,0,124,1,0,124,2,0,100,3, - 0,124,4,0,131,2,1,125,5,0,121,44,0,124,5,0, - 124,0,0,100,2,0,60,124,4,0,124,0,0,100,1,0, - 60,124,2,0,124,0,0,100,4,0,60,124,3,0,124,0, - 0,100,5,0,60,87,110,18,0,4,116,5,0,107,10,0, - 114,190,0,1,1,1,89,110,1,0,88,100,0,0,83,41, - 6,78,114,227,0,0,0,218,8,95,95,115,112,101,99,95, - 95,114,127,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,127,0,0,0,114,224,0,0,0,114,219,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,106,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,127,0,0,0,114,133,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,14,95,102,105, - 120,95,117,112,95,109,111,100,117,108,101,69,5,0,0,115, - 34,0,0,0,0,2,15,1,15,1,6,1,6,1,12,1, - 12,1,18,2,15,1,6,1,21,1,3,1,10,1,10,1, - 10,1,14,1,13,2,114,26,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,55,0,0,0,116,0,0,116,1,0,106,2,0,131,0, - 0,102,2,0,125,0,0,116,3,0,116,4,0,102,2,0, - 125,1,0,116,5,0,116,6,0,102,2,0,125,2,0,124, - 0,0,124,1,0,124,2,0,103,3,0,83,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,225,0,0,0,114,150,0,0,0,218,18,101,120,116, - 101,110,115,105,111,110,95,115,117,102,102,105,120,101,115,114, - 219,0,0,0,114,84,0,0,0,114,224,0,0,0,114,74, - 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,5,0, - 0,0,114,167,0,0,0,92,5,0,0,115,8,0,0,0, - 0,5,18,1,12,1,12,1,114,167,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,70,2,0,0,124,0,0,97,0,0,116,0,0, - 106,1,0,97,1,0,116,0,0,106,2,0,97,2,0,116, - 1,0,106,3,0,116,4,0,25,125,1,0,120,76,0,100, - 26,0,68,93,68,0,125,2,0,124,2,0,116,1,0,106, - 3,0,107,7,0,114,83,0,116,0,0,106,5,0,124,2, - 0,131,1,0,125,3,0,110,13,0,116,1,0,106,3,0, - 124,2,0,25,125,3,0,116,6,0,124,1,0,124,2,0, - 124,3,0,131,3,0,1,113,44,0,87,100,5,0,100,6, - 0,103,1,0,102,2,0,100,7,0,100,8,0,100,6,0, - 103,2,0,102,2,0,102,2,0,125,4,0,120,149,0,124, - 4,0,68,93,129,0,92,2,0,125,5,0,125,6,0,116, - 7,0,100,9,0,100,10,0,132,0,0,124,6,0,68,131, - 1,0,131,1,0,115,199,0,116,8,0,130,1,0,124,6, - 0,100,11,0,25,125,7,0,124,5,0,116,1,0,106,3, - 0,107,6,0,114,241,0,116,1,0,106,3,0,124,5,0, - 25,125,8,0,80,113,156,0,121,20,0,116,0,0,106,5, - 0,124,5,0,131,1,0,125,8,0,80,87,113,156,0,4, - 116,9,0,107,10,0,114,28,1,1,1,1,119,156,0,89, - 113,156,0,88,113,156,0,87,116,9,0,100,12,0,131,1, - 0,130,1,0,116,6,0,124,1,0,100,13,0,124,8,0, - 131,3,0,1,116,6,0,124,1,0,100,14,0,124,7,0, - 131,3,0,1,116,6,0,124,1,0,100,15,0,100,16,0, - 106,10,0,124,6,0,131,1,0,131,3,0,1,121,19,0, - 116,0,0,106,5,0,100,17,0,131,1,0,125,9,0,87, - 110,24,0,4,116,9,0,107,10,0,114,147,1,1,1,1, - 100,18,0,125,9,0,89,110,1,0,88,116,6,0,124,1, - 0,100,17,0,124,9,0,131,3,0,1,116,0,0,106,5, - 0,100,19,0,131,1,0,125,10,0,116,6,0,124,1,0, - 100,19,0,124,10,0,131,3,0,1,124,5,0,100,7,0, - 107,2,0,114,238,1,116,0,0,106,5,0,100,20,0,131, - 1,0,125,11,0,116,6,0,124,1,0,100,21,0,124,11, - 0,131,3,0,1,116,6,0,124,1,0,100,22,0,116,11, - 0,131,0,0,131,3,0,1,116,12,0,106,13,0,116,2, - 0,106,14,0,131,0,0,131,1,0,1,124,5,0,100,7, - 0,107,2,0,114,66,2,116,15,0,106,16,0,100,23,0, - 131,1,0,1,100,24,0,116,12,0,107,6,0,114,66,2, - 100,25,0,116,17,0,95,18,0,100,18,0,83,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,49, - 0,0,0,114,60,0,0,0,218,8,98,117,105,108,116,105, - 110,115,114,147,0,0,0,90,5,112,111,115,105,120,250,1, - 47,218,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,33,0, - 0,0,124,0,0,93,23,0,125,1,0,116,0,0,124,1, - 0,131,1,0,100,0,0,107,2,0,86,1,113,3,0,100, - 1,0,83,41,2,114,29,0,0,0,78,41,1,114,31,0, - 0,0,41,2,114,22,0,0,0,114,77,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,231,0, - 0,0,128,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,173,0, - 0,0,114,6,0,0,0,122,4,46,112,121,119,122,6,95, - 100,46,112,121,100,84,41,4,122,3,95,105,111,122,9,95, - 119,97,114,110,105,110,103,115,122,8,98,117,105,108,116,105, - 110,115,122,7,109,97,114,115,104,97,108,41,19,114,121,0, - 0,0,114,7,0,0,0,114,150,0,0,0,114,132,0,0, - 0,114,112,0,0,0,90,18,95,98,117,105,108,116,105,110, - 95,102,114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11, - 0,0,0,114,233,0,0,0,114,154,0,0,0,114,27,1, - 0,0,114,84,0,0,0,114,169,0,0,0,114,172,0,0, - 0,114,177,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, + 0,0,0,114,247,0,0,0,27,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,15,114,112,0,0,0,114, + 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185, + 0,0,0,114,253,0,0,0,114,130,0,0,0,114,182,0, + 0,0,114,124,0,0,0,114,8,1,0,0,114,181,0,0, + 0,114,16,1,0,0,114,183,0,0,0,114,22,1,0,0, + 114,247,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,9,1,0,0,143,4, + 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6, + 2,12,12,12,5,15,45,12,31,18,18,114,9,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,195,0,0,0,124,0,0,106,0,0, + 100,1,0,131,1,0,125,4,0,124,0,0,106,0,0,100, + 2,0,131,1,0,125,5,0,124,4,0,115,99,0,124,5, + 0,114,54,0,124,5,0,106,1,0,125,4,0,110,45,0, + 124,2,0,124,3,0,107,2,0,114,84,0,116,2,0,124, + 1,0,124,2,0,131,2,0,125,4,0,110,15,0,116,3, + 0,124,1,0,124,2,0,131,2,0,125,4,0,124,5,0, + 115,126,0,116,4,0,124,1,0,124,2,0,100,3,0,124, + 4,0,131,2,1,125,5,0,121,44,0,124,5,0,124,0, + 0,100,2,0,60,124,4,0,124,0,0,100,1,0,60,124, + 2,0,124,0,0,100,4,0,60,124,3,0,124,0,0,100, + 5,0,60,87,110,18,0,4,116,5,0,107,10,0,114,190, + 0,1,1,1,89,110,1,0,88,100,0,0,83,41,6,78, + 114,226,0,0,0,218,8,95,95,115,112,101,99,95,95,114, + 127,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,127,0,0,0,114,223,0,0,0,114,218,0,0,0, + 114,167,0,0,0,218,9,69,120,99,101,112,116,105,111,110, + 41,6,90,2,110,115,114,106,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,127,0,0,0,114,164,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,14,95,102,105,120,95, + 117,112,95,109,111,100,117,108,101,33,5,0,0,115,34,0, + 0,0,0,2,15,1,15,1,6,1,6,1,12,1,12,1, + 18,2,15,1,6,1,21,1,3,1,10,1,10,1,10,1, + 14,1,13,2,114,26,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,55, + 0,0,0,116,0,0,116,1,0,106,2,0,131,0,0,102, + 2,0,125,0,0,116,3,0,116,4,0,102,2,0,125,1, + 0,116,5,0,116,6,0,102,2,0,125,2,0,124,0,0, + 124,1,0,124,2,0,103,3,0,83,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, + 224,0,0,0,114,145,0,0,0,218,18,101,120,116,101,110, + 115,105,111,110,95,115,117,102,102,105,120,101,115,114,218,0, + 0,0,114,84,0,0,0,114,223,0,0,0,114,74,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,5,0,0,0, - 218,6,95,115,101,116,117,112,103,5,0,0,115,82,0,0, - 0,0,8,6,1,9,1,9,3,13,1,13,1,15,1,18, - 2,13,1,20,3,33,1,19,2,31,1,10,1,15,1,13, - 1,4,2,3,1,15,1,5,1,13,1,12,2,12,1,16, - 1,16,1,25,3,3,1,19,1,13,2,11,1,16,3,15, - 1,16,3,12,1,15,1,16,3,19,1,19,1,12,1,13, - 1,12,1,114,35,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,116,0, - 0,0,116,0,0,124,0,0,131,1,0,1,116,1,0,131, - 0,0,125,1,0,116,2,0,106,3,0,106,4,0,116,5, - 0,106,6,0,124,1,0,140,0,0,103,1,0,131,1,0, - 1,116,7,0,106,8,0,100,1,0,107,2,0,114,78,0, - 116,2,0,106,9,0,106,10,0,116,11,0,131,1,0,1, - 116,2,0,106,9,0,106,10,0,116,12,0,131,1,0,1, - 116,5,0,124,0,0,95,5,0,116,13,0,124,0,0,95, - 13,0,100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0, - 114,167,0,0,0,114,7,0,0,0,114,1,1,0,0,114, - 154,0,0,0,114,9,1,0,0,114,22,1,0,0,114,3, - 0,0,0,114,112,0,0,0,218,9,109,101,116,97,95,112, - 97,116,104,114,169,0,0,0,114,172,0,0,0,114,252,0, - 0,0,114,219,0,0,0,41,2,114,34,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,5,0,0,0, - 218,8,95,105,110,115,116,97,108,108,171,5,0,0,115,16, - 0,0,0,0,2,10,1,9,1,28,1,15,1,16,1,16, - 4,9,1,114,37,1,0,0,41,3,122,3,119,105,110,114, - 1,0,0,0,114,2,0,0,0,41,59,114,114,0,0,0, - 114,10,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,55,0,0,0,218,4,116,121,112,101,218,8,95, - 95,99,111,100,101,95,95,114,149,0,0,0,114,15,0,0, - 0,114,140,0,0,0,114,14,0,0,0,114,18,0,0,0, - 90,17,95,82,65,87,95,77,65,71,73,67,95,78,85,77, - 66,69,82,114,73,0,0,0,114,72,0,0,0,114,84,0, - 0,0,114,74,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,79,0, - 0,0,114,85,0,0,0,114,91,0,0,0,114,95,0,0, - 0,114,97,0,0,0,114,105,0,0,0,114,123,0,0,0, - 114,130,0,0,0,114,135,0,0,0,114,146,0,0,0,114, - 152,0,0,0,114,155,0,0,0,114,160,0,0,0,114,131, - 0,0,0,218,6,111,98,106,101,99,116,114,168,0,0,0, - 114,165,0,0,0,114,172,0,0,0,114,187,0,0,0,114, - 195,0,0,0,114,211,0,0,0,114,219,0,0,0,114,224, - 0,0,0,114,233,0,0,0,114,225,0,0,0,114,234,0, - 0,0,114,250,0,0,0,114,252,0,0,0,114,9,1,0, - 0,114,26,1,0,0,114,167,0,0,0,114,35,1,0,0, - 114,37,1,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,8,60,109,111,100,117, - 108,101,62,8,0,0,0,115,104,0,0,0,6,17,6,3, - 12,12,12,5,12,5,12,6,12,12,12,10,12,9,12,5, - 12,7,15,22,15,108,22,1,18,2,6,1,6,2,9,2, - 9,2,10,2,21,44,12,33,12,19,12,12,12,12,18,8, - 12,27,12,18,12,15,21,55,21,12,18,10,12,14,24,22, - 9,3,12,1,15,65,19,63,19,27,22,110,19,41,25,43, + 114,161,0,0,0,56,5,0,0,115,8,0,0,0,0,5, + 18,1,12,1,12,1,114,161,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,70,2,0,0,124,0,0,97,0,0,116,0,0,106,1, + 0,97,1,0,116,0,0,106,2,0,97,2,0,116,1,0, + 106,3,0,116,4,0,25,125,1,0,120,76,0,100,26,0, + 68,93,68,0,125,2,0,124,2,0,116,1,0,106,3,0, + 107,7,0,114,83,0,116,0,0,106,5,0,124,2,0,131, + 1,0,125,3,0,110,13,0,116,1,0,106,3,0,124,2, + 0,25,125,3,0,116,6,0,124,1,0,124,2,0,124,3, + 0,131,3,0,1,113,44,0,87,100,5,0,100,6,0,103, + 1,0,102,2,0,100,7,0,100,8,0,100,6,0,103,2, + 0,102,2,0,102,2,0,125,4,0,120,149,0,124,4,0, + 68,93,129,0,92,2,0,125,5,0,125,6,0,116,7,0, + 100,9,0,100,10,0,132,0,0,124,6,0,68,131,1,0, + 131,1,0,115,199,0,116,8,0,130,1,0,124,6,0,100, + 11,0,25,125,7,0,124,5,0,116,1,0,106,3,0,107, + 6,0,114,241,0,116,1,0,106,3,0,124,5,0,25,125, + 8,0,80,113,156,0,121,20,0,116,0,0,106,5,0,124, + 5,0,131,1,0,125,8,0,80,87,113,156,0,4,116,9, + 0,107,10,0,114,28,1,1,1,1,119,156,0,89,113,156, + 0,88,113,156,0,87,116,9,0,100,12,0,131,1,0,130, + 1,0,116,6,0,124,1,0,100,13,0,124,8,0,131,3, + 0,1,116,6,0,124,1,0,100,14,0,124,7,0,131,3, + 0,1,116,6,0,124,1,0,100,15,0,100,16,0,106,10, + 0,124,6,0,131,1,0,131,3,0,1,121,19,0,116,0, + 0,106,5,0,100,17,0,131,1,0,125,9,0,87,110,24, + 0,4,116,9,0,107,10,0,114,147,1,1,1,1,100,18, + 0,125,9,0,89,110,1,0,88,116,6,0,124,1,0,100, + 17,0,124,9,0,131,3,0,1,116,0,0,106,5,0,100, + 19,0,131,1,0,125,10,0,116,6,0,124,1,0,100,19, + 0,124,10,0,131,3,0,1,124,5,0,100,7,0,107,2, + 0,114,238,1,116,0,0,106,5,0,100,20,0,131,1,0, + 125,11,0,116,6,0,124,1,0,100,21,0,124,11,0,131, + 3,0,1,116,6,0,124,1,0,100,22,0,116,11,0,131, + 0,0,131,3,0,1,116,12,0,106,13,0,116,2,0,106, + 14,0,131,0,0,131,1,0,1,124,5,0,100,7,0,107, + 2,0,114,66,2,116,15,0,106,16,0,100,23,0,131,1, + 0,1,100,24,0,116,12,0,107,6,0,114,66,2,100,25, + 0,116,17,0,95,18,0,100,18,0,83,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,49,0,0, + 0,114,60,0,0,0,218,8,98,117,105,108,116,105,110,115, + 114,142,0,0,0,90,5,112,111,115,105,120,250,1,47,218, + 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,33,0,0,0, + 124,0,0,93,23,0,125,1,0,116,0,0,124,1,0,131, + 1,0,100,0,0,107,2,0,86,1,113,3,0,100,1,0, + 83,41,2,114,29,0,0,0,78,41,1,114,31,0,0,0, + 41,2,114,22,0,0,0,114,77,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,230,0,0,0, + 92,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,169,0,0,0, + 114,6,0,0,0,122,4,46,112,121,119,122,6,95,100,46, + 112,121,100,84,41,4,122,3,95,105,111,122,9,95,119,97, + 114,110,105,110,103,115,122,8,98,117,105,108,116,105,110,115, + 122,7,109,97,114,115,104,97,108,41,19,114,121,0,0,0, + 114,7,0,0,0,114,145,0,0,0,114,242,0,0,0,114, + 112,0,0,0,90,18,95,98,117,105,108,116,105,110,95,102, + 114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0,0, + 0,114,232,0,0,0,114,149,0,0,0,114,27,1,0,0, + 114,84,0,0,0,114,163,0,0,0,114,168,0,0,0,114, + 173,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, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,6, + 95,115,101,116,117,112,67,5,0,0,115,82,0,0,0,0, + 8,6,1,9,1,9,3,13,1,13,1,15,1,18,2,13, + 1,20,3,33,1,19,2,31,1,10,1,15,1,13,1,4, + 2,3,1,15,1,5,1,13,1,12,2,12,1,16,1,16, + 1,25,3,3,1,19,1,13,2,11,1,16,3,15,1,16, + 3,12,1,15,1,16,3,19,1,19,1,12,1,13,1,12, + 1,114,35,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,116,0,0,0, + 116,0,0,124,0,0,131,1,0,1,116,1,0,131,0,0, + 125,1,0,116,2,0,106,3,0,106,4,0,116,5,0,106, + 6,0,124,1,0,140,0,0,103,1,0,131,1,0,1,116, + 7,0,106,8,0,100,1,0,107,2,0,114,78,0,116,2, + 0,106,9,0,106,10,0,116,11,0,131,1,0,1,116,2, + 0,106,9,0,106,10,0,116,12,0,131,1,0,1,116,5, + 0,124,0,0,95,5,0,116,13,0,124,0,0,95,13,0, + 100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0,114,161, + 0,0,0,114,7,0,0,0,114,1,1,0,0,114,149,0, + 0,0,114,9,1,0,0,114,22,1,0,0,114,3,0,0, + 0,114,112,0,0,0,218,9,109,101,116,97,95,112,97,116, + 104,114,163,0,0,0,114,168,0,0,0,114,252,0,0,0, + 114,218,0,0,0,41,2,114,34,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,5,0,0,0,218,8, + 95,105,110,115,116,97,108,108,135,5,0,0,115,16,0,0, + 0,0,2,10,1,9,1,28,1,15,1,16,1,16,4,9, + 1,114,37,1,0,0,41,3,122,3,119,105,110,114,1,0, + 0,0,114,2,0,0,0,41,57,114,114,0,0,0,114,10, + 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,55,0,0,0,218,4,116,121,112,101,218,8,95,95,99, + 111,100,101,95,95,114,144,0,0,0,114,15,0,0,0,114, + 135,0,0,0,114,14,0,0,0,114,18,0,0,0,90,17, + 95,82,65,87,95,77,65,71,73,67,95,78,85,77,66,69, + 82,114,73,0,0,0,114,72,0,0,0,114,84,0,0,0, + 114,74,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,79,0,0,0, + 114,85,0,0,0,114,91,0,0,0,114,95,0,0,0,114, + 97,0,0,0,114,105,0,0,0,114,123,0,0,0,114,130, + 0,0,0,114,141,0,0,0,114,147,0,0,0,114,150,0, + 0,0,114,155,0,0,0,218,6,111,98,106,101,99,116,114, + 162,0,0,0,114,167,0,0,0,114,168,0,0,0,114,184, + 0,0,0,114,194,0,0,0,114,210,0,0,0,114,218,0, + 0,0,114,223,0,0,0,114,232,0,0,0,114,224,0,0, + 0,114,233,0,0,0,114,250,0,0,0,114,252,0,0,0, + 114,9,1,0,0,114,26,1,0,0,114,161,0,0,0,114, + 35,1,0,0,114,37,1,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,60, + 109,111,100,117,108,101,62,8,0,0,0,115,100,0,0,0, + 6,17,6,3,12,12,12,5,12,5,12,6,12,12,12,10, + 12,9,12,5,12,7,15,22,15,108,22,1,18,2,6,1, + 6,2,9,2,9,2,10,2,21,44,12,33,12,19,12,12, + 12,12,18,8,12,27,12,17,21,55,21,12,18,10,12,14, + 9,3,12,1,15,65,19,64,19,28,22,110,19,41,25,43, 25,16,6,3,19,57,19,57,19,41,19,134,19,146,15,23, 12,11,12,68, }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 06:01:23 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 16 May 2015 04:01:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Tighten-up_code_by_elimina?= =?utf-8?q?ting_an_unnecessary_variable=2E?= Message-ID: <20150516040123.26552.83177@psf.io> https://hg.python.org/cpython/rev/bffb4303681b changeset: 96076:bffb4303681b user: Raymond Hettinger date: Fri May 15 21:01:13 2015 -0700 summary: Tighten-up code by eliminating an unnecessary variable. files: Modules/_heapqmodule.c | 18 ++++++++---------- 1 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -50,7 +50,7 @@ static int siftup(PyListObject *heap, Py_ssize_t pos) { - Py_ssize_t startpos, endpos, childpos, rightpos, limit; + Py_ssize_t startpos, endpos, childpos, limit; PyObject *tmp1, *tmp2; int cmp; @@ -67,16 +67,15 @@ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ - rightpos = childpos + 1; - if (rightpos < endpos) { + if (childpos + 1 < endpos) { cmp = PyObject_RichCompareBool( PyList_GET_ITEM(heap, childpos), - PyList_GET_ITEM(heap, rightpos), + PyList_GET_ITEM(heap, childpos + 1), Py_LT); if (cmp == -1) return -1; if (cmp == 0) - childpos = rightpos; + childpos++; /* rightmost child is smallest */ if (endpos != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); @@ -402,7 +401,7 @@ static int siftup_max(PyListObject *heap, Py_ssize_t pos) { - Py_ssize_t startpos, endpos, childpos, rightpos, limit; + Py_ssize_t startpos, endpos, childpos, limit; PyObject *tmp1, *tmp2; int cmp; @@ -419,16 +418,15 @@ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ - rightpos = childpos + 1; - if (rightpos < endpos) { + if (childpos + 1 < endpos) { cmp = PyObject_RichCompareBool( - PyList_GET_ITEM(heap, rightpos), + PyList_GET_ITEM(heap, childpos + 1), PyList_GET_ITEM(heap, childpos), Py_LT); if (cmp == -1) return -1; if (cmp == 0) - childpos = rightpos; + childpos++; /* rightmost child is smallest */ if (endpos != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat May 16 10:42:34 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 16 May 2015 08:42:34 +0000 Subject: [Python-checkins] Daily reference leaks (bffb4303681b): sum=4 Message-ID: <20150516084234.26850.43059@psf.io> results for bffb4303681b on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogxZbx_M', '--timeout', '7200'] From python-checkins at python.org Sat May 16 13:12:32 2015 From: python-checkins at python.org (tal.einat) Date: Sat, 16 May 2015 11:12:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Argument_Clinic=3A_added_m?= =?utf-8?q?issing_bit_of_info_in_howto?= Message-ID: <20150516111229.21164.5450@psf.io> https://hg.python.org/cpython/rev/57a27aae7836 changeset: 96077:57a27aae7836 user: Tal Einat date: Sat May 16 14:12:15 2015 +0300 summary: Argument Clinic: added missing bit of info in howto files: Doc/howto/clinic.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -826,6 +826,7 @@ ``'I'`` ``unsigned_int(bitwise=True)`` ``'k'`` ``unsigned_long(bitwise=True)`` ``'K'`` ``unsigned_PY_LONG_LONG(bitwise=True)`` +``'l'`` ``long`` ``'L'`` ``PY_LONG_LONG`` ``'n'`` ``Py_ssize_t`` ``'O'`` ``object`` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 13:14:59 2015 From: python-checkins at python.org (tal.einat) Date: Sat, 16 May 2015 11:14:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320182=3A_converte?= =?utf-8?q?d_the_signal_module_to_use_Argument_Clinic?= Message-ID: <20150516111457.44689.87156@psf.io> https://hg.python.org/cpython/rev/5342fad7cd59 changeset: 96078:5342fad7cd59 user: Tal Einat date: Sat May 16 14:14:49 2015 +0300 summary: Issue #20182: converted the signal module to use Argument Clinic files: Doc/library/signal.rst | 12 +- Modules/clinic/signalmodule.c.h | 432 ++++++++++++++++++ Modules/signalmodule.c | 461 ++++++++++--------- 3 files changed, 684 insertions(+), 221 deletions(-) diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -219,21 +219,21 @@ :func:`sigpending`. -.. function:: pthread_kill(thread_id, signum) +.. function:: pthread_kill(thread_id, signalnum) - Send the signal *signum* to the thread *thread_id*, another thread in the + Send the signal *signalnum* to the thread *thread_id*, another thread in the same process as the caller. The target thread can be executing any code (Python or not). However, if the target thread is executing the Python interpreter, the Python signal handlers will be :ref:`executed by the main - thread `. Therefore, the only point of sending a signal to a particular - Python thread would be to force a running system call to fail with - :exc:`InterruptedError`. + thread `. Therefore, the only point of sending a + signal to a particular Python thread would be to force a running system call + to fail with :exc:`InterruptedError`. Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` attribute of :class:`threading.Thread` objects to get a suitable value for *thread_id*. - If *signum* is 0, then no signal is sent, but error checking is still + If *signalnum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if the target thread is still running. Availability: Unix (see the man page :manpage:`pthread_kill(3)` for further diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h new file mode 100644 --- /dev/null +++ b/Modules/clinic/signalmodule.c.h @@ -0,0 +1,432 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(HAVE_ALARM) + +PyDoc_STRVAR(signal_alarm__doc__, +"alarm($module, seconds, /)\n" +"--\n" +"\n" +"Arrange for SIGALRM to arrive after the given number of seconds."); + +#define SIGNAL_ALARM_METHODDEF \ + {"alarm", (PyCFunction)signal_alarm, METH_O, signal_alarm__doc__}, + +static long +signal_alarm_impl(PyModuleDef *module, int seconds); + +static PyObject * +signal_alarm(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int seconds; + long _return_value; + + if (!PyArg_Parse(arg, "i:alarm", &seconds)) + goto exit; + _return_value = signal_alarm_impl(module, seconds); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_ALARM) */ + +#if defined(HAVE_PAUSE) + +PyDoc_STRVAR(signal_pause__doc__, +"pause($module, /)\n" +"--\n" +"\n" +"Wait until a signal arrives."); + +#define SIGNAL_PAUSE_METHODDEF \ + {"pause", (PyCFunction)signal_pause, METH_NOARGS, signal_pause__doc__}, + +static PyObject * +signal_pause_impl(PyModuleDef *module); + +static PyObject * +signal_pause(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_pause_impl(module); +} + +#endif /* defined(HAVE_PAUSE) */ + +PyDoc_STRVAR(signal_signal__doc__, +"signal($module, signalnum, handler, /)\n" +"--\n" +"\n" +"Set the action for the given signal.\n" +"\n" +"The action can be SIG_DFL, SIG_IGN, or a callable Python object.\n" +"The previous action is returned. See getsignal() for possible return values.\n" +"\n" +"*** IMPORTANT NOTICE ***\n" +"A signal handler function is called with two arguments:\n" +"the first is the signal number, the second is the interrupted stack frame."); + +#define SIGNAL_SIGNAL_METHODDEF \ + {"signal", (PyCFunction)signal_signal, METH_VARARGS, signal_signal__doc__}, + +static PyObject * +signal_signal_impl(PyModuleDef *module, int signalnum, PyObject *handler); + +static PyObject * +signal_signal(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int signalnum; + PyObject *handler; + + if (!PyArg_ParseTuple(args, "iO:signal", + &signalnum, &handler)) + goto exit; + return_value = signal_signal_impl(module, signalnum, handler); + +exit: + return return_value; +} + +PyDoc_STRVAR(signal_getsignal__doc__, +"getsignal($module, signalnum, /)\n" +"--\n" +"\n" +"Return the current action for the given signal.\n" +"\n" +"The return value can be:\n" +" SIG_IGN -- if the signal is being ignored\n" +" SIG_DFL -- if the default action for the signal is in effect\n" +" None -- if an unknown handler is in effect\n" +" anything else -- the callable Python object used as a handler"); + +#define SIGNAL_GETSIGNAL_METHODDEF \ + {"getsignal", (PyCFunction)signal_getsignal, METH_O, signal_getsignal__doc__}, + +static PyObject * +signal_getsignal_impl(PyModuleDef *module, int signalnum); + +static PyObject * +signal_getsignal(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int signalnum; + + if (!PyArg_Parse(arg, "i:getsignal", &signalnum)) + goto exit; + return_value = signal_getsignal_impl(module, signalnum); + +exit: + return return_value; +} + +#if defined(HAVE_SIGINTERRUPT) + +PyDoc_STRVAR(signal_siginterrupt__doc__, +"siginterrupt($module, signalnum, flag, /)\n" +"--\n" +"\n" +"Change system call restart behaviour.\n" +"\n" +"If flag is False, system calls will be restarted when interrupted by\n" +"signal sig, else system calls will be interrupted."); + +#define SIGNAL_SIGINTERRUPT_METHODDEF \ + {"siginterrupt", (PyCFunction)signal_siginterrupt, METH_VARARGS, signal_siginterrupt__doc__}, + +static PyObject * +signal_siginterrupt_impl(PyModuleDef *module, int signalnum, int flag); + +static PyObject * +signal_siginterrupt(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int signalnum; + int flag; + + if (!PyArg_ParseTuple(args, "ii:siginterrupt", + &signalnum, &flag)) + goto exit; + return_value = signal_siginterrupt_impl(module, signalnum, flag); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SIGINTERRUPT) */ + +#if defined(HAVE_SETITIMER) + +PyDoc_STRVAR(signal_setitimer__doc__, +"setitimer($module, which, seconds, interval=0.0, /)\n" +"--\n" +"\n" +"Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF).\n" +"\n" +"The timer will fire after value seconds and after that every interval seconds.\n" +"The itimer can be cleared by setting seconds to zero.\n" +"\n" +"Returns old values as a tuple: (delay, interval)."); + +#define SIGNAL_SETITIMER_METHODDEF \ + {"setitimer", (PyCFunction)signal_setitimer, METH_VARARGS, signal_setitimer__doc__}, + +static PyObject * +signal_setitimer_impl(PyModuleDef *module, int which, double seconds, + double interval); + +static PyObject * +signal_setitimer(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int which; + double seconds; + double interval = 0.0; + + if (!PyArg_ParseTuple(args, "id|d:setitimer", + &which, &seconds, &interval)) + goto exit; + return_value = signal_setitimer_impl(module, which, seconds, interval); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETITIMER) */ + +#if defined(HAVE_GETITIMER) + +PyDoc_STRVAR(signal_getitimer__doc__, +"getitimer($module, which, /)\n" +"--\n" +"\n" +"Returns current value of given itimer."); + +#define SIGNAL_GETITIMER_METHODDEF \ + {"getitimer", (PyCFunction)signal_getitimer, METH_O, signal_getitimer__doc__}, + +static PyObject * +signal_getitimer_impl(PyModuleDef *module, int which); + +static PyObject * +signal_getitimer(PyModuleDef *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int which; + + if (!PyArg_Parse(arg, "i:getitimer", &which)) + goto exit; + return_value = signal_getitimer_impl(module, which); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETITIMER) */ + +#if defined(PYPTHREAD_SIGMASK) + +PyDoc_STRVAR(signal_pthread_sigmask__doc__, +"pthread_sigmask($module, how, mask, /)\n" +"--\n" +"\n" +"Fetch and/or change the signal mask of the calling thread."); + +#define SIGNAL_PTHREAD_SIGMASK_METHODDEF \ + {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, METH_VARARGS, signal_pthread_sigmask__doc__}, + +static PyObject * +signal_pthread_sigmask_impl(PyModuleDef *module, int how, PyObject *mask); + +static PyObject * +signal_pthread_sigmask(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int how; + PyObject *mask; + + if (!PyArg_ParseTuple(args, "iO:pthread_sigmask", + &how, &mask)) + goto exit; + return_value = signal_pthread_sigmask_impl(module, how, mask); + +exit: + return return_value; +} + +#endif /* defined(PYPTHREAD_SIGMASK) */ + +#if defined(HAVE_SIGPENDING) + +PyDoc_STRVAR(signal_sigpending__doc__, +"sigpending($module, /)\n" +"--\n" +"\n" +"Examine pending signals.\n" +"\n" +"Returns a set of signal numbers that are pending for delivery to\n" +"the calling thread."); + +#define SIGNAL_SIGPENDING_METHODDEF \ + {"sigpending", (PyCFunction)signal_sigpending, METH_NOARGS, signal_sigpending__doc__}, + +static PyObject * +signal_sigpending_impl(PyModuleDef *module); + +static PyObject * +signal_sigpending(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_sigpending_impl(module); +} + +#endif /* defined(HAVE_SIGPENDING) */ + +#if defined(HAVE_SIGWAIT) + +PyDoc_STRVAR(signal_sigwait__doc__, +"sigwait($module, sigset, /)\n" +"--\n" +"\n" +"Wait for a signal.\n" +"\n" +"Suspend execution of the calling thread until the delivery of one of the\n" +"signals specified in the signal set sigset. The function accepts the signal\n" +"and returns the signal number."); + +#define SIGNAL_SIGWAIT_METHODDEF \ + {"sigwait", (PyCFunction)signal_sigwait, METH_O, signal_sigwait__doc__}, + +#endif /* defined(HAVE_SIGWAIT) */ + +#if defined(HAVE_SIGWAITINFO) + +PyDoc_STRVAR(signal_sigwaitinfo__doc__, +"sigwaitinfo($module, sigset, /)\n" +"--\n" +"\n" +"Wait synchronously until one of the signals in *sigset* is delivered.\n" +"\n" +"Returns a struct_siginfo containing information about the signal."); + +#define SIGNAL_SIGWAITINFO_METHODDEF \ + {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, METH_O, signal_sigwaitinfo__doc__}, + +#endif /* defined(HAVE_SIGWAITINFO) */ + +#if defined(HAVE_SIGTIMEDWAIT) + +PyDoc_STRVAR(signal_sigtimedwait__doc__, +"sigtimedwait($module, sigset, timeout, /)\n" +"--\n" +"\n" +"Like sigwaitinfo(), but with a timeout.\n" +"\n" +"The timeout is specified in seconds, with floating point numbers allowed."); + +#define SIGNAL_SIGTIMEDWAIT_METHODDEF \ + {"sigtimedwait", (PyCFunction)signal_sigtimedwait, METH_VARARGS, signal_sigtimedwait__doc__}, + +static PyObject * +signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, + PyObject *timeout); + +static PyObject * +signal_sigtimedwait(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *sigset; + PyObject *timeout; + + if (!PyArg_UnpackTuple(args, "sigtimedwait", + 2, 2, + &sigset, &timeout)) + goto exit; + return_value = signal_sigtimedwait_impl(module, sigset, timeout); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SIGTIMEDWAIT) */ + +#if (defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)) + +PyDoc_STRVAR(signal_pthread_kill__doc__, +"pthread_kill($module, thread_id, signalnum, /)\n" +"--\n" +"\n" +"Send a signal to a thread."); + +#define SIGNAL_PTHREAD_KILL_METHODDEF \ + {"pthread_kill", (PyCFunction)signal_pthread_kill, METH_VARARGS, signal_pthread_kill__doc__}, + +static PyObject * +signal_pthread_kill_impl(PyModuleDef *module, long thread_id, int signalnum); + +static PyObject * +signal_pthread_kill(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + long thread_id; + int signalnum; + + if (!PyArg_ParseTuple(args, "li:pthread_kill", + &thread_id, &signalnum)) + goto exit; + return_value = signal_pthread_kill_impl(module, thread_id, signalnum); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)) */ + +#ifndef SIGNAL_ALARM_METHODDEF + #define SIGNAL_ALARM_METHODDEF +#endif /* !defined(SIGNAL_ALARM_METHODDEF) */ + +#ifndef SIGNAL_PAUSE_METHODDEF + #define SIGNAL_PAUSE_METHODDEF +#endif /* !defined(SIGNAL_PAUSE_METHODDEF) */ + +#ifndef SIGNAL_SIGINTERRUPT_METHODDEF + #define SIGNAL_SIGINTERRUPT_METHODDEF +#endif /* !defined(SIGNAL_SIGINTERRUPT_METHODDEF) */ + +#ifndef SIGNAL_SETITIMER_METHODDEF + #define SIGNAL_SETITIMER_METHODDEF +#endif /* !defined(SIGNAL_SETITIMER_METHODDEF) */ + +#ifndef SIGNAL_GETITIMER_METHODDEF + #define SIGNAL_GETITIMER_METHODDEF +#endif /* !defined(SIGNAL_GETITIMER_METHODDEF) */ + +#ifndef SIGNAL_PTHREAD_SIGMASK_METHODDEF + #define SIGNAL_PTHREAD_SIGMASK_METHODDEF +#endif /* !defined(SIGNAL_PTHREAD_SIGMASK_METHODDEF) */ + +#ifndef SIGNAL_SIGPENDING_METHODDEF + #define SIGNAL_SIGPENDING_METHODDEF +#endif /* !defined(SIGNAL_SIGPENDING_METHODDEF) */ + +#ifndef SIGNAL_SIGWAIT_METHODDEF + #define SIGNAL_SIGWAIT_METHODDEF +#endif /* !defined(SIGNAL_SIGWAIT_METHODDEF) */ + +#ifndef SIGNAL_SIGWAITINFO_METHODDEF + #define SIGNAL_SIGWAITINFO_METHODDEF +#endif /* !defined(SIGNAL_SIGWAITINFO_METHODDEF) */ + +#ifndef SIGNAL_SIGTIMEDWAIT_METHODDEF + #define SIGNAL_SIGTIMEDWAIT_METHODDEF +#endif /* !defined(SIGNAL_SIGTIMEDWAIT_METHODDEF) */ + +#ifndef SIGNAL_PTHREAD_KILL_METHODDEF + #define SIGNAL_PTHREAD_KILL_METHODDEF +#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ +/*[clinic end generated code: output=65ca7b83632eda99 input=a9049054013a1b77]*/ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -52,6 +52,13 @@ # endif #endif +#include "clinic/signalmodule.c.h" + +/*[clinic input] +module signal +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ + /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -322,25 +329,37 @@ #ifdef HAVE_ALARM -static PyObject * -signal_alarm(PyObject *self, PyObject *args) + +/*[clinic input] +signal.alarm -> long + + seconds: int + / + +Arrange for SIGALRM to arrive after the given number of seconds. +[clinic start generated code]*/ + +static long +signal_alarm_impl(PyModuleDef *module, int seconds) +/*[clinic end generated code: output=f5f9badaab25d3e7 input=0d5e97e0e6f39e86]*/ { - int t; - if (!PyArg_ParseTuple(args, "i:alarm", &t)) - return NULL; /* alarm() returns the number of seconds remaining */ - return PyLong_FromLong((long)alarm(t)); + return (long)alarm(seconds); } -PyDoc_STRVAR(alarm_doc, -"alarm(seconds)\n\ -\n\ -Arrange for SIGALRM to arrive after the given number of seconds."); #endif #ifdef HAVE_PAUSE + +/*[clinic input] +signal.pause + +Wait until a signal arrives. +[clinic start generated code]*/ + static PyObject * -signal_pause(PyObject *self) +signal_pause_impl(PyModuleDef *module) +/*[clinic end generated code: output=9245704caa63bbe9 input=f03de0f875752062]*/ { Py_BEGIN_ALLOW_THREADS (void)pause(); @@ -351,29 +370,38 @@ if (PyErr_CheckSignals()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -PyDoc_STRVAR(pause_doc, -"pause()\n\ -\n\ -Wait until a signal arrives."); #endif +/*[clinic input] +signal.signal + + signalnum: int + handler: object + / + +Set the action for the given signal. + +The action can be SIG_DFL, SIG_IGN, or a callable Python object. +The previous action is returned. See getsignal() for possible return values. + +*** IMPORTANT NOTICE *** +A signal handler function is called with two arguments: +the first is the signal number, the second is the interrupted stack frame. +[clinic start generated code]*/ + static PyObject * -signal_signal(PyObject *self, PyObject *args) +signal_signal_impl(PyModuleDef *module, int signalnum, PyObject *handler) +/*[clinic end generated code: output=622d7d0beebea546 input=deee84af5fa0432c]*/ { - PyObject *obj; - int sig_num; PyObject *old_handler; void (*func)(int); - if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj)) - return NULL; #ifdef MS_WINDOWS - /* Validate that sig_num is one of the allowable signals */ - switch (sig_num) { + /* Validate that signalnum is one of the allowable signals */ + switch (signalnum) { case SIGABRT: break; #ifdef SIGBREAK /* Issue #10003: SIGBREAK is not documented as permitted, but works @@ -397,61 +425,63 @@ return NULL; } #endif - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - if (obj == IgnoreHandler) + if (handler == IgnoreHandler) func = SIG_IGN; - else if (obj == DefaultHandler) + else if (handler == DefaultHandler) func = SIG_DFL; - else if (!PyCallable_Check(obj)) { + else if (!PyCallable_Check(handler)) { PyErr_SetString(PyExc_TypeError, "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object"); return NULL; } else func = signal_handler; - if (PyOS_setsig(sig_num, func) == SIG_ERR) { + if (PyOS_setsig(signalnum, func) == SIG_ERR) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - old_handler = Handlers[sig_num].func; - Handlers[sig_num].tripped = 0; - Py_INCREF(obj); - Handlers[sig_num].func = obj; + old_handler = Handlers[signalnum].func; + Handlers[signalnum].tripped = 0; + Py_INCREF(handler); + Handlers[signalnum].func = handler; if (old_handler != NULL) return old_handler; else Py_RETURN_NONE; } -PyDoc_STRVAR(signal_doc, -"signal(sig, action) -> action\n\ -\n\ -Set the action for the given signal. The action can be SIG_DFL,\n\ -SIG_IGN, or a callable Python object. The previous action is\n\ -returned. See getsignal() for possible return values.\n\ -\n\ -*** IMPORTANT NOTICE ***\n\ -A signal handler function is called with two arguments:\n\ -the first is the signal number, the second is the interrupted stack frame."); +/*[clinic input] +signal.getsignal + + signalnum: int + / + +Return the current action for the given signal. + +The return value can be: + SIG_IGN -- if the signal is being ignored + SIG_DFL -- if the default action for the signal is in effect + None -- if an unknown handler is in effect + anything else -- the callable Python object used as a handler +[clinic start generated code]*/ static PyObject * -signal_getsignal(PyObject *self, PyObject *args) +signal_getsignal_impl(PyModuleDef *module, int signalnum) +/*[clinic end generated code: output=d50ec355757e360c input=ac23a00f19dfa509]*/ { - int sig_num; PyObject *old_handler; - if (!PyArg_ParseTuple(args, "i:getsignal", &sig_num)) - return NULL; - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - old_handler = Handlers[sig_num].func; + old_handler = Handlers[signalnum].func; if (old_handler != NULL) { Py_INCREF(old_handler); return old_handler; @@ -461,47 +491,41 @@ } } -PyDoc_STRVAR(getsignal_doc, -"getsignal(sig) -> action\n\ -\n\ -Return the current action for the given signal. The return value can be:\n\ -SIG_IGN -- if the signal is being ignored\n\ -SIG_DFL -- if the default action for the signal is in effect\n\ -None -- if an unknown handler is in effect\n\ -anything else -- the callable Python object used as a handler"); +#ifdef HAVE_SIGINTERRUPT -#ifdef HAVE_SIGINTERRUPT -PyDoc_STRVAR(siginterrupt_doc, -"siginterrupt(sig, flag) -> None\n\ -change system call restart behaviour: if flag is False, system calls\n\ -will be restarted when interrupted by signal sig, else system calls\n\ -will be interrupted."); +/*[clinic input] +signal.siginterrupt + + signalnum: int + flag: int + / + +Change system call restart behaviour. + +If flag is False, system calls will be restarted when interrupted by +signal sig, else system calls will be interrupted. +[clinic start generated code]*/ static PyObject * -signal_siginterrupt(PyObject *self, PyObject *args) +signal_siginterrupt_impl(PyModuleDef *module, int signalnum, int flag) +/*[clinic end generated code: output=5dcf8b031b0e8044 input=4160acacca3e2099]*/ { - int sig_num; - int flag; - - if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag)) - return NULL; - if (sig_num < 1 || sig_num >= NSIG) { + if (signalnum < 1 || signalnum >= NSIG) { PyErr_SetString(PyExc_ValueError, "signal number out of range"); return NULL; } - if (siginterrupt(sig_num, flag)<0) { + if (siginterrupt(signalnum, flag)<0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif -static PyObject * + +static PyObject* signal_set_wakeup_fd(PyObject *self, PyObject *args) { struct _Py_stat_struct status; @@ -640,62 +664,69 @@ #ifdef HAVE_SETITIMER + +/*[clinic input] +signal.setitimer + + which: int + seconds: double + interval: double = 0.0 + / + +Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL or ITIMER_PROF). + +The timer will fire after value seconds and after that every interval seconds. +The itimer can be cleared by setting seconds to zero. + +Returns old values as a tuple: (delay, interval). +[clinic start generated code]*/ + static PyObject * -signal_setitimer(PyObject *self, PyObject *args) +signal_setitimer_impl(PyModuleDef *module, int which, double seconds, + double interval) +/*[clinic end generated code: output=9a9227a27bd05988 input=0d27d417cfcbd51a]*/ { - double first; - double interval = 0; - int which; struct itimerval new, old; - if(!PyArg_ParseTuple(args, "id|d:setitimer", &which, &first, &interval)) - return NULL; - - timeval_from_double(first, &new.it_value); + timeval_from_double(seconds, &new.it_value); timeval_from_double(interval, &new.it_interval); /* Let OS check "which" value */ if (setitimer(which, &new, &old) != 0) { - PyErr_SetFromErrno(ItimerError); - return NULL; + PyErr_SetFromErrno(ItimerError); + return NULL; } return itimer_retval(&old); } -PyDoc_STRVAR(setitimer_doc, -"setitimer(which, seconds[, interval])\n\ -\n\ -Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL\n\ -or ITIMER_PROF) to fire after value seconds and after\n\ -that every interval seconds.\n\ -The itimer can be cleared by setting seconds to zero.\n\ -\n\ -Returns old values as a tuple: (delay, interval)."); #endif #ifdef HAVE_GETITIMER + +/*[clinic input] +signal.getitimer + + which: int + / + +Returns current value of given itimer. +[clinic start generated code]*/ + static PyObject * -signal_getitimer(PyObject *self, PyObject *args) +signal_getitimer_impl(PyModuleDef *module, int which) +/*[clinic end generated code: output=d1349ab18aadc569 input=f7d21d38f3490627]*/ { - int which; struct itimerval old; - if (!PyArg_ParseTuple(args, "i:getitimer", &which)) - return NULL; - if (getitimer(which, &old) != 0) { - PyErr_SetFromErrno(ItimerError); - return NULL; + PyErr_SetFromErrno(ItimerError); + return NULL; } return itimer_retval(&old); } -PyDoc_STRVAR(getitimer_doc, -"getitimer(which)\n\ -\n\ -Returns current value of given itimer."); #endif #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ @@ -786,21 +817,28 @@ #endif #ifdef PYPTHREAD_SIGMASK + +/*[clinic input] +signal.pthread_sigmask + + how: int + mask: object + / + +Fetch and/or change the signal mask of the calling thread. +[clinic start generated code]*/ + static PyObject * -signal_pthread_sigmask(PyObject *self, PyObject *args) +signal_pthread_sigmask_impl(PyModuleDef *module, int how, PyObject *mask) +/*[clinic end generated code: output=b043a9f0eeb1e075 input=f3b7d7a61b7b8283]*/ { - int how; - PyObject *signals; - sigset_t mask, previous; + sigset_t newmask, previous; int err; - if (!PyArg_ParseTuple(args, "iO:pthread_sigmask", &how, &signals)) + if (iterable_to_sigset(mask, &newmask)) return NULL; - if (iterable_to_sigset(signals, &mask)) - return NULL; - - err = pthread_sigmask(how, &mask, &previous); + err = pthread_sigmask(how, &newmask, &previous); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -814,16 +852,23 @@ return sigset_to_set(previous); } -PyDoc_STRVAR(signal_pthread_sigmask_doc, -"pthread_sigmask(how, mask) -> old mask\n\ -\n\ -Fetch and/or change the signal mask of the calling thread."); #endif /* #ifdef PYPTHREAD_SIGMASK */ #ifdef HAVE_SIGPENDING + +/*[clinic input] +signal.sigpending + +Examine pending signals. + +Returns a set of signal numbers that are pending for delivery to +the calling thread. +[clinic start generated code]*/ + static PyObject * -signal_sigpending(PyObject *self) +signal_sigpending_impl(PyModuleDef *module) +/*[clinic end generated code: output=bf4ced803e7e51dd input=e0036c016f874e29]*/ { int err; sigset_t mask; @@ -833,25 +878,32 @@ return sigset_to_set(mask); } -PyDoc_STRVAR(signal_sigpending_doc, -"sigpending() -> list\n\ -\n\ -Examine pending signals."); #endif /* #ifdef HAVE_SIGPENDING */ #ifdef HAVE_SIGWAIT + +/*[clinic input] +signal.sigwait + + sigset: object + / + +Wait for a signal. + +Suspend execution of the calling thread until the delivery of one of the +signals specified in the signal set sigset. The function accepts the signal +and returns the signal number. +[clinic start generated code]*/ + static PyObject * -signal_sigwait(PyObject *self, PyObject *args) +signal_sigwait(PyModuleDef *module, PyObject *sigset) +/*[clinic end generated code: output=dae53048b0336a5c input=11af2d82d83c2e94]*/ { - PyObject *signals; sigset_t set; int err, signum; - if (!PyArg_ParseTuple(args, "O:sigwait", &signals)) - return NULL; - - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; Py_BEGIN_ALLOW_THREADS @@ -865,11 +917,8 @@ return PyLong_FromLong(signum); } -PyDoc_STRVAR(signal_sigwait_doc, -"sigwait(sigset) -> signum\n\ -\n\ -Wait a signal."); -#endif /* #ifdef HAVE_SIGPENDING */ +#endif /* #ifdef HAVE_SIGWAIT */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) static int initialized; @@ -924,19 +973,28 @@ #endif #ifdef HAVE_SIGWAITINFO + +/*[clinic input] +signal.sigwaitinfo + + sigset: object + / + +Wait synchronously until one of the signals in *sigset* is delivered. + +Returns a struct_siginfo containing information about the signal. +[clinic start generated code]*/ + static PyObject * -signal_sigwaitinfo(PyObject *self, PyObject *args) +signal_sigwaitinfo(PyModuleDef *module, PyObject *sigset) +/*[clinic end generated code: output=0bb53b07e5e926b5 input=f3779a74a991e171]*/ { - PyObject *signals; sigset_t set; siginfo_t si; int err; int async_err = 0; - if (!PyArg_ParseTuple(args, "O:sigwaitinfo", &signals)) - return NULL; - - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; do { @@ -951,29 +1009,33 @@ return fill_siginfo(&si); } -PyDoc_STRVAR(signal_sigwaitinfo_doc, -"sigwaitinfo(sigset) -> struct_siginfo\n\ -\n\ -Wait synchronously for a signal until one of the signals in *sigset* is\n\ -delivered.\n\ -Returns a struct_siginfo containing information about the signal."); #endif /* #ifdef HAVE_SIGWAITINFO */ #ifdef HAVE_SIGTIMEDWAIT + +/*[clinic input] +signal.sigtimedwait + + sigset: object + timeout: object + / + +Like sigwaitinfo(), but with a timeout. + +The timeout is specified in seconds, with floating point numbers allowed. +[clinic start generated code]*/ + static PyObject * -signal_sigtimedwait(PyObject *self, PyObject *args) +signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, + PyObject *timeout) +/*[clinic end generated code: output=e6e049f2bddea688 input=036bbab9b15cb8de]*/ { - PyObject *signals, *timeout_obj; struct timespec ts; sigset_t set; siginfo_t si; int res; _PyTime_t timeout, deadline, monotonic; - if (!PyArg_ParseTuple(args, "OO:sigtimedwait", - &signals, &timeout_obj)) - return NULL; - if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_CEILING) < 0) return NULL; @@ -983,7 +1045,7 @@ return NULL; } - if (iterable_to_sigset(signals, &set)) + if (iterable_to_sigset(sigset, &set)) return NULL; deadline = _PyTime_GetMonotonicClock() + timeout; @@ -1019,26 +1081,28 @@ return fill_siginfo(&si); } -PyDoc_STRVAR(signal_sigtimedwait_doc, -"sigtimedwait(sigset, (timeout_sec, timeout_nsec)) -> struct_siginfo\n\ -\n\ -Like sigwaitinfo(), but with a timeout specified as a tuple of (seconds,\n\ -nanoseconds)."); #endif /* #ifdef HAVE_SIGTIMEDWAIT */ #if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) + +/*[clinic input] +signal.pthread_kill + + thread_id: long + signalnum: int + / + +Send a signal to a thread. +[clinic start generated code]*/ + static PyObject * -signal_pthread_kill(PyObject *self, PyObject *args) +signal_pthread_kill_impl(PyModuleDef *module, long thread_id, int signalnum) +/*[clinic end generated code: output=35aed2713c756d7a input=77ed6a3b6f2a8122]*/ { - long tid; - int signum; int err; - if (!PyArg_ParseTuple(args, "li:pthread_kill", &tid, &signum)) - return NULL; - - err = pthread_kill((pthread_t)tid, signum); + err = pthread_kill((pthread_t)thread_id, signalnum); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -1052,62 +1116,29 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(signal_pthread_kill_doc, -"pthread_kill(thread_id, signum)\n\ -\n\ -Send a signal to a thread."); #endif /* #if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) */ -/* List of functions defined in the module */ +/* List of functions defined in the module -- some of the methoddefs are + defined to nothing if the corresponding C function is not available. */ static PyMethodDef signal_methods[] = { -#ifdef HAVE_ALARM - {"alarm", signal_alarm, METH_VARARGS, alarm_doc}, -#endif -#ifdef HAVE_SETITIMER - {"setitimer", signal_setitimer, METH_VARARGS, setitimer_doc}, -#endif -#ifdef HAVE_GETITIMER - {"getitimer", signal_getitimer, METH_VARARGS, getitimer_doc}, -#endif - {"signal", signal_signal, METH_VARARGS, signal_doc}, - {"getsignal", signal_getsignal, METH_VARARGS, getsignal_doc}, + {"default_int_handler", signal_default_int_handler, METH_VARARGS, default_int_handler_doc}, + SIGNAL_ALARM_METHODDEF + SIGNAL_SETITIMER_METHODDEF + SIGNAL_GETITIMER_METHODDEF + SIGNAL_SIGNAL_METHODDEF + SIGNAL_GETSIGNAL_METHODDEF {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc}, -#ifdef HAVE_SIGINTERRUPT - {"siginterrupt", signal_siginterrupt, METH_VARARGS, siginterrupt_doc}, -#endif -#ifdef HAVE_PAUSE - {"pause", (PyCFunction)signal_pause, - METH_NOARGS, pause_doc}, -#endif - {"default_int_handler", signal_default_int_handler, - METH_VARARGS, default_int_handler_doc}, -#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) - {"pthread_kill", (PyCFunction)signal_pthread_kill, - METH_VARARGS, signal_pthread_kill_doc}, -#endif -#ifdef PYPTHREAD_SIGMASK - {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, - METH_VARARGS, signal_pthread_sigmask_doc}, -#endif -#ifdef HAVE_SIGPENDING - {"sigpending", (PyCFunction)signal_sigpending, - METH_NOARGS, signal_sigpending_doc}, -#endif -#ifdef HAVE_SIGWAIT - {"sigwait", (PyCFunction)signal_sigwait, - METH_VARARGS, signal_sigwait_doc}, -#endif -#ifdef HAVE_SIGWAITINFO - {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, - METH_VARARGS, signal_sigwaitinfo_doc}, -#endif -#ifdef HAVE_SIGTIMEDWAIT - {"sigtimedwait", (PyCFunction)signal_sigtimedwait, - METH_VARARGS, signal_sigtimedwait_doc}, -#endif - {NULL, NULL} /* sentinel */ + SIGNAL_SIGINTERRUPT_METHODDEF + SIGNAL_PAUSE_METHODDEF + SIGNAL_PTHREAD_KILL_METHODDEF + SIGNAL_PTHREAD_SIGMASK_METHODDEF + SIGNAL_SIGPENDING_METHODDEF + SIGNAL_SIGWAIT_METHODDEF + SIGNAL_SIGWAITINFO_METHODDEF + SIGNAL_SIGTIMEDWAIT_METHODDEF + {NULL, NULL} /* sentinel */ }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 14:58:17 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 12:58:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_compilation_error_in?= =?utf-8?q?_signalmodule=2Ec_=28issue_=2320182=29=2E?= Message-ID: <20150516125816.39261.32834@psf.io> https://hg.python.org/cpython/rev/738ac3ad9ee4 changeset: 96079:738ac3ad9ee4 user: Serhiy Storchaka date: Sat May 16 15:57:56 2015 +0300 summary: Fixed compilation error in signalmodule.c (issue #20182). files: Modules/clinic/signalmodule.c.h | 10 +++++----- Modules/signalmodule.c | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -333,20 +333,20 @@ static PyObject * signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, - PyObject *timeout); + PyObject *timeout_obj); static PyObject * signal_sigtimedwait(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; PyObject *sigset; - PyObject *timeout; + PyObject *timeout_obj; if (!PyArg_UnpackTuple(args, "sigtimedwait", 2, 2, - &sigset, &timeout)) + &sigset, &timeout_obj)) goto exit; - return_value = signal_sigtimedwait_impl(module, sigset, timeout); + return_value = signal_sigtimedwait_impl(module, sigset, timeout_obj); exit: return return_value; @@ -429,4 +429,4 @@ #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=65ca7b83632eda99 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b99278c16c40ea43 input=a9049054013a1b77]*/ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1017,7 +1017,7 @@ signal.sigtimedwait sigset: object - timeout: object + timeout as timeout_obj: object / Like sigwaitinfo(), but with a timeout. @@ -1027,8 +1027,8 @@ static PyObject * signal_sigtimedwait_impl(PyModuleDef *module, PyObject *sigset, - PyObject *timeout) -/*[clinic end generated code: output=e6e049f2bddea688 input=036bbab9b15cb8de]*/ + PyObject *timeout_obj) +/*[clinic end generated code: output=c1960b5cea139929 input=53fd4ea3e3724eb8]*/ { struct timespec ts; sigset_t set; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:33:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:33:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Reverted_issue?= =?utf-8?q?_=2324134_changes_=28except_new_tests=29=2E?= Message-ID: <20150516133303.16316.59929@psf.io> https://hg.python.org/cpython/rev/a69a346f0c34 changeset: 96081:a69a346f0c34 branch: 3.4 parent: 96073:526ce81f700d user: Serhiy Storchaka date: Sat May 16 16:25:43 2015 +0300 summary: Reverted issue #24134 changes (except new tests). files: Lib/unittest/case.py | 24 ++++++++++----------- Lib/unittest/test/test_case.py | 11 ---------- Misc/NEWS | 3 -- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -129,17 +129,15 @@ msg = self.test_case._formatMessage(self.msg, standardMsg) raise self.test_case.failureException(msg) -def _sentinel(*args, **kwargs): - raise AssertionError('Should never be called') class _AssertRaisesBaseContext(_BaseTestCaseContext): - def __init__(self, expected, test_case, callable_obj=_sentinel, + def __init__(self, expected, test_case, callable_obj=None, expected_regex=None): _BaseTestCaseContext.__init__(self, test_case) self.expected = expected self.test_case = test_case - if callable_obj is not _sentinel: + if callable_obj is not None: try: self.obj_name = callable_obj.__name__ except AttributeError: @@ -153,11 +151,11 @@ def handle(self, name, callable_obj, args, kwargs): """ - If callable_obj is _sentinel, assertRaises/Warns is being used as a + If callable_obj is None, assertRaises/Warns is being used as a context manager, so check for a 'msg' kwarg and return self. - If callable_obj is not _sentinel, call it passing args and kwargs. + If callable_obj is not None, call it passing args and kwargs. """ - if callable_obj is _sentinel: + if callable_obj is None: self.msg = kwargs.pop('msg', None) return self with self: @@ -676,7 +674,7 @@ except UnicodeDecodeError: return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): + def assertRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -684,7 +682,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted, will return a + If called with callableObj omitted or None, will return a context object used like this:: with self.assertRaises(SomeException): @@ -705,7 +703,7 @@ context = _AssertRaisesContext(excClass, self, callableObj) return context.handle('assertRaises', callableObj, args, kwargs) - def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs): + def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): """Fail unless a warning of class warnClass is triggered by callable_obj when invoked with arguments args and keyword arguments kwargs. If a different type of warning is @@ -713,7 +711,7 @@ warning filtering rules in effect, it might be silenced, printed out, or raised as an exception. - If called with callable_obj omitted, will return a + If called with callable_obj omitted or None, will return a context object used like this:: with self.assertWarns(SomeWarning): @@ -1221,7 +1219,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegex(self, expected_exception, expected_regex, - callable_obj=_sentinel, *args, **kwargs): + callable_obj=None, *args, **kwargs): """Asserts that the message in a raised exception matches a regex. Args: @@ -1240,7 +1238,7 @@ return context.handle('assertRaisesRegex', callable_obj, args, kwargs) def assertWarnsRegex(self, expected_warning, expected_regex, - callable_obj=_sentinel, *args, **kwargs): + callable_obj=None, *args, **kwargs): """Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1147,9 +1147,6 @@ # Failure when no exception is raised with self.assertRaises(self.failureException): self.assertRaises(ExceptionMock, lambda: 0) - # Failure when the function is None - with self.assertRaises(TypeError): - self.assertRaises(ExceptionMock, None) # Failure when another exception is raised with self.assertRaises(ExceptionMock): self.assertRaises(ValueError, Stub) @@ -1187,8 +1184,6 @@ self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) - with self.assertRaises(TypeError): - self.assertRaisesRegex(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegex(self): self.assertRaisesRegex( @@ -1256,9 +1251,6 @@ # Failure when no warning is triggered with self.assertRaises(self.failureException): self.assertWarns(RuntimeWarning, lambda: 0) - # Failure when the function is None - with self.assertRaises(TypeError): - self.assertWarns(RuntimeWarning, None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) @@ -1320,9 +1312,6 @@ with self.assertRaises(self.failureException): self.assertWarnsRegex(RuntimeWarning, "o+", lambda: 0) - # Failure when the function is None - with self.assertRaises(TypeError): - self.assertWarnsRegex(RuntimeWarning, "o+", None) # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,9 +48,6 @@ - Issue #23796: peak and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. -- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and - assertWarnsRegex() checks are not longer successful if the callable is None. - - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:33:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:33:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150516133303.21158.34641@psf.io> https://hg.python.org/cpython/rev/d5d7591dcea8 changeset: 96083:d5d7591dcea8 parent: 96082:ac13f0390866 parent: 96081:a69a346f0c34 user: Serhiy Storchaka date: Sat May 16 16:31:35 2015 +0300 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:33:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:33:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324134=3A_assertRa?= =?utf-8?q?ises=28=29=2C_assertRaisesRegex=28=29=2C_assertWarns=28=29_and?= Message-ID: <20150516133303.39247.36647@psf.io> https://hg.python.org/cpython/rev/ac13f0390866 changeset: 96082:ac13f0390866 parent: 96079:738ac3ad9ee4 user: Serhiy Storchaka date: Sat May 16 16:29:50 2015 +0300 summary: Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks now emits a deprecation warning when callable is None or keyword arguments except msg is passed in the context manager mode. files: Lib/unittest/case.py | 88 +++++++++++----------- Lib/unittest/test/test_case.py | 44 ++++++++++- Misc/NEWS | 3 +- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -129,37 +129,42 @@ msg = self.test_case._formatMessage(self.msg, standardMsg) raise self.test_case.failureException(msg) -def _sentinel(*args, **kwargs): - raise AssertionError('Should never be called') - class _AssertRaisesBaseContext(_BaseTestCaseContext): - def __init__(self, expected, test_case, callable_obj=_sentinel, - expected_regex=None): + def __init__(self, expected, test_case, expected_regex=None): _BaseTestCaseContext.__init__(self, test_case) self.expected = expected self.test_case = test_case - if callable_obj is not _sentinel: - try: - self.obj_name = callable_obj.__name__ - except AttributeError: - self.obj_name = str(callable_obj) - else: - self.obj_name = None if expected_regex is not None: expected_regex = re.compile(expected_regex) self.expected_regex = expected_regex + self.obj_name = None self.msg = None - def handle(self, name, callable_obj, args, kwargs): + def handle(self, name, args, kwargs): """ - If callable_obj is _sentinel, assertRaises/Warns is being used as a + If args is empty, assertRaises/Warns is being used as a context manager, so check for a 'msg' kwarg and return self. - If callable_obj is not _sentinel, call it passing args and kwargs. + If args is not empty, call a callable passing positional and keyword + arguments. """ - if callable_obj is _sentinel: + if args and args[0] is None: + warnings.warn("callable is None", + DeprecationWarning, 3) + args = () + if not args: self.msg = kwargs.pop('msg', None) + if kwargs: + warnings.warn('%r is an invalid keyword argument for ' + 'this function' % next(iter(kwargs)), + DeprecationWarning, 3) return self + + callable_obj, *args = args + try: + self.obj_name = callable_obj.__name__ + except AttributeError: + self.obj_name = str(callable_obj) with self: callable_obj(*args, **kwargs) @@ -676,15 +681,15 @@ except UnicodeDecodeError: return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): - """Fail unless an exception of class excClass is raised - by callableObj when invoked with arguments args and keyword - arguments kwargs. If a different type of exception is + def assertRaises(self, expected_exception, *args, **kwargs): + """Fail unless an exception of class expected_exception is raised + by the callable when invoked with specified positional and + keyword arguments. If a different type of exception is raised, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted, will return a + If called with the callable and arguments omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -702,18 +707,18 @@ the_exception = cm.exception self.assertEqual(the_exception.error_code, 3) """ - context = _AssertRaisesContext(excClass, self, callableObj) - return context.handle('assertRaises', callableObj, args, kwargs) + context = _AssertRaisesContext(expected_exception, self) + return context.handle('assertRaises', args, kwargs) - def assertWarns(self, expected_warning, callable_obj=_sentinel, *args, **kwargs): + def assertWarns(self, expected_warning, *args, **kwargs): """Fail unless a warning of class warnClass is triggered - by callable_obj when invoked with arguments args and keyword - arguments kwargs. If a different type of warning is + by the callable when invoked with specified positional and + keyword arguments. If a different type of warning is triggered, it will not be handled: depending on the other warning filtering rules in effect, it might be silenced, printed out, or raised as an exception. - If called with callable_obj omitted, will return a + If called with the callable and arguments omitted, will return a context object used like this:: with self.assertWarns(SomeWarning): @@ -733,8 +738,8 @@ the_warning = cm.warning self.assertEqual(the_warning.some_attribute, 147) """ - context = _AssertWarnsContext(expected_warning, self, callable_obj) - return context.handle('assertWarns', callable_obj, args, kwargs) + context = _AssertWarnsContext(expected_warning, self) + return context.handle('assertWarns', args, kwargs) def assertLogs(self, logger=None, level=None): """Fail unless a log message of level *level* or higher is emitted @@ -1221,26 +1226,23 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegex(self, expected_exception, expected_regex, - callable_obj=_sentinel, *args, **kwargs): + *args, **kwargs): """Asserts that the message in a raised exception matches a regex. Args: expected_exception: Exception class expected to be raised. expected_regex: Regex (re pattern object or string) expected to be found in error message. - callable_obj: Function to be called. + args: Function to be called and extra positional args. + kwargs: Extra kwargs. msg: Optional message used in case of failure. Can only be used when assertRaisesRegex is used as a context manager. - args: Extra args. - kwargs: Extra kwargs. """ - context = _AssertRaisesContext(expected_exception, self, callable_obj, - expected_regex) - - return context.handle('assertRaisesRegex', callable_obj, args, kwargs) + context = _AssertRaisesContext(expected_exception, self, expected_regex) + return context.handle('assertRaisesRegex', args, kwargs) def assertWarnsRegex(self, expected_warning, expected_regex, - callable_obj=_sentinel, *args, **kwargs): + *args, **kwargs): """Asserts that the message in a triggered warning matches a regexp. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression @@ -1250,15 +1252,13 @@ expected_warning: Warning class expected to be triggered. expected_regex: Regex (re pattern object or string) expected to be found in error message. - callable_obj: Function to be called. + args: Function to be called and extra positional args. + kwargs: Extra kwargs. msg: Optional message used in case of failure. Can only be used when assertWarnsRegex is used as a context manager. - args: Extra args. - kwargs: Extra kwargs. """ - context = _AssertWarnsContext(expected_warning, self, callable_obj, - expected_regex) - return context.handle('assertWarnsRegex', callable_obj, args, kwargs) + context = _AssertWarnsContext(expected_warning, self, expected_regex) + return context.handle('assertWarnsRegex', args, kwargs) def assertRegex(self, text, expected_regex, msg=None): """Fail the test unless the text matches the regular expression.""" diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1146,7 +1146,7 @@ with self.assertRaises(self.failureException): self.assertRaises(ExceptionMock, lambda: 0) # Failure when the function is None - with self.assertRaises(TypeError): + with self.assertWarns(DeprecationWarning): self.assertRaises(ExceptionMock, None) # Failure when another exception is raised with self.assertRaises(ExceptionMock): @@ -1172,6 +1172,15 @@ with self.assertRaises(self.failureException): with self.assertRaises(ExceptionMock): pass + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertRaises(ExceptionMock, msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \ + self.assertRaises(AssertionError): + with self.assertRaises(ExceptionMock, foobar=42): + pass # Failure when another exception is raised with self.assertRaises(ExceptionMock): self.assertRaises(ValueError, Stub) @@ -1185,7 +1194,7 @@ self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) - with self.assertRaises(TypeError): + with self.assertWarns(DeprecationWarning): self.assertRaisesRegex(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegex(self): @@ -1197,6 +1206,15 @@ self.failureException, '^Exception not raised by $', self.assertRaisesRegex, Exception, 'x', lambda: None) + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertRaisesRegex(Exception, 'expect', msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \ + self.assertRaises(AssertionError): + with self.assertRaisesRegex(Exception, 'expect', foobar=42): + pass def testAssertRaisesRegexInvalidRegex(self): # Issue 20145. @@ -1255,7 +1273,7 @@ with self.assertRaises(self.failureException): self.assertWarns(RuntimeWarning, lambda: 0) # Failure when the function is None - with self.assertRaises(TypeError): + with self.assertWarns(DeprecationWarning): self.assertWarns(RuntimeWarning, None) # Failure when another warning is triggered with warnings.catch_warnings(): @@ -1295,6 +1313,15 @@ with self.assertRaises(self.failureException): with self.assertWarns(RuntimeWarning): pass + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertWarns(RuntimeWarning, msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \ + self.assertRaises(AssertionError): + with self.assertWarns(RuntimeWarning, foobar=42): + pass # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) @@ -1319,7 +1346,7 @@ self.assertWarnsRegex(RuntimeWarning, "o+", lambda: 0) # Failure when the function is None - with self.assertRaises(TypeError): + with self.assertWarns(DeprecationWarning): self.assertWarnsRegex(RuntimeWarning, "o+", None) # Failure when another warning is triggered with warnings.catch_warnings(): @@ -1357,6 +1384,15 @@ with self.assertRaises(self.failureException): with self.assertWarnsRegex(RuntimeWarning, "o+"): pass + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertWarnsRegex(RuntimeWarning, 'o+', msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \ + self.assertRaises(AssertionError): + with self.assertWarnsRegex(RuntimeWarning, 'o+', foobar=42): + pass # Failure when another warning is triggered with warnings.catch_warnings(): # Force default filter (in case tests are run with -We) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -76,7 +76,8 @@ usernames and passwords to UTF8. - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and - assertWarnsRegex() checks are not longer successful if the callable is None. + assertWarnsRegex() checks now emits a deprecation warning when callable is + None or keyword arguments except msg is passed in the context manager mode. - Issue #24018: Add a collections.abc.Generator abstract base class. Contributed by Stefan Behnel. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:33:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:33:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Reverted_issue?= =?utf-8?q?_=2324134_changes=2E?= Message-ID: <20150516133303.39267.23405@psf.io> https://hg.python.org/cpython/rev/0c93868f202e changeset: 96080:0c93868f202e branch: 2.7 parent: 96072:8875d7c6a99d user: Serhiy Storchaka date: Sat May 16 16:21:10 2015 +0300 summary: Reverted issue #24134 changes. files: Lib/unittest/case.py | 12 +++++------- Lib/unittest/test/test_case.py | 5 ----- Misc/NEWS | 2 ++ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -127,8 +127,6 @@ (expected_regexp.pattern, str(exc_value))) return True -def _sentinel(*args, **kwargs): - raise AssertionError('Should never be called') class TestCase(object): """A class whose instances are single test cases. @@ -445,7 +443,7 @@ return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): + def assertRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -453,7 +451,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted, will return a + If called with callableObj omitted or None, will return a context object used like this:: with self.assertRaises(SomeException): @@ -469,7 +467,7 @@ self.assertEqual(the_exception.error_code, 3) """ context = _AssertRaisesContext(excClass, self) - if callableObj is _sentinel: + if callableObj is None: return context with context: callableObj(*args, **kwargs) @@ -975,7 +973,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegexp(self, expected_exception, expected_regexp, - callable_obj=_sentinel, *args, **kwargs): + callable_obj=None, *args, **kwargs): """Asserts that the message in a raised exception matches a regexp. Args: @@ -989,7 +987,7 @@ if expected_regexp is not None: expected_regexp = re.compile(expected_regexp) context = _AssertRaisesContext(expected_exception, self, expected_regexp) - if callable_obj is _sentinel: + if callable_obj is None: return context with context: callable_obj(*args, **kwargs) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -967,9 +967,6 @@ # Failure when no exception is raised with self.assertRaises(self.failureException): self.assertRaises(ExceptionMock, lambda: 0) - # Failure when the function is None - with self.assertRaises(TypeError): - self.assertRaises(ExceptionMock, None) # Failure when another exception is raised with self.assertRaises(ExceptionMock): self.assertRaises(ValueError, Stub) @@ -1008,8 +1005,6 @@ self.assertRaisesRegexp(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegexp(ExceptionMock, 'expect$', Stub) self.assertRaisesRegexp(ExceptionMock, u'expect$', Stub) - with self.assertRaises(TypeError): - self.assertRaisesRegexp(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegexp(self): self.assertRaisesRegexp( diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #24134: Reverted issue #24134 changes. + What's New in Python 2.7.10 release candidate 1? ================================================ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:33:11 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:33:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_release_date=2E?= Message-ID: <20150516133309.32287.91736@psf.io> https://hg.python.org/cpython/rev/ce07e646b76e changeset: 96084:ce07e646b76e user: Serhiy Storchaka date: Sat May 16 16:32:21 2015 +0300 summary: Fixed release date. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.5.0 beta 1? ================================== -Release date: 2015-04-24 +Release date: 2015-05-24 Core and Builtins ----------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:43:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 13:43:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNjM3?= =?utf-8?q?=3A_Showing_a_warning_no_longer_fails_with_UnicodeErrror=2E?= Message-ID: <20150516134320.39241.30087@psf.io> https://hg.python.org/cpython/rev/22e44a7ee89f changeset: 96085:22e44a7ee89f branch: 2.7 parent: 96080:0c93868f202e user: Serhiy Storchaka date: Sat May 16 16:42:18 2015 +0300 summary: Issue #23637: Showing a warning no longer fails with UnicodeErrror. Formatting unicode warning in the file with the path containing non-ascii characters no longer fails with UnicodeErrror. files: Lib/test/test_warnings.py | 57 +++++++++++++++++++++++++++ Lib/warnings.py | 22 +++++++++- Misc/NEWS | 4 + 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -593,6 +593,63 @@ self.assertEqual(expect, self.module.formatwarning(message, category, file_name, line_num, file_line)) + @test_support.requires_unicode + def test_formatwarning_unicode_msg(self): + message = u"msg" + category = Warning + file_name = os.path.splitext(warning_tests.__file__)[0] + '.py' + line_num = 3 + file_line = linecache.getline(file_name, line_num).strip() + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num)) + # Test the 'line' argument. + file_line += " for the win!" + expect = format % (file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + + @test_support.requires_unicode + @unittest.skipUnless(test_support.FS_NONASCII, 'need test_support.FS_NONASCII') + def test_formatwarning_unicode_msg_nonascii_filename(self): + message = u"msg" + category = Warning + unicode_file_name = test_support.FS_NONASCII + u'.py' + file_name = unicode_file_name.encode(sys.getfilesystemencoding()) + line_num = 3 + file_line = 'spam' + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, str(message), + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + message = u"\xb5sg" + expect = format % (unicode_file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + + @test_support.requires_unicode + def test_formatwarning_unicode_msg_nonascii_fileline(self): + message = u"msg" + category = Warning + file_name = 'file.py' + line_num = 3 + file_line = 'sp\xe4m' + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, str(message), + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + message = u"\xb5sg" + expect = format % (file_name, line_num, category.__name__, message, + unicode(file_line, 'latin1')) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + def test_showwarning(self): file_name = os.path.splitext(warning_tests.__file__)[0] + '.py' line_num = 3 diff --git a/Lib/warnings.py b/Lib/warnings.py --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -31,7 +31,7 @@ return try: file.write(formatwarning(message, category, filename, lineno, line)) - except IOError: + except (IOError, UnicodeError): pass # the file (probably stderr) is invalid - this warning gets lost. # Keep a working version around in case the deprecation of the old API is # triggered. @@ -39,11 +39,29 @@ def formatwarning(message, category, filename, lineno, line=None): """Function to format a warning the standard way.""" - s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message) + try: + unicodetype = unicode + except NameError: + unicodetype = () + try: + message = str(message) + except UnicodeEncodeError: + pass + s = "%s: %s: %s\n" % (lineno, category.__name__, message) line = linecache.getline(filename, lineno) if line is None else line if line: line = line.strip() + if isinstance(s, unicodetype) and isinstance(line, str): + line = unicode(line, 'latin1') s += " %s\n" % line + if isinstance(s, unicodetype) and isinstance(filename, str): + enc = sys.getfilesystemencoding() + if enc: + try: + filename = unicode(filename, enc) + except UnicodeDecodeError: + pass + s = "%s:%s" % (filename, s) return s def filterwarnings(action, message="", category=Warning, module="", lineno=0, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Library ------- +- Issue #23637: Showing a warning no longer fails with UnicodeErrror. + Formatting unicode warning in the file with the path containing non-ascii + characters no longer fails with UnicodeErrror. + - Issue #24134: Reverted issue #24134 changes. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 15:45:03 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 16 May 2015 13:45:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_allow_test_node_after_**_i?= =?utf-8?q?n_calls_=28closes_=2324176=29?= Message-ID: <20150516134502.4233.26978@psf.io> https://hg.python.org/cpython/rev/38b2307372bf changeset: 96086:38b2307372bf parent: 96084:ce07e646b76e user: Benjamin Peterson date: Sat May 16 09:44:45 2015 -0400 summary: allow test node after ** in calls (closes #24176) files: Grammar/Grammar | 2 +- Lib/test/test_grammar.py | 1 + Modules/parsermodule.c | 2 +- Python/graminit.c | 12 ++++-------- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -136,7 +136,7 @@ # that precede iterable unpackings are blocked; etc. argument: ( test [comp_for] | test '=' test | - '**' expr | + '**' test | star_expr ) comp_iter: comp_for | comp_if diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -206,6 +206,7 @@ d01(1) d01(*(1,)) d01(**{'a':2}) + d01(**{'a':2} or {}) def d11(a, b=1): pass d11(1) d11(1, 2) diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -2871,7 +2871,7 @@ if (res) { if (TYPE(CHILD(tree, 0)) == DOUBLESTAR) { - res = validate_expr(CHILD(tree, 1)); + res = validate_test(CHILD(tree, 1)); } else if (nch == 1) { res = validate_test_or_star_expr(CHILD(tree, 0)); diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1748,24 +1748,20 @@ }; static arc arcs_78_1[3] = { {164, 3}, - {31, 4}, + {31, 2}, {0, 1}, }; static arc arcs_78_2[1] = { - {107, 3}, + {26, 3}, }; static arc arcs_78_3[1] = { {0, 3}, }; -static arc arcs_78_4[1] = { - {26, 3}, -}; -static state states_78[5] = { +static state states_78[4] = { {3, arcs_78_0}, {3, arcs_78_1}, {1, arcs_78_2}, {1, arcs_78_3}, - {1, arcs_78_4}, }; static arc arcs_79_0[2] = { {164, 1}, @@ -2021,7 +2017,7 @@ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"}, {333, "arglist", 0, 3, states_77, "\000\040\200\000\006\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, - {334, "argument", 0, 5, states_78, + {334, "argument", 0, 4, states_78, "\000\040\200\000\006\000\000\000\000\000\004\000\000\000\010\001\000\140\110\224\017\000"}, {335, "comp_iter", 0, 2, states_79, "\000\000\000\000\000\000\000\000\000\000\000\000\021\000\000\000\000\000\000\000\000\000"}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 16:10:28 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 16 May 2015 14:10:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24208=3A_Fix_tests_-?= =?utf-8?q?-_don=27t_create_a_tempdir_in_=5F=5Finit=5F=5F=2E?= Message-ID: <20150516141026.44675.78231@psf.io> https://hg.python.org/cpython/rev/08829230079b changeset: 96087:08829230079b user: Yury Selivanov date: Sat May 16 10:10:21 2015 -0400 summary: Issue 24208: Fix tests -- don't create a tempdir in __init__. files: Lib/test/test_inspect.py | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -288,9 +288,7 @@ # Subclasses must override. fodderModule = None - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) - + def setUp(self): with open(inspect.getsourcefile(self.fodderModule)) as fp: self.source = fp.read() @@ -571,7 +569,7 @@ self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) class TestNoEOL(GetSourceBase): - def __init__(self, *args, **kwargs): + def setUp(self): self.tempdir = TESTFN + '_dir' os.mkdir(self.tempdir) with open(os.path.join(self.tempdir, @@ -580,7 +578,7 @@ with DirsOnSysPath(self.tempdir): import inspect_fodder3 as mod3 self.fodderModule = mod3 - GetSourceBase.__init__(self, *args, **kwargs) + super().setUp() def tearDown(self): shutil.rmtree(self.tempdir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 16:13:24 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 14:13:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMDE0?= =?utf-8?q?=3A_array=2Earray=28=29_now_accepts_unicode_typecodes=2E__Based?= =?utf-8?q?_on_patch_by?= Message-ID: <20150516141323.39247.80779@psf.io> https://hg.python.org/cpython/rev/7d60cb6c33cf changeset: 96088:7d60cb6c33cf branch: 2.7 parent: 96085:22e44a7ee89f user: Serhiy Storchaka date: Sat May 16 17:11:41 2015 +0300 summary: Issue #20014: array.array() now accepts unicode typecodes. Based on patch by Vajrasky Kok. files: Lib/test/test_array.py | 21 +++++++++++++++++++++ Misc/NEWS | 3 +++ Modules/arraymodule.c | 18 +++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -26,7 +26,17 @@ self.assertRaises(TypeError, array.array) self.assertRaises(TypeError, array.array, spam=42) self.assertRaises(TypeError, array.array, 'xx') + self.assertRaises(TypeError, array.array, '') + self.assertRaises(TypeError, array.array, 1) self.assertRaises(ValueError, array.array, 'x') + self.assertRaises(ValueError, array.array, '\x80') + + @test_support.requires_unicode + def test_unicode_constructor(self): + self.assertRaises(TypeError, array.array, u'xx') + self.assertRaises(TypeError, array.array, u'') + self.assertRaises(ValueError, array.array, u'x') + self.assertRaises(ValueError, array.array, u'\x80') tests.append(BadConstructorTest) @@ -1039,6 +1049,17 @@ minitemsize = 4 tests.append(UnsignedLongTest) + + at test_support.requires_unicode +class UnicodeTypecodeTest(unittest.TestCase): + def test_unicode_typecode(self): + for typecode in typecodes: + a = array.array(unicode(typecode)) + self.assertEqual(a.typecode, typecode) + self.assertIs(type(a.typecode), str) +tests.append(UnicodeTypecodeTest) + + class FPTest(NumberTest): example = [-42.0, 0, 42, 1e5, -1e10] smallerexample = [-42.0, 0, 42, 1e5, -2e10] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #20014: array.array() now accepts unicode typecodes. Based on patch by + Vajrasky Kok. + - Issue #23637: Showing a warning no longer fails with UnicodeErrror. Formatting unicode warning in the file with the path containing non-ascii characters no longer fails with UnicodeErrror. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1928,16 +1928,28 @@ static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - char c; - PyObject *initial = NULL, *it = NULL; + int c = -1; + PyObject *initial = NULL, *it = NULL, *typecode = NULL; struct arraydescr *descr; if (type == &Arraytype && !_PyArg_NoKeywords("array.array()", kwds)) return NULL; - if (!PyArg_ParseTuple(args, "c|O:array", &c, &initial)) + if (!PyArg_ParseTuple(args, "O|O:array", &typecode, &initial)) return NULL; + if (PyString_Check(typecode) && PyString_GET_SIZE(typecode) == 1) + c = (unsigned char)*PyString_AS_STRING(typecode); + else if (PyUnicode_Check(typecode) && PyUnicode_GET_SIZE(typecode) == 1) + c = *PyUnicode_AS_UNICODE(typecode); + else { + PyErr_Format(PyExc_TypeError, + "array() argument 1 or typecode must be char (string or " + "ascii-unicode with length 1), not %s", + Py_TYPE(typecode)->tp_name); + return NULL; + } + if (!(initial == NULL || PyList_Check(initial) || PyString_Check(initial) || PyTuple_Check(initial) || (c == 'u' && PyUnicode_Check(initial)))) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 17:59:14 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 15:59:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1MjY3?= =?utf-8?q?=3A_HTTPConnection=2Erequest=28=29_now_is_compatibile_with_old-?= =?utf-8?q?style?= Message-ID: <20150516155914.26578.82173@psf.io> https://hg.python.org/cpython/rev/c34513c2a894 changeset: 96089:c34513c2a894 branch: 2.7 user: Serhiy Storchaka date: Sat May 16 18:58:41 2015 +0300 summary: Issue #15267: HTTPConnection.request() now is compatibile with old-style classes (such as TemporaryFile). Original patch by Atsuo Ishimoto. files: Lib/httplib.py | 2 +- Lib/test/test_httplib.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -1063,7 +1063,7 @@ elif body is not None: try: thelen = str(len(body)) - except TypeError: + except (TypeError, AttributeError): # If this is a file-like object, try to # fstat its file descriptor try: diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -5,6 +5,7 @@ import socket import errno import os +import tempfile import unittest TestCase = unittest.TestCase @@ -399,6 +400,22 @@ conn.sock = sock conn.request('GET', '/foo', body) self.assertTrue(sock.data.startswith(expected)) + self.assertIn('def test_send_file', sock.data) + + def test_send_tempfile(self): + expected = ('GET /foo HTTP/1.1\r\nHost: example.com\r\n' + 'Accept-Encoding: identity\r\nContent-Length: 9\r\n\r\n' + 'fake\ndata') + + with tempfile.TemporaryFile() as body: + body.write('fake\ndata') + body.seek(0) + + conn = httplib.HTTPConnection('example.com') + sock = FakeSocket(body) + conn.sock = sock + conn.request('GET', '/foo', body) + self.assertEqual(sock.data, expected) def test_send(self): expected = 'this is a test this is only a test' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #15267: HTTPConnection.request() now is compatibile with old-style + classes (such as TemporaryFile). Original patch by Atsuo Ishimoto. + - Issue #20014: array.array() now accepts unicode typecodes. Based on patch by Vajrasky Kok. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 19:24:45 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 16 May 2015 17:24:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324210=3A_Silence_?= =?utf-8?q?a_PendingDeprecationWarning_warning_in?= Message-ID: <20150516172445.21174.80951@psf.io> https://hg.python.org/cpython/rev/6181146842ba changeset: 96090:6181146842ba parent: 96087:08829230079b user: Berker Peksag date: Sat May 16 20:24:28 2015 +0300 summary: Issue #24210: Silence a PendingDeprecationWarning warning in platform.platform(). files: Lib/platform.py | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -114,6 +114,8 @@ import collections import sys, os, re, subprocess +import warnings + ### Globals & Constants # Determine the platform's /dev/null device @@ -1438,7 +1440,15 @@ elif system in ('Linux',): # Linux based systems - distname, distversion, distid = dist('') + with warnings.catch_warnings(): + # see issue #1322 for more information + warnings.filterwarnings( + 'ignore', + 'dist\(\) and linux_distribution\(\) ' + 'functions are deprecated .*', + PendingDeprecationWarning, + ) + distname, distversion, distid = dist('') if distname and not terse: platform = _platform(system, release, machine, processor, 'with', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 19:45:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 16 May 2015 17:45:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24190=3A_Add_inspect?= =?utf-8?q?=2EBoundArguments=2Eapply=5Fdefaults=28=29_method=2E?= Message-ID: <20150516174524.26568.7464@psf.io> https://hg.python.org/cpython/rev/ea61d8eb8a28 changeset: 96091:ea61d8eb8a28 user: Yury Selivanov date: Sat May 16 13:45:09 2015 -0400 summary: Issue 24190: Add inspect.BoundArguments.apply_defaults() method. files: Doc/library/inspect.rst | 41 +++++++++++++-------------- Doc/whatsnew/3.5.rst | 3 ++ Lib/inspect.py | 30 ++++++++++++++++++++ Lib/test/test_inspect.py | 35 +++++++++++++++++++++++ Misc/NEWS | 3 ++ 5 files changed, 91 insertions(+), 21 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -667,27 +667,8 @@ Arguments for which :meth:`Signature.bind` or :meth:`Signature.bind_partial` relied on a default value are skipped. - However, if needed, it is easy to include them. - - :: - - >>> def foo(a, b=10): - ... pass - - >>> sig = signature(foo) - >>> ba = sig.bind(5) - - >>> ba.args, ba.kwargs - ((5,), {}) - - >>> for param in sig.parameters.values(): - ... if (param.name not in ba.arguments - ... and param.default is not param.empty): - ... ba.arguments[param.name] = param.default - - >>> ba.args, ba.kwargs - ((5, 10), {}) - + However, if needed, use :meth:`BoundArguments.apply_defaults` to add + them. .. attribute:: BoundArguments.args @@ -703,6 +684,24 @@ A reference to the parent :class:`Signature` object. + .. method:: BoundArguments.apply_defaults() + + Set default values for missing arguments. + + For variable-positional arguments (``*args``) the default is an + empty tuple. + + For variable-keyword arguments (``**kwargs``) the default is an + empty dict. + + :: + + >>> def foo(a, b='ham', *args): pass + >>> ba = inspect.signature(foo).bind('spam') + >>> ba.apply_defaults() + >>> ba.arguments + OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())]) + The :attr:`args` and :attr:`kwargs` properties can be used to invoke functions:: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -400,6 +400,9 @@ picklable and hashable. (Contributed by Yury Selivanov in :issue:`20726` and :issue:`20334`.) +* New method :meth:`inspect.BoundArguments.apply_defaults`. (Contributed + by Yury Selivanov in :issue:`24190`.) + * New class method :meth:`inspect.Signature.from_callable`, which makes subclassing of :class:`~inspect.Signature` easier. (Contributed by Yury Selivanov and Eric Snow in :issue:`17373`.) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2443,6 +2443,36 @@ return kwargs + def apply_defaults(self): + """Set default values for missing arguments. + + For variable-positional arguments (*args) the default is an + empty tuple. + + For variable-keyword arguments (**kwargs) the default is an + empty dict. + """ + arguments = self.arguments + if not arguments: + return + new_arguments = [] + for name, param in self._signature.parameters.items(): + try: + new_arguments.append((name, arguments[name])) + except KeyError: + if param.default is not _empty: + val = param.default + elif param.kind is _VAR_POSITIONAL: + val = () + elif param.kind is _VAR_KEYWORD: + val = {} + else: + # This BoundArguments was likely produced by + # Signature.bind_partial(). + continue + new_arguments.append((name, val)) + self.arguments = OrderedDict(new_arguments) + def __eq__(self, other): return (self is other or (issubclass(other.__class__, BoundArguments) and diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3153,6 +3153,41 @@ ba = sig.bind(20, 30, z={}) self.assertRegex(repr(ba), r'') + def test_signature_bound_arguments_apply_defaults(self): + def foo(a, b=1, *args, c:1={}, **kw): pass + sig = inspect.signature(foo) + + ba = sig.bind(20) + ba.apply_defaults() + self.assertEqual( + list(ba.arguments.items()), + [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})]) + + # Make sure that we preserve the order: + # i.e. 'c' should be *before* 'kw'. + ba = sig.bind(10, 20, 30, d=1) + ba.apply_defaults() + self.assertEqual( + list(ba.arguments.items()), + [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})]) + + # Make sure that BoundArguments produced by bind_partial() + # are supported. + def foo(a, b): pass + sig = inspect.signature(foo) + ba = sig.bind_partial(20) + ba.apply_defaults() + self.assertEqual( + list(ba.arguments.items()), + [('a', 20)]) + + # Test no args + def foo(): pass + sig = inspect.signature(foo) + ba = sig.bind() + ba.apply_defaults() + self.assertEqual(list(ba.arguments.items()), []) + class TestSignaturePrivateHelpers(unittest.TestCase): def test_signature_get_bound_param(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -131,6 +131,9 @@ - Issue 22547: Implement informative __repr__ for inspect.BoundArguments. Contributed by Yury Selivanov. +- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method. + Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 19:58:29 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 May 2015 17:58:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2322027=3A_Add_RFC6531_su?= =?utf-8?q?pport_to_smtplib=2E?= Message-ID: <20150516175829.44681.87950@psf.io> https://hg.python.org/cpython/rev/6b0e4c87bf9e changeset: 96092:6b0e4c87bf9e user: R David Murray date: Sat May 16 13:58:14 2015 -0400 summary: #22027: Add RFC6531 support to smtplib. Initial patch by Milan Oberkirch. files: Doc/library/smtplib.rst | 35 +++++++- Doc/whatsnew/3.5.rst | 3 + Lib/smtplib.py | 42 ++++++++- Lib/test/test_smtplib.py | 119 +++++++++++++++++++++++++++ Misc/NEWS | 2 + 5 files changed, 194 insertions(+), 7 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -61,6 +61,10 @@ .. versionchanged:: 3.3 source_address argument was added. + .. versionadded:: 3.5 + The SMTPUTF8 extension (:rfc:`6531`) is now supported. + + .. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, \ certfile=None [, timeout], context=None, \ source_address=None) @@ -161,6 +165,13 @@ The server refused our ``HELO`` message. +.. exception:: SMTPNotSupportedError + + The command or option attempted is not supported by the server. + + .. versionadded:: 3.5 + + .. exception:: SMTPAuthenticationError SMTP authentication went wrong. Most probably the server didn't accept the @@ -291,6 +302,9 @@ :exc:`SMTPAuthenticationError` The server didn't accept the username/password combination. + :exc:`SMTPNotSupportedError` + The ``AUTH`` command is not supported by the server. + :exc:`SMTPException` No suitable authentication method was found. @@ -298,6 +312,9 @@ turn if they are advertised as supported by the server (see :meth:`auth` for a list of supported authentication methods). + .. versionchanged:: 3.5 + :exc:`SMTPNotSupportedError` may be raised. + .. method:: SMTP.auth(mechanism, authobject) @@ -349,7 +366,7 @@ :exc:`SMTPHeloError` The server didn't reply properly to the ``HELO`` greeting. - :exc:`SMTPException` + :exc:`SMTPNotSupportedError` The server does not support the STARTTLS extension. :exc:`RuntimeError` @@ -363,6 +380,11 @@ :attr:`SSLContext.check_hostname` and *Server Name Indicator* (see :data:`~ssl.HAS_SNI`). + .. versionchanged:: 3.5 + The error raised for lack of STARTTLS support is now the + :exc:`SMTPNotSupportedError` subclass instead of the base + :exc:`SMTPException`. + .. method:: SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) @@ -399,6 +421,9 @@ recipient that was refused. Each entry contains a tuple of the SMTP error code and the accompanying error message sent by the server. + If ``SMTPUTF8`` is included in *mail_options*, and the server supports it, + *from_addr* and *to_addr* may contain non-ASCII characters. + This method may raise the following exceptions: :exc:`SMTPRecipientsRefused` @@ -417,12 +442,20 @@ The server replied with an unexpected error code (other than a refusal of a recipient). + :exc:`SMTPNotSupportedError` + ``SMTPUTF8`` was given in the *mail_options* but is not supported by the + server. + Unless otherwise noted, the connection will be open even after an exception is raised. .. versionchanged:: 3.2 *msg* may be a byte string. + .. versionchanged:: 3.5 + ``SMTPUTF8`` support added, and :exc:`SMTPNotSupportedError` may be + raised if ``SMTPUTF8`` is specified but the server does not support it. + .. method:: SMTP.send_message(msg, from_addr=None, to_addrs=None, \ mail_options=[], rcpt_options=[]) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -527,6 +527,9 @@ :class:`smtplib.SMTP`. (Contributed by Gavin Chappell and Maciej Szulik in :issue:`16914`.) +* :mod:`smtplib` now support :rfc:`6531` (SMTPUTF8). (Contributed by + Milan Oberkirch and R. David Murray in :issue:`22027`.) + sndhdr ------ diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -71,6 +71,13 @@ class SMTPException(OSError): """Base class for all exceptions raised by this module.""" +class SMTPNotSupportedError(SMTPException): + """The command or option is not supported by the SMTP server. + + This exception is raised when an attempt is made to run a command or a + command with an option which is not supported by the server. + """ + class SMTPServerDisconnected(SMTPException): """Not connected to any SMTP server. @@ -237,6 +244,7 @@ self._host = host self.timeout = timeout self.esmtp_features = {} + self.command_encoding = 'ascii' self.source_address = source_address if host: @@ -337,7 +345,10 @@ self._print_debug('send:', repr(s)) if hasattr(self, 'sock') and self.sock: if isinstance(s, str): - s = s.encode("ascii") + # send is used by the 'data' command, where command_encoding + # should not be used, but 'data' needs to convert the string to + # binary itself anyway, so that's not a problem. + s = s.encode(self.command_encoding) try: self.sock.sendall(s) except OSError: @@ -482,6 +493,7 @@ def rset(self): """SMTP 'rset' command -- resets session.""" + self.command_encoding = 'ascii' return self.docmd("rset") def _rset(self): @@ -501,9 +513,22 @@ return self.docmd("noop") def mail(self, sender, options=[]): - """SMTP 'mail' command -- begins mail xfer session.""" + """SMTP 'mail' command -- begins mail xfer session. + + This method may raise the following exceptions: + + SMTPNotSupportedError The options parameter includes 'SMTPUTF8' + but the SMTPUTF8 extension is not supported by + the server. + """ optionlist = '' if options and self.does_esmtp: + if any(x.lower()=='smtputf8' for x in options): + if self.has_extn('smtputf8'): + self.command_encoding = 'utf-8' + else: + raise SMTPNotSupportedError( + 'SMTPUTF8 not supported by server') optionlist = ' ' + ' '.join(options) self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist)) return self.getreply() @@ -642,13 +667,16 @@ the helo greeting. SMTPAuthenticationError The server didn't accept the username/ password combination. + SMTPNotSupportedError The AUTH command is not supported by the + server. SMTPException No suitable authentication method was found. """ self.ehlo_or_helo_if_needed() if not self.has_extn("auth"): - raise SMTPException("SMTP AUTH extension not supported by server.") + raise SMTPNotSupportedError( + "SMTP AUTH extension not supported by server.") # Authentication methods the server claims to support advertised_authlist = self.esmtp_features["auth"].split() @@ -700,7 +728,8 @@ """ self.ehlo_or_helo_if_needed() if not self.has_extn("starttls"): - raise SMTPException("STARTTLS extension not supported by server.") + raise SMTPNotSupportedError( + "STARTTLS extension not supported by server.") (resp, reply) = self.docmd("STARTTLS") if resp == 220: if not _have_ssl: @@ -765,6 +794,9 @@ SMTPDataError The server replied with an unexpected error code (other than a refusal of a recipient). + SMTPNotSupportedError The mail_options parameter includes 'SMTPUTF8' + but the SMTPUTF8 extension is not supported by + the server. Note: the connection will be open even after an exception is raised. @@ -793,8 +825,6 @@ if isinstance(msg, str): msg = _fix_eols(msg).encode('ascii') if self.does_esmtp: - # Hmmm? what's this? -ddm - # self.esmtp_features['7bit']="" if self.has_extn('size'): esmtp_opts.append("size=%d" % len(msg)) for option in mail_options: diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -977,6 +977,125 @@ self.assertIsNone(smtp.sock) self.assertEqual(self.serv._SMTPchannel.rcpt_count, 0) + def test_smtputf8_NotSupportedError_if_no_server_support(self): + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + smtp.ehlo() + self.assertTrue(smtp.does_esmtp) + self.assertFalse(smtp.has_extn('smtputf8')) + self.assertRaises( + smtplib.SMTPNotSupportedError, + smtp.sendmail, + 'John', 'Sally', '', mail_options=['BODY=8BITMIME', 'SMTPUTF8']) + self.assertRaises( + smtplib.SMTPNotSupportedError, + smtp.mail, 'John', options=['BODY=8BITMIME', 'SMTPUTF8']) + + def test_send_unicode_without_SMTPUTF8(self): + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + self.assertRaises(UnicodeEncodeError, smtp.sendmail, 'Alice', 'B?b', '') + self.assertRaises(UnicodeEncodeError, smtp.mail, '?lice') + + +class SimSMTPUTF8Server(SimSMTPServer): + + def __init__(self, *args, **kw): + # The base SMTP server turns these on automatically, but our test + # server is set up to munge the EHLO response, so we need to provide + # them as well. And yes, the call is to SMTPServer not SimSMTPServer. + self._extra_features = ['SMTPUTF8', '8BITMIME'] + smtpd.SMTPServer.__init__(self, *args, **kw) + + def handle_accepted(self, conn, addr): + self._SMTPchannel = self.channel_class( + self._extra_features, self, conn, addr, + decode_data=self._decode_data, + enable_SMTPUTF8=self.enable_SMTPUTF8, + ) + + def process_message(self, peer, mailfrom, rcpttos, data, mail_options=None, + rcpt_options=None): + self.last_peer = peer + self.last_mailfrom = mailfrom + self.last_rcpttos = rcpttos + self.last_message = data + self.last_mail_options = mail_options + self.last_rcpt_options = rcpt_options + + + at unittest.skipUnless(threading, 'Threading required for this test.') +class SMTPUTF8SimTests(unittest.TestCase): + + def setUp(self): + self.real_getfqdn = socket.getfqdn + socket.getfqdn = mock_socket.getfqdn + self.serv_evt = threading.Event() + self.client_evt = threading.Event() + # Pick a random unused port by passing 0 for the port number + self.serv = SimSMTPUTF8Server((HOST, 0), ('nowhere', -1), + decode_data=False, + enable_SMTPUTF8=True) + # Keep a note of what port was assigned + self.port = self.serv.socket.getsockname()[1] + serv_args = (self.serv, self.serv_evt, self.client_evt) + self.thread = threading.Thread(target=debugging_server, args=serv_args) + self.thread.start() + + # wait until server thread has assigned a port number + self.serv_evt.wait() + self.serv_evt.clear() + + def tearDown(self): + socket.getfqdn = self.real_getfqdn + # indicate that the client is finished + self.client_evt.set() + # wait for the server thread to terminate + self.serv_evt.wait() + self.thread.join() + + def test_test_server_supports_extensions(self): + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + smtp.ehlo() + self.assertTrue(smtp.does_esmtp) + self.assertTrue(smtp.has_extn('smtputf8')) + + def test_send_unicode_with_SMTPUTF8_via_sendmail(self): + m = '?a test message containing unicode!'.encode('utf-8') + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + smtp.sendmail('J?hn', 'S?lly', m, + mail_options=['BODY=8BITMIME', 'SMTPUTF8']) + self.assertEqual(self.serv.last_mailfrom, 'J?hn') + self.assertEqual(self.serv.last_rcpttos, ['S?lly']) + self.assertEqual(self.serv.last_message, m) + self.assertIn('BODY=8BITMIME', self.serv.last_mail_options) + self.assertIn('SMTPUTF8', self.serv.last_mail_options) + self.assertEqual(self.serv.last_rcpt_options, []) + + def test_send_unicode_with_SMTPUTF8_via_low_level_API(self): + m = '?a test message containing unicode!'.encode('utf-8') + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + smtp.ehlo() + self.assertEqual( + smtp.mail('J?', options=['BODY=8BITMIME', 'SMTPUTF8']), + (250, b'OK')) + self.assertEqual(smtp.rcpt('J?nos'), (250, b'OK')) + self.assertEqual(smtp.data(m), (250, b'OK')) + self.assertEqual(self.serv.last_mailfrom, 'J?') + self.assertEqual(self.serv.last_rcpttos, ['J?nos']) + self.assertEqual(self.serv.last_message, m) + self.assertIn('BODY=8BITMIME', self.serv.last_mail_options) + self.assertIn('SMTPUTF8', self.serv.last_mail_options) + self.assertEqual(self.serv.last_rcpt_options, []) + @support.reap_threads def test_main(verbose=None): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,8 @@ Library ------- +- Issue #22027: smtplib now supports RFC 6531 (SMTPUTF8). + - Issue #23488: Random generator objects now consume 2x less memory on 64-bit. - Issue #1322: platform.dist() and platform.linux_distribution() functions are -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:18:21 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 May 2015 18:18:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2319662=3A_Make_requireme?= =?utf-8?q?nt_to_support_arbitrary_keywords_explicit=2E?= Message-ID: <20150516181821.16308.82393@psf.io> https://hg.python.org/cpython/rev/a7d3074fa888 changeset: 96093:a7d3074fa888 user: R David Murray date: Sat May 16 14:16:33 2015 -0400 summary: #19662: Make requirement to support arbitrary keywords explicit. When not using decode_data=True, smtpd may provide keyword arguments to the process_message user-implemented method. This doc update is intended to make it clear that arbitrary keywords must be supported, so that we can add additional features in the future by just adding keywords to the process_message call. files: Doc/library/smtpd.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst --- a/Doc/library/smtpd.rst +++ b/Doc/library/smtpd.rst @@ -89,6 +89,10 @@ Currently no ``RCPT TO`` options are supported, so for now this will always be an empty list. + Implementations of ``process_message`` should use the ``**kwargs`` + signature to accept arbitrary keword arguments, since future feature + enhancements may add keys to the kwargs dictionary. + Return ``None`` to request a normal ``250 Ok`` response; otherwise return the desired response string in :RFC:`5321` format. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:24:30 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 18:24:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzOTY0?= =?utf-8?q?=3A_Update_idlelib/idle=5Ftest/README=2Etxt=2E_first_patch_by_A?= =?utf-8?q?l_Sweigart=2E?= Message-ID: <20150516182430.26562.67304@psf.io> https://hg.python.org/cpython/rev/19e111891e39 changeset: 96094:19e111891e39 branch: 2.7 parent: 96089:c34513c2a894 user: Terry Jan Reedy date: Sat May 16 14:23:33 2015 -0400 summary: Issue #23964: Update idlelib/idle_test/README.txt. first patch by Al Sweigart. files: Lib/idlelib/idle_test/README.txt | 128 +++++++++++------- 1 files changed, 78 insertions(+), 50 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -1,14 +1,24 @@ README FOR IDLE TESTS IN IDLELIB.IDLE_TEST +0. Quick Start + +Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x. +To run the tests from a command line: + +python -m test.test_idle + +Human-mediated tests were added later in 2.7 and in 3.4. + +python -m idlelib.idle_test.htest + 1. Test Files The idle directory, idlelib, has over 60 xyz.py files. The idle_test -subdirectory should contain a test_xyy.py for each. (For test modules, make -'xyz' lower case, and possibly shorten it.) Each file should start with the -something like the following template, with the blanks after after '.' and 'as', -and before and after '_' filled in. ---- +subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased +even if xyz.py is not. Here is a possible template, with the blanks after after +'.' and 'as', and before and after '_' to be filled in. + import unittest from test.support import requires import idlelib. as @@ -18,33 +28,33 @@ def test_(self): if __name__ == '__main__': - unittest.main(verbosity=2, exit=2) ---- -Idle tests are run with unittest; do not use regrtest's test_main. + unittest.main(verbosity=2) -Once test_xyy is written, the following should go at the end of xyy.py, -with xyz (lowercased) added after 'test_'. ---- +Add the following at the end of xyy.py, with the appropriate name added after +'test_'. Some files already have something like this for htest. If so, insert +the import and unittest.main lines before the htest lines. + if __name__ == "__main__": import unittest unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False) ---- -2. Gui Tests -Gui tests need 'requires' from test.support (test.test_support in 2.7). A -test is a gui test if it creates a Tk root or master object either directly -or indirectly by instantiating a tkinter or idle class. For the benefit of -test processes that either have no graphical environment available or are not -allowed to use it, gui tests must be 'guarded' by "requires('gui')" in a -setUp function or method. This will typically be setUpClass. +2. GUI Tests -To avoid interfering with other gui tests, all gui objects must be destroyed -and deleted by the end of the test. If a widget, such as a Tk root, is created -in a setUpX function, destroy it in the corresponding tearDownX. For module -and class attributes, also delete the widget. ---- +When run as part of the Python test suite, Idle gui tests need to run +test.support.requires('gui') (test.test_support in 2.7). A test is a gui test +if it creates a Tk root or master object either directly or indirectly by +instantiating a tkinter or idle class. For the benefit of test processes that +either have no graphical environment available or are not allowed to use it, gui +tests must be 'guarded' by "requires('gui')" in a setUp function or method. +This will typically be setUpClass. + +To avoid interfering with other gui tests, all gui objects must be destroyed and +deleted by the end of the test. Widgets, such as a Tk root, created in a setUpX +function, should be destroyed in the corresponding tearDownX. Module and class +widget attributes should also be deleted.. + @classmethod def setUpClass(cls): requires('gui') @@ -54,49 +64,55 @@ def tearDownClass(cls): cls.root.destroy() del cls.root ---- -Support.requires('gui') causes the test(s) it guards to be skipped if any of + +Requires('gui') causes the test(s) it guards to be skipped if any of a few conditions are met: - - The tests are being run by regrtest.py, and it was started without - enabling the "gui" resource with the "-u" command line option. + + - The tests are being run by regrtest.py, and it was started without enabling + the "gui" resource with the "-u" command line option. + - The tests are being run on Windows by a service that is not allowed to interact with the graphical environment. + - The tests are being run on Mac OSX in a process that cannot make a window manager connection. + - tkinter.Tk cannot be successfully instantiated for some reason. + - test.support.use_resources has been set by something other than regrtest.py and does not contain "gui". + +Tests of non-gui operations should avoid creating tk widgets. Incidental uses of +tk variables and messageboxes can be replaced by the mock classes in +idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget. -Since non-gui tests always run, but gui tests only sometimes, tests of non-gui -operations should best avoid needing a gui. Methods that make incidental use of -tkinter (tk) variables and messageboxes can do this by using the mock classes in -idle_test/mock_tk.py. There is also a mock text that will handle some uses of the -tk Text widget. +3. Running Unit Tests -3. Running Tests +Assume that xyz.py and test_xyz.py both end with a unittest.main() call. +Running either from an Idle editor runs all tests in the test_xyz file with the +version of Python running Idle. Test output appears in the Shell window. The +'verbosity=2' option lists all test methods in the file, which is appropriate +when developing tests. The 'exit=False' option is needed in xyx.py files when an +htest follows. -Assume that xyz.py and test_xyz.py end with the "if __name__" statements given -above. In Idle, pressing F5 in an editor window with either loaded will run all -tests in the test_xyz file with the version of Python running Idle. The test -report and any tracebacks will appear in the Shell window. The options in these -"if __name__" statements are appropriate for developers running (as opposed to -importing) either of the files during development: verbosity=2 lists all test -methods in the file; exit=False avoids a spurious sys.exit traceback that would -otherwise occur when running in Idle. The following command lines also run -all test methods, including gui tests, in test_xyz.py. (The exceptions are that -idlelib and idlelib.idle start Idle and idlelib.PyShell should (issue 18330).) +The following command lines also run all test methods, including +gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start +Idle and so cannot run tests.) -python -m idlelib.xyz # With the capitalization of the xyz module +python -m idlelib.xyz python -m idlelib.idle_test.test_xyz -To run all idle_test/test_*.py tests, either interactively -('>>>', with unittest imported) or from a command line, use one of the -following. (Notes: in 2.7, 'test ' (with the space) is 'test.regrtest '; -where present, -v and -ugui can be omitted.) +The following runs all idle_test/test_*.py tests interactively. ->>> unittest.main('idlelib.idle_test', verbosity=2, exit=False) +>>> import unittest +>>> unittest.main('idlelib.idle_test', verbosity=2) + +The following run all Idle tests at a command line. Option '-v' is the same as +'verbosity=2'. (For 2.7, replace 'test' in the second line with +'test.regrtest'.) + python -m unittest -v idlelib.idle_test python -m test -v -ugui test_idle python -m test.test_idle @@ -113,3 +129,15 @@ unittest on the command line. python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth + + +4. Human-mediated Tests + +Human-mediated tests are widget tests that cannot be automated but need human +verification. They are contained in idlelib/idle_test/htest.py, which has +instructions. (Some modules need an auxiliary function, identified with # htest +# on the header line.) The set is about complete, though some tests need +improvement. To run all htests, run the htest file from an editor or from the +command line with: + +python -m idlelib.idle_test.htest -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:24:30 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 18:24:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTY0?= =?utf-8?q?=3A_Update_idlelib/idle=5Ftest/README=2Etxt=2E_first_patch_by_A?= =?utf-8?q?l_Sweigart=2E?= Message-ID: <20150516182430.26564.58349@psf.io> https://hg.python.org/cpython/rev/35b84ba2f8b1 changeset: 96095:35b84ba2f8b1 branch: 3.4 parent: 96081:a69a346f0c34 user: Terry Jan Reedy date: Sat May 16 14:23:39 2015 -0400 summary: Issue #23964: Update idlelib/idle_test/README.txt. first patch by Al Sweigart. files: Lib/idlelib/idle_test/README.txt | 128 +++++++++++------- 1 files changed, 78 insertions(+), 50 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -1,14 +1,24 @@ README FOR IDLE TESTS IN IDLELIB.IDLE_TEST +0. Quick Start + +Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x. +To run the tests from a command line: + +python -m test.test_idle + +Human-mediated tests were added later in 2.7 and in 3.4. + +python -m idlelib.idle_test.htest + 1. Test Files The idle directory, idlelib, has over 60 xyz.py files. The idle_test -subdirectory should contain a test_xyy.py for each. (For test modules, make -'xyz' lower case, and possibly shorten it.) Each file should start with the -something like the following template, with the blanks after after '.' and 'as', -and before and after '_' filled in. ---- +subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased +even if xyz.py is not. Here is a possible template, with the blanks after after +'.' and 'as', and before and after '_' to be filled in. + import unittest from test.support import requires import idlelib. as @@ -18,33 +28,33 @@ def test_(self): if __name__ == '__main__': - unittest.main(verbosity=2, exit=2) ---- -Idle tests are run with unittest; do not use regrtest's test_main. + unittest.main(verbosity=2) -Once test_xyy is written, the following should go at the end of xyy.py, -with xyz (lowercased) added after 'test_'. ---- +Add the following at the end of xyy.py, with the appropriate name added after +'test_'. Some files already have something like this for htest. If so, insert +the import and unittest.main lines before the htest lines. + if __name__ == "__main__": import unittest unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False) ---- -2. Gui Tests -Gui tests need 'requires' from test.support (test.test_support in 2.7). A -test is a gui test if it creates a Tk root or master object either directly -or indirectly by instantiating a tkinter or idle class. For the benefit of -test processes that either have no graphical environment available or are not -allowed to use it, gui tests must be 'guarded' by "requires('gui')" in a -setUp function or method. This will typically be setUpClass. +2. GUI Tests -To avoid interfering with other gui tests, all gui objects must be destroyed -and deleted by the end of the test. If a widget, such as a Tk root, is created -in a setUpX function, destroy it in the corresponding tearDownX. For module -and class attributes, also delete the widget. ---- +When run as part of the Python test suite, Idle gui tests need to run +test.support.requires('gui') (test.test_support in 2.7). A test is a gui test +if it creates a Tk root or master object either directly or indirectly by +instantiating a tkinter or idle class. For the benefit of test processes that +either have no graphical environment available or are not allowed to use it, gui +tests must be 'guarded' by "requires('gui')" in a setUp function or method. +This will typically be setUpClass. + +To avoid interfering with other gui tests, all gui objects must be destroyed and +deleted by the end of the test. Widgets, such as a Tk root, created in a setUpX +function, should be destroyed in the corresponding tearDownX. Module and class +widget attributes should also be deleted.. + @classmethod def setUpClass(cls): requires('gui') @@ -54,49 +64,55 @@ def tearDownClass(cls): cls.root.destroy() del cls.root ---- -Support.requires('gui') causes the test(s) it guards to be skipped if any of + +Requires('gui') causes the test(s) it guards to be skipped if any of a few conditions are met: - - The tests are being run by regrtest.py, and it was started without - enabling the "gui" resource with the "-u" command line option. + + - The tests are being run by regrtest.py, and it was started without enabling + the "gui" resource with the "-u" command line option. + - The tests are being run on Windows by a service that is not allowed to interact with the graphical environment. + - The tests are being run on Mac OSX in a process that cannot make a window manager connection. + - tkinter.Tk cannot be successfully instantiated for some reason. + - test.support.use_resources has been set by something other than regrtest.py and does not contain "gui". + +Tests of non-gui operations should avoid creating tk widgets. Incidental uses of +tk variables and messageboxes can be replaced by the mock classes in +idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget. -Since non-gui tests always run, but gui tests only sometimes, tests of non-gui -operations should best avoid needing a gui. Methods that make incidental use of -tkinter (tk) variables and messageboxes can do this by using the mock classes in -idle_test/mock_tk.py. There is also a mock text that will handle some uses of the -tk Text widget. +3. Running Unit Tests -3. Running Tests +Assume that xyz.py and test_xyz.py both end with a unittest.main() call. +Running either from an Idle editor runs all tests in the test_xyz file with the +version of Python running Idle. Test output appears in the Shell window. The +'verbosity=2' option lists all test methods in the file, which is appropriate +when developing tests. The 'exit=False' option is needed in xyx.py files when an +htest follows. -Assume that xyz.py and test_xyz.py end with the "if __name__" statements given -above. In Idle, pressing F5 in an editor window with either loaded will run all -tests in the test_xyz file with the version of Python running Idle. The test -report and any tracebacks will appear in the Shell window. The options in these -"if __name__" statements are appropriate for developers running (as opposed to -importing) either of the files during development: verbosity=2 lists all test -methods in the file; exit=False avoids a spurious sys.exit traceback that would -otherwise occur when running in Idle. The following command lines also run -all test methods, including gui tests, in test_xyz.py. (The exceptions are that -idlelib and idlelib.idle start Idle and idlelib.PyShell should (issue 18330).) +The following command lines also run all test methods, including +gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start +Idle and so cannot run tests.) -python -m idlelib.xyz # With the capitalization of the xyz module +python -m idlelib.xyz python -m idlelib.idle_test.test_xyz -To run all idle_test/test_*.py tests, either interactively -('>>>', with unittest imported) or from a command line, use one of the -following. (Notes: in 2.7, 'test ' (with the space) is 'test.regrtest '; -where present, -v and -ugui can be omitted.) +The following runs all idle_test/test_*.py tests interactively. ->>> unittest.main('idlelib.idle_test', verbosity=2, exit=False) +>>> import unittest +>>> unittest.main('idlelib.idle_test', verbosity=2) + +The following run all Idle tests at a command line. Option '-v' is the same as +'verbosity=2'. (For 2.7, replace 'test' in the second line with +'test.regrtest'.) + python -m unittest -v idlelib.idle_test python -m test -v -ugui test_idle python -m test.test_idle @@ -113,3 +129,15 @@ unittest on the command line. python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth + + +4. Human-mediated Tests + +Human-mediated tests are widget tests that cannot be automated but need human +verification. They are contained in idlelib/idle_test/htest.py, which has +instructions. (Some modules need an auxiliary function, identified with # htest +# on the header line.) The set is about complete, though some tests need +improvement. To run all htests, run the htest file from an editor or from the +command line with: + +python -m idlelib.idle_test.htest -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:24:31 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 18:24:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150516182430.39257.12595@psf.io> https://hg.python.org/cpython/rev/f0c94892ac31 changeset: 96096:f0c94892ac31 parent: 96093:a7d3074fa888 parent: 96095:35b84ba2f8b1 user: Terry Jan Reedy date: Sat May 16 14:24:06 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/idle_test/README.txt | 128 +++++++++++------- 1 files changed, 78 insertions(+), 50 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -1,14 +1,24 @@ README FOR IDLE TESTS IN IDLELIB.IDLE_TEST +0. Quick Start + +Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x. +To run the tests from a command line: + +python -m test.test_idle + +Human-mediated tests were added later in 2.7 and in 3.4. + +python -m idlelib.idle_test.htest + 1. Test Files The idle directory, idlelib, has over 60 xyz.py files. The idle_test -subdirectory should contain a test_xyy.py for each. (For test modules, make -'xyz' lower case, and possibly shorten it.) Each file should start with the -something like the following template, with the blanks after after '.' and 'as', -and before and after '_' filled in. ---- +subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased +even if xyz.py is not. Here is a possible template, with the blanks after after +'.' and 'as', and before and after '_' to be filled in. + import unittest from test.support import requires import idlelib. as @@ -18,33 +28,33 @@ def test_(self): if __name__ == '__main__': - unittest.main(verbosity=2, exit=2) ---- -Idle tests are run with unittest; do not use regrtest's test_main. + unittest.main(verbosity=2) -Once test_xyy is written, the following should go at the end of xyy.py, -with xyz (lowercased) added after 'test_'. ---- +Add the following at the end of xyy.py, with the appropriate name added after +'test_'. Some files already have something like this for htest. If so, insert +the import and unittest.main lines before the htest lines. + if __name__ == "__main__": import unittest unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False) ---- -2. Gui Tests -Gui tests need 'requires' from test.support (test.test_support in 2.7). A -test is a gui test if it creates a Tk root or master object either directly -or indirectly by instantiating a tkinter or idle class. For the benefit of -test processes that either have no graphical environment available or are not -allowed to use it, gui tests must be 'guarded' by "requires('gui')" in a -setUp function or method. This will typically be setUpClass. +2. GUI Tests -To avoid interfering with other gui tests, all gui objects must be destroyed -and deleted by the end of the test. If a widget, such as a Tk root, is created -in a setUpX function, destroy it in the corresponding tearDownX. For module -and class attributes, also delete the widget. ---- +When run as part of the Python test suite, Idle gui tests need to run +test.support.requires('gui') (test.test_support in 2.7). A test is a gui test +if it creates a Tk root or master object either directly or indirectly by +instantiating a tkinter or idle class. For the benefit of test processes that +either have no graphical environment available or are not allowed to use it, gui +tests must be 'guarded' by "requires('gui')" in a setUp function or method. +This will typically be setUpClass. + +To avoid interfering with other gui tests, all gui objects must be destroyed and +deleted by the end of the test. Widgets, such as a Tk root, created in a setUpX +function, should be destroyed in the corresponding tearDownX. Module and class +widget attributes should also be deleted.. + @classmethod def setUpClass(cls): requires('gui') @@ -54,49 +64,55 @@ def tearDownClass(cls): cls.root.destroy() del cls.root ---- -Support.requires('gui') causes the test(s) it guards to be skipped if any of + +Requires('gui') causes the test(s) it guards to be skipped if any of a few conditions are met: - - The tests are being run by regrtest.py, and it was started without - enabling the "gui" resource with the "-u" command line option. + + - The tests are being run by regrtest.py, and it was started without enabling + the "gui" resource with the "-u" command line option. + - The tests are being run on Windows by a service that is not allowed to interact with the graphical environment. + - The tests are being run on Mac OSX in a process that cannot make a window manager connection. + - tkinter.Tk cannot be successfully instantiated for some reason. + - test.support.use_resources has been set by something other than regrtest.py and does not contain "gui". + +Tests of non-gui operations should avoid creating tk widgets. Incidental uses of +tk variables and messageboxes can be replaced by the mock classes in +idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget. -Since non-gui tests always run, but gui tests only sometimes, tests of non-gui -operations should best avoid needing a gui. Methods that make incidental use of -tkinter (tk) variables and messageboxes can do this by using the mock classes in -idle_test/mock_tk.py. There is also a mock text that will handle some uses of the -tk Text widget. +3. Running Unit Tests -3. Running Tests +Assume that xyz.py and test_xyz.py both end with a unittest.main() call. +Running either from an Idle editor runs all tests in the test_xyz file with the +version of Python running Idle. Test output appears in the Shell window. The +'verbosity=2' option lists all test methods in the file, which is appropriate +when developing tests. The 'exit=False' option is needed in xyx.py files when an +htest follows. -Assume that xyz.py and test_xyz.py end with the "if __name__" statements given -above. In Idle, pressing F5 in an editor window with either loaded will run all -tests in the test_xyz file with the version of Python running Idle. The test -report and any tracebacks will appear in the Shell window. The options in these -"if __name__" statements are appropriate for developers running (as opposed to -importing) either of the files during development: verbosity=2 lists all test -methods in the file; exit=False avoids a spurious sys.exit traceback that would -otherwise occur when running in Idle. The following command lines also run -all test methods, including gui tests, in test_xyz.py. (The exceptions are that -idlelib and idlelib.idle start Idle and idlelib.PyShell should (issue 18330).) +The following command lines also run all test methods, including +gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start +Idle and so cannot run tests.) -python -m idlelib.xyz # With the capitalization of the xyz module +python -m idlelib.xyz python -m idlelib.idle_test.test_xyz -To run all idle_test/test_*.py tests, either interactively -('>>>', with unittest imported) or from a command line, use one of the -following. (Notes: in 2.7, 'test ' (with the space) is 'test.regrtest '; -where present, -v and -ugui can be omitted.) +The following runs all idle_test/test_*.py tests interactively. ->>> unittest.main('idlelib.idle_test', verbosity=2, exit=False) +>>> import unittest +>>> unittest.main('idlelib.idle_test', verbosity=2) + +The following run all Idle tests at a command line. Option '-v' is the same as +'verbosity=2'. (For 2.7, replace 'test' in the second line with +'test.regrtest'.) + python -m unittest -v idlelib.idle_test python -m test -v -ugui test_idle python -m test.test_idle @@ -113,3 +129,15 @@ unittest on the command line. python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth + + +4. Human-mediated Tests + +Human-mediated tests are widget tests that cannot be automated but need human +verification. They are contained in idlelib/idle_test/htest.py, which has +instructions. (Some modules need an auxiliary function, identified with # htest +# on the header line.) The set is about complete, though some tests need +improvement. To run all htests, run the htest file from an editor or from the +command line with: + +python -m idlelib.idle_test.htest -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:39:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 18:39:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_tests_fo?= =?utf-8?q?r_more_builtin_types=2E?= Message-ID: <20150516183940.125518.30075@psf.io> https://hg.python.org/cpython/rev/6570e4e9b1f3 changeset: 96097:6570e4e9b1f3 branch: 2.7 parent: 96094:19e111891e39 user: Serhiy Storchaka date: Sat May 16 21:34:56 2015 +0300 summary: Added tests for more builtin types. files: Lib/test/test_pprint.py | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -56,6 +56,7 @@ # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, uni("yaddayadda"), + bytearray(b"ghi"), True, False, None, self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -125,21 +126,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0L, 0+0j, 0.0, "", uni(""), + for simple in (0, 0L, 0+0j, 0.0, "", uni(""), bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6L, -6-6j, -1.5, "x", uni("x"), (3,), [3], {3: 6}, + -6, -6L, -6-6j, -1.5, "x", uni("x"), bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:39:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 18:39:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Added_tests_fo?= =?utf-8?q?r_more_builtin_types=2E?= Message-ID: <20150516183940.44691.21736@psf.io> https://hg.python.org/cpython/rev/955dffec3d94 changeset: 96098:955dffec3d94 branch: 3.4 parent: 96095:35b84ba2f8b1 user: Serhiy Storchaka date: Sat May 16 21:35:24 2015 +0300 summary: Added tests for more builtin types. Made test_pprint discoverable. files: Lib/test/test_pprint.py | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -58,7 +58,8 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", + bytearray(b"ghi"), True, False, None, self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -128,21 +129,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", + for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -597,9 +600,5 @@ self, object, context, maxlevels, level) -def test_main(): - test.support.run_unittest(QueryTestCase) - - if __name__ == "__main__": - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:39:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 18:39:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Added_tests_for_more_builtin_types=2E?= Message-ID: <20150516183940.21146.77232@psf.io> https://hg.python.org/cpython/rev/7b350f712c0e changeset: 96099:7b350f712c0e parent: 96096:f0c94892ac31 parent: 96098:955dffec3d94 user: Serhiy Storchaka date: Sat May 16 21:35:56 2015 +0300 summary: Added tests for more builtin types. Made test_pprint discoverable. files: Lib/test/test_pprint.py | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -91,7 +91,8 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", + bytearray(b"ghi"), True, False, None, self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -161,21 +162,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", + for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -1005,9 +1008,5 @@ self, object, context, maxlevels, level) -def test_main(): - test.support.run_unittest(QueryTestCase) - - if __name__ == "__main__": - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 20:39:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 18:39:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2318682=3A_Optimize?= =?utf-8?q?d_pprint_functions_for_builtin_scalar_types=2E?= Message-ID: <20150516183940.26580.30732@psf.io> https://hg.python.org/cpython/rev/c77a42c234d6 changeset: 96100:c77a42c234d6 user: Serhiy Storchaka date: Sat May 16 21:38:05 2015 +0300 summary: Issue #18682: Optimized pprint functions for builtin scalar types. files: Lib/pprint.py | 22 ++++------------------ Misc/NEWS | 2 ++ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Lib/pprint.py b/Lib/pprint.py --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -489,24 +489,8 @@ def _safe_repr(object, context, maxlevels, level): typ = type(object) - if typ is str: - if 'locale' not in _sys.modules: - return repr(object), True, False - if "'" in object and '"' not in object: - closure = '"' - quotes = {'"': '\\"'} - else: - closure = "'" - quotes = {"'": "\\'"} - qget = quotes.get - sio = _StringIO() - write = sio.write - for char in object: - if char.isalpha(): - write(char) - else: - write(qget(char, repr(char)[1:-1])) - return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False + if typ in _builtin_scalars: + return repr(object), True, False r = getattr(typ, "__repr__", None) if issubclass(typ, dict) and r is dict.__repr__: @@ -571,6 +555,8 @@ rep = repr(object) return rep, (rep and not rep.startswith('<')), False +_builtin_scalars = frozenset({str, bytes, bytearray, int, float, complex, + bool, type(None)}) def _recursion(object): return ("" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,8 @@ Library ------- +- Issue #18682: Optimized pprint functions for builtin scalar types. + - Issue #22027: smtplib now supports RFC 6531 (SMTPUTF8). - Issue #23488: Random generator objects now consume 2x less memory on 64-bit. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 21:06:36 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 May 2015 19:06:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2321804=3A_Add_RFC_6856_?= =?utf-8?q?=28UTF8=29_support_to_poplib=2E?= Message-ID: <20150516190636.26566.73233@psf.io> https://hg.python.org/cpython/rev/6ea762200e27 changeset: 96101:6ea762200e27 user: R David Murray date: Sat May 16 15:05:53 2015 -0400 summary: #21804: Add RFC 6856 (UTF8) support to poplib. Patch by Milan Oberkirch. files: Doc/library/poplib.rst | 9 +++++++++ Doc/whatsnew/3.5.rst | 7 +++++++ Lib/poplib.py | 7 +++++++ Lib/test/test_poplib.py | 16 ++++++++++++++++ Misc/NEWS | 2 ++ 5 files changed, 41 insertions(+), 0 deletions(-) diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -194,6 +194,15 @@ the unique id for that message in the form ``'response mesgnum uid``, otherwise result is list ``(response, ['mesgnum uid', ...], octets)``. + +.. method:: POP3.utf8() + + Try to switch to UTF-8 mode. Returns the server response if sucessful, + raises :class:`error_proto` if not. Specified in :RFC:`6856`. + + .. versionadded:: 3.5 + + .. method:: POP3.stls(context=None) Start a TLS session on the active connection as specified in :rfc:`2595`. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -452,6 +452,13 @@ classes) now are supported with pickle protocols < 4. (Contributed by Serhiy Storchaka in :issue:`23611`.) +poplib +------ + +* A new command :meth:`~poplib.POP3.utf8` enables :rfc:`6856` + (internationalized email) support if the POP server supports it. (Contributed + by Milan OberKirch in :issue:`21804`.) + re -- diff --git a/Lib/poplib.py b/Lib/poplib.py --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -71,6 +71,7 @@ UIDL [msg] uidl(msg = None) CAPA capa() STLS stls() + UTF8 utf8() Raises one exception: 'error_proto'. @@ -348,6 +349,12 @@ return self._longcmd('UIDL') + def utf8(self): + """Try to enter UTF-8 mode (see RFC 6856). Returns server response. + """ + return self._shortcmd('UTF8') + + def capa(self): """Return server capabilities (RFC 2449) as a dictionary >>> c=poplib.POP3('localhost') diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -44,6 +44,7 @@ class DummyPOP3Handler(asynchat.async_chat): CAPAS = {'UIDL': [], 'IMPLEMENTATION': ['python-testlib-pop-server']} + enable_UTF8 = False def __init__(self, conn): asynchat.async_chat.__init__(self, conn) @@ -142,6 +143,11 @@ self.push(' '.join(_ln)) self.push('.') + def cmd_utf8(self, arg): + self.push('+OK I know RFC6856' + if self.enable_UTF8 + else '-ERR What is UTF8?!') + if SUPPORTS_SSL: def cmd_stls(self, arg): @@ -309,6 +315,16 @@ self.client.uidl() self.client.uidl('foo') + def test_utf8_raises_if_unsupported(self): + self.server.handler.enable_UTF8 = False + self.assertRaises(poplib.error_proto, self.client.utf8) + + def test_utf8(self): + self.server.handler.enable_UTF8 = True + expected = b'+OK I know RFC6856' + result = self.client.utf8() + self.assertEqual(result, expected) + def test_capa(self): capa = self.client.capa() self.assertTrue('IMPLEMENTATION' in capa.keys()) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,8 @@ Library ------- +- Issue #21804: poplib now supports RFC 6856 (UTF8). + - Issue #18682: Optimized pprint functions for builtin scalar types. - Issue #22027: smtplib now supports RFC 6531 (SMTPUTF8). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 21:13:47 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 19:13:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316314=3A_Added_su?= =?utf-8?q?pport_for_the_LZMA_compression_in_distutils=2E?= Message-ID: <20150516191347.16312.55429@psf.io> https://hg.python.org/cpython/rev/09bd552999bf changeset: 96102:09bd552999bf user: Serhiy Storchaka date: Sat May 16 22:13:27 2015 +0300 summary: Issue #16314: Added support for the LZMA compression in distutils. files: Doc/distutils/apiref.rst | 32 +- Doc/distutils/builtdist.rst | 45 +- Doc/distutils/sourcedist.rst | 8 +- Doc/whatsnew/3.5.rst | 3 + Lib/distutils/archive_util.py | 21 +- Lib/distutils/command/bdist.py | 3 +- Lib/distutils/command/bdist_dumb.py | 3 +- Lib/distutils/tests/test_archive_util.py | 154 +++++++--- Lib/distutils/tests/test_bdist.py | 2 +- Misc/NEWS | 2 + 10 files changed, 180 insertions(+), 93 deletions(-) diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -868,23 +868,31 @@ Create an archive file (eg. ``zip`` or ``tar``). *base_name* is the name of the file to create, minus any format-specific extension; *format* is the - archive format: one of ``zip``, ``tar``, ``ztar``, or ``gztar``. *root_dir* is - a directory that will be the root directory of the archive; ie. we typically - ``chdir`` into *root_dir* before creating the archive. *base_dir* is the - directory where we start archiving from; ie. *base_dir* will be the common - prefix of all files and directories in the archive. *root_dir* and *base_dir* - both default to the current directory. Returns the name of the archive file. + archive format: one of ``zip``, ``tar``, ``gztar``, ``bztar``, ``xztar``, or + ``ztar``. *root_dir* is a directory that will be the root directory of the + archive; ie. we typically ``chdir`` into *root_dir* before creating the + archive. *base_dir* is the directory where we start archiving from; ie. + *base_dir* will be the common prefix of all files and directories in the + archive. *root_dir* and *base_dir* both default to the current directory. + Returns the name of the archive file. + + .. versionchanged: 3.5 + Added support for the ``xztar`` format. .. function:: make_tarball(base_name, base_dir[, compress='gzip', verbose=0, dry_run=0]) 'Create an (optional compressed) archive as a tar file from all files in and - under *base_dir*. *compress* must be ``'gzip'`` (the default), ``'compress'``, - ``'bzip2'``, or ``None``. Both :program:`tar` and the compression utility named - by *compress* must be on the default program search path, so this is probably - Unix-specific. The output tar file will be named :file:`base_dir.tar`, - possibly plus the appropriate compression extension (:file:`.gz`, :file:`.bz2` - or :file:`.Z`). Return the output filename. + under *base_dir*. *compress* must be ``'gzip'`` (the default), + ``'bzip2'``, ``'xz'``, ``'compress'``, or ``None``. For the ``'compress'`` + method the compression utility named by :program:`compress` must be on the + default program search path, so this is probably Unix-specific. The output + tar file will be named :file:`base_dir.tar`, possibly plus the appropriate + compression extension (``.gz``, ``.bz2``, ``.xz`` or ``.Z``). Return the + output filename. + + .. versionchanged: 3.5 + Added support for the ``xz`` compression. .. function:: make_zipfile(base_name, base_dir[, verbose=0, dry_run=0]) diff --git a/Doc/distutils/builtdist.rst b/Doc/distutils/builtdist.rst --- a/Doc/distutils/builtdist.rst +++ b/Doc/distutils/builtdist.rst @@ -72,13 +72,19 @@ +-------------+------------------------------+---------+ | Format | Description | Notes | +=============+==============================+=========+ -| ``gztar`` | gzipped tar file | (1),(3) | +| ``gztar`` | gzipped tar file | \(1) | | | (:file:`.tar.gz`) | | +-------------+------------------------------+---------+ +| ``bztar`` | bzipped tar file | | +| | (:file:`.tar.bz2`) | | ++-------------+------------------------------+---------+ +| ``xztar`` | xzipped tar file | | +| | (:file:`.tar.xz`) | | ++-------------+------------------------------+---------+ | ``ztar`` | compressed tar file | \(3) | | | (:file:`.tar.Z`) | | +-------------+------------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | \(3) | +| ``tar`` | tar file (:file:`.tar`) | | +-------------+------------------------------+---------+ | ``zip`` | zip file (:file:`.zip`) | (2),(4) | +-------------+------------------------------+---------+ @@ -94,6 +100,9 @@ | ``msi`` | Microsoft Installer. | | +-------------+------------------------------+---------+ +.. versionchanged: 3.5 + Added support for the ``xztar`` format. + Notes: @@ -104,8 +113,7 @@ default on Windows (3) - requires external utilities: :program:`tar` and possibly one of :program:`gzip`, - :program:`bzip2`, or :program:`compress` + requires external :program:`compress` utility. (4) requires either external :program:`zip` utility or :mod:`zipfile` module (part @@ -119,21 +127,22 @@ option; you can also use the command that directly implements the format you're interested in. Some of these :command:`bdist` "sub-commands" actually generate several similar formats; for instance, the :command:`bdist_dumb` command -generates all the "dumb" archive formats (``tar``, ``ztar``, ``gztar``, and -``zip``), and :command:`bdist_rpm` generates both binary and source RPMs. The -:command:`bdist` sub-commands, and the formats generated by each, are: +generates all the "dumb" archive formats (``tar``, ``gztar``, ``bztar``, +``xztar``, ``ztar``, and ``zip``), and :command:`bdist_rpm` generates both +binary and source RPMs. The :command:`bdist` sub-commands, and the formats +generated by each, are: -+--------------------------+-----------------------+ -| Command | Formats | -+==========================+=======================+ -| :command:`bdist_dumb` | tar, ztar, gztar, zip | -+--------------------------+-----------------------+ -| :command:`bdist_rpm` | rpm, srpm | -+--------------------------+-----------------------+ -| :command:`bdist_wininst` | wininst | -+--------------------------+-----------------------+ -| :command:`bdist_msi` | msi | -+--------------------------+-----------------------+ ++--------------------------+-------------------------------------+ +| Command | Formats | ++==========================+=====================================+ +| :command:`bdist_dumb` | tar, gztar, bztar, xztar, ztar, zip | ++--------------------------+-------------------------------------+ +| :command:`bdist_rpm` | rpm, srpm | ++--------------------------+-------------------------------------+ +| :command:`bdist_wininst` | wininst | ++--------------------------+-------------------------------------+ +| :command:`bdist_msi` | msi | ++--------------------------+-------------------------------------+ The following sections give details on the individual :command:`bdist_\*` commands. diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -32,12 +32,18 @@ | ``bztar`` | bzip2'ed tar file | | | | (:file:`.tar.bz2`) | | +-----------+-------------------------+---------+ +| ``xztar`` | xz'ed tar file | | +| | (:file:`.tar.xz`) | | ++-----------+-------------------------+---------+ | ``ztar`` | compressed tar file | \(4) | | | (:file:`.tar.Z`) | | +-----------+-------------------------+---------+ | ``tar`` | tar file (:file:`.tar`) | | +-----------+-------------------------+---------+ +.. versionchanged: 3.5 + Added support for the ``xztar`` format. + Notes: (1) @@ -54,7 +60,7 @@ requires the :program:`compress` program. Notice that this format is now pending for deprecation and will be removed in the future versions of Python. -When using any ``tar`` format (``gztar``, ``bztar``, ``ztar`` or +When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or ``tar``), under Unix you can specify the ``owner`` and ``group`` names that will be set for each member of the archive. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -338,6 +338,9 @@ option to enable parallel building of extension modules. (Contributed by Antoine Pitrou in :issue:`5309`.) +* Added support for the LZMA compression. + (Contributed by Serhiy Storchaka in :issue:`16314`.) + doctest ------- diff --git a/Lib/distutils/archive_util.py b/Lib/distutils/archive_util.py --- a/Lib/distutils/archive_util.py +++ b/Lib/distutils/archive_util.py @@ -57,26 +57,28 @@ """Create a (possibly compressed) tar file from all the files under 'base_dir'. - 'compress' must be "gzip" (the default), "compress", "bzip2", or None. - (compress will be deprecated in Python 3.2) + 'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or + None. ("compress" will be deprecated in Python 3.2) 'owner' and 'group' can be used to define an owner and a group for the archive that is being built. If not provided, the current owner and group will be used. The output tar file will be named 'base_dir' + ".tar", possibly plus - the appropriate compression extension (".gz", ".bz2" or ".Z"). + the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z"). Returns the output filename. """ - tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''} - compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'} + tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', 'xz': 'xz', None: '', + 'compress': ''} + compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz', + 'compress': '.Z'} # flags for compression program, each element of list will be an argument if compress is not None and compress not in compress_ext.keys(): raise ValueError( - "bad value for 'compress': must be None, 'gzip', 'bzip2' " - "or 'compress'") + "bad value for 'compress': must be None, 'gzip', 'bzip2', " + "'xz' or 'compress'") archive_name = base_name + '.tar' if compress != 'compress': @@ -177,6 +179,7 @@ ARCHIVE_FORMATS = { 'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), 'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"), 'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"), 'tar': (make_tarball, [('compress', None)], "uncompressed tar file"), 'zip': (make_zipfile, [],"ZIP file") @@ -197,8 +200,8 @@ """Create an archive file (eg. zip or tar). 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "ztar", - or "gztar". + extension; 'format' is the archive format: one of "zip", "tar", "gztar", + "bztar", "xztar", or "ztar". 'root_dir' is a directory that will be the root directory of the archive; ie. we typically chdir into 'root_dir' before creating the diff --git a/Lib/distutils/command/bdist.py b/Lib/distutils/command/bdist.py --- a/Lib/distutils/command/bdist.py +++ b/Lib/distutils/command/bdist.py @@ -61,13 +61,14 @@ 'nt': 'zip'} # Establish the preferred order (for the --help-formats option). - format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar', + format_commands = ['rpm', 'gztar', 'bztar', 'xztar', 'ztar', 'tar', 'wininst', 'zip', 'msi'] # And the real information. format_command = {'rpm': ('bdist_rpm', "RPM distribution"), 'gztar': ('bdist_dumb', "gzip'ed tar file"), 'bztar': ('bdist_dumb', "bzip2'ed tar file"), + 'xztar': ('bdist_dumb', "xz'ed tar file"), 'ztar': ('bdist_dumb', "compressed tar file"), 'tar': ('bdist_dumb', "tar file"), 'wininst': ('bdist_wininst', diff --git a/Lib/distutils/command/bdist_dumb.py b/Lib/distutils/command/bdist_dumb.py --- a/Lib/distutils/command/bdist_dumb.py +++ b/Lib/distutils/command/bdist_dumb.py @@ -22,7 +22,8 @@ "platform name to embed in generated filenames " "(default: %s)" % get_platform()), ('format=', 'f', - "archive format to create (tar, ztar, gztar, zip)"), + "archive format to create (tar, gztar, bztar, xztar, " + "ztar, zip)"), ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), diff --git a/Lib/distutils/tests/test_archive_util.py b/Lib/distutils/tests/test_archive_util.py --- a/Lib/distutils/tests/test_archive_util.py +++ b/Lib/distutils/tests/test_archive_util.py @@ -13,7 +13,7 @@ ARCHIVE_FORMATS) from distutils.spawn import find_executable, spawn from distutils.tests import support -from test.support import check_warnings, run_unittest, patch +from test.support import check_warnings, run_unittest, patch, change_cwd try: import grp @@ -34,6 +34,16 @@ except ImportError: ZLIB_SUPPORT = False +try: + import bz2 +except ImportError: + bz2 = None + +try: + import lzma +except ImportError: + lzma = None + def can_fs_encode(filename): """ Return True if the filename can be saved in the file system. @@ -52,19 +62,36 @@ unittest.TestCase): @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') - def test_make_tarball(self): - self._make_tarball('archive') + def test_make_tarball(self, name='archive'): + # creating something to tar + tmpdir = self._create_files() + self._make_tarball(tmpdir, name, '.tar.gz') + # trying an uncompressed one + self._make_tarball(tmpdir, name, '.tar', compress=None) @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') + def test_make_tarball_gzip(self): + tmpdir = self._create_files() + self._make_tarball(tmpdir, 'archive', '.tar.gz', compress='gzip') + + @unittest.skipUnless(bz2, 'Need bz2 support to run') + def test_make_tarball_bzip2(self): + tmpdir = self._create_files() + self._make_tarball(tmpdir, 'archive', '.tar.bz2', compress='bzip2') + + @unittest.skipUnless(lzma, 'Need lzma support to run') + def test_make_tarball_xz(self): + tmpdir = self._create_files() + self._make_tarball(tmpdir, 'archive', '.tar.xz', compress='xz') + @unittest.skipUnless(can_fs_encode('?rchiv'), 'File system cannot handle this filename') def test_make_tarball_latin1(self): """ Mirror test_make_tarball, except filename contains latin characters. """ - self._make_tarball('?rchiv') # note this isn't a real word + self.test_make_tarball('?rchiv') # note this isn't a real word - @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') @unittest.skipUnless(can_fs_encode('??????'), 'File system cannot handle this filename') def test_make_tarball_extended(self): @@ -72,16 +99,9 @@ Mirror test_make_tarball, except filename contains extended characters outside the latin charset. """ - self._make_tarball('??????') # japanese for archive + self.test_make_tarball('??????') # japanese for archive - def _make_tarball(self, target_name): - # creating something to tar - tmpdir = self.mkdtemp() - self.write_file([tmpdir, 'file1'], 'xxx') - self.write_file([tmpdir, 'file2'], 'xxx') - os.mkdir(os.path.join(tmpdir, 'sub')) - self.write_file([tmpdir, 'sub', 'file3'], 'xxx') - + def _make_tarball(self, tmpdir, target_name, suffix, **kwargs): tmpdir2 = self.mkdtemp() unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], "source and target should be on same drive") @@ -89,27 +109,13 @@ base_name = os.path.join(tmpdir2, target_name) # working with relative paths to avoid tar warnings - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - make_tarball(splitdrive(base_name)[1], '.') - finally: - os.chdir(old_dir) + with change_cwd(tmpdir): + make_tarball(splitdrive(base_name)[1], 'dist', **kwargs) # check if the compressed tarball was created - tarball = base_name + '.tar.gz' + tarball = base_name + suffix self.assertTrue(os.path.exists(tarball)) - - # trying an uncompressed one - base_name = os.path.join(tmpdir2, target_name) - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - make_tarball(splitdrive(base_name)[1], '.', compress=None) - finally: - os.chdir(old_dir) - tarball = base_name + '.tar' - self.assertTrue(os.path.exists(tarball)) + self.assertEqual(self._tarinfo(tarball), self._created_files) def _tarinfo(self, path): tar = tarfile.open(path) @@ -120,6 +126,9 @@ finally: tar.close() + _created_files = ('dist', 'dist/file1', 'dist/file2', + 'dist/sub', 'dist/sub/file3', 'dist/sub2') + def _create_files(self): # creating something to tar tmpdir = self.mkdtemp() @@ -130,15 +139,15 @@ os.mkdir(os.path.join(dist, 'sub')) self.write_file([dist, 'sub', 'file3'], 'xxx') os.mkdir(os.path.join(dist, 'sub2')) - tmpdir2 = self.mkdtemp() - base_name = os.path.join(tmpdir2, 'archive') - return tmpdir, tmpdir2, base_name + return tmpdir @unittest.skipUnless(find_executable('tar') and find_executable('gzip') and ZLIB_SUPPORT, 'Need the tar, gzip and zlib command to run') def test_tarfile_vs_tar(self): - tmpdir, tmpdir2, base_name = self._create_files() + tmpdir = self._create_files() + tmpdir2 = self.mkdtemp() + base_name = os.path.join(tmpdir2, 'archive') old_dir = os.getcwd() os.chdir(tmpdir) try: @@ -164,7 +173,8 @@ self.assertTrue(os.path.exists(tarball2)) # let's compare both tarballs - self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2)) + self.assertEqual(self._tarinfo(tarball), self._created_files) + self.assertEqual(self._tarinfo(tarball2), self._created_files) # trying an uncompressed one base_name = os.path.join(tmpdir2, 'archive') @@ -191,7 +201,8 @@ @unittest.skipUnless(find_executable('compress'), 'The compress program is required') def test_compress_deprecated(self): - tmpdir, tmpdir2, base_name = self._create_files() + tmpdir = self._create_files() + base_name = os.path.join(self.mkdtemp(), 'archive') # using compress and testing the PendingDeprecationWarning old_dir = os.getcwd() @@ -224,17 +235,17 @@ 'Need zip and zlib support to run') def test_make_zipfile(self): # creating something to tar - tmpdir = self.mkdtemp() - self.write_file([tmpdir, 'file1'], 'xxx') - self.write_file([tmpdir, 'file2'], 'xxx') - - tmpdir2 = self.mkdtemp() - base_name = os.path.join(tmpdir2, 'archive') - make_zipfile(base_name, tmpdir) + tmpdir = self._create_files() + base_name = os.path.join(self.mkdtemp(), 'archive') + with change_cwd(tmpdir): + make_zipfile(base_name, 'dist') # check if the compressed tarball was created tarball = base_name + '.zip' self.assertTrue(os.path.exists(tarball)) + with zipfile.ZipFile(tarball) as zf: + self.assertEqual(sorted(zf.namelist()), + ['dist/file1', 'dist/file2', 'dist/sub/file3']) @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run') def test_make_zipfile_no_zlib(self): @@ -250,18 +261,24 @@ patch(self, archive_util.zipfile, 'ZipFile', fake_zipfile) # create something to tar and compress - tmpdir, tmpdir2, base_name = self._create_files() - make_zipfile(base_name, tmpdir) + tmpdir = self._create_files() + base_name = os.path.join(self.mkdtemp(), 'archive') + with change_cwd(tmpdir): + make_zipfile(base_name, 'dist') tarball = base_name + '.zip' self.assertEqual(called, [((tarball, "w"), {'compression': zipfile.ZIP_STORED})]) self.assertTrue(os.path.exists(tarball)) + with zipfile.ZipFile(tarball) as zf: + self.assertEqual(sorted(zf.namelist()), + ['dist/file1', 'dist/file2', 'dist/sub/file3']) def test_check_archive_formats(self): self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']), 'xxx') - self.assertEqual(check_archive_formats(['gztar', 'zip']), None) + self.assertIsNone(check_archive_formats(['gztar', 'bztar', 'xztar', + 'ztar', 'tar', 'zip'])) def test_make_archive(self): tmpdir = self.mkdtemp() @@ -282,6 +299,41 @@ finally: del ARCHIVE_FORMATS['xxx'] + def test_make_archive_tar(self): + base_dir = self._create_files() + base_name = os.path.join(self.mkdtemp() , 'archive') + res = make_archive(base_name, 'tar', base_dir, 'dist') + self.assertTrue(os.path.exists(res)) + self.assertEqual(os.path.basename(res), 'archive.tar') + self.assertEqual(self._tarinfo(res), self._created_files) + + @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') + def test_make_archive_gztar(self): + base_dir = self._create_files() + base_name = os.path.join(self.mkdtemp() , 'archive') + res = make_archive(base_name, 'gztar', base_dir, 'dist') + self.assertTrue(os.path.exists(res)) + self.assertEqual(os.path.basename(res), 'archive.tar.gz') + self.assertEqual(self._tarinfo(res), self._created_files) + + @unittest.skipUnless(bz2, 'Need bz2 support to run') + def test_make_archive_bztar(self): + base_dir = self._create_files() + base_name = os.path.join(self.mkdtemp() , 'archive') + res = make_archive(base_name, 'bztar', base_dir, 'dist') + self.assertTrue(os.path.exists(res)) + self.assertEqual(os.path.basename(res), 'archive.tar.bz2') + self.assertEqual(self._tarinfo(res), self._created_files) + + @unittest.skipUnless(bz2, 'Need xz support to run') + def test_make_archive_xztar(self): + base_dir = self._create_files() + base_name = os.path.join(self.mkdtemp() , 'archive') + res = make_archive(base_name, 'xztar', base_dir, 'dist') + self.assertTrue(os.path.exists(res)) + self.assertEqual(os.path.basename(res), 'archive.tar.xz') + self.assertEqual(self._tarinfo(res), self._created_files) + def test_make_archive_owner_group(self): # testing make_archive with owner and group, with various combinations # this works even if there's not gid/uid support @@ -291,7 +343,8 @@ else: group = owner = 'root' - base_dir, root_dir, base_name = self._create_files() + base_dir = self._create_files() + root_dir = self.mkdtemp() base_name = os.path.join(self.mkdtemp() , 'archive') res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner, group=group) @@ -311,7 +364,8 @@ @unittest.skipUnless(ZLIB_SUPPORT, "Requires zlib") @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support") def test_tarfile_root_owner(self): - tmpdir, tmpdir2, base_name = self._create_files() + tmpdir = self._create_files() + base_name = os.path.join(self.mkdtemp(), 'archive') old_dir = os.getcwd() os.chdir(tmpdir) group = grp.getgrgid(0)[0] diff --git a/Lib/distutils/tests/test_bdist.py b/Lib/distutils/tests/test_bdist.py --- a/Lib/distutils/tests/test_bdist.py +++ b/Lib/distutils/tests/test_bdist.py @@ -21,7 +21,7 @@ # what formats does bdist offer? formats = ['bztar', 'gztar', 'msi', 'rpm', 'tar', - 'wininst', 'zip', 'ztar'] + 'wininst', 'xztar', 'zip', 'ztar'] found = sorted(cmd.format_command) self.assertEqual(found, formats) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,8 @@ Library ------- +- Issue #16314: Added support for the LZMA compression in distutils. + - Issue #21804: poplib now supports RFC 6856 (UTF8). - Issue #18682: Optimized pprint functions for builtin scalar types. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 21:41:19 2015 From: python-checkins at python.org (r.david.murray) Date: Sat, 16 May 2015 19:41:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2321083=3A_add_get=5Fcont?= =?utf-8?q?ent=5Fdisposition_method_to_email=2Emessage=2E?= Message-ID: <20150516194118.39267.49419@psf.io> https://hg.python.org/cpython/rev/29ba76f5c3dc changeset: 96103:29ba76f5c3dc user: R David Murray date: Sat May 16 15:41:07 2015 -0400 summary: #21083: add get_content_disposition method to email.message. Patch by Abhilash Raj. files: Doc/library/email.message.rst | 9 +++++++++ Doc/whatsnew/3.5.rst | 8 ++++++++ Lib/email/message.py | 12 ++++++++++++ Lib/test/test_email/test_email.py | 11 +++++++++++ Misc/ACKS | 1 + 5 files changed, 41 insertions(+), 0 deletions(-) diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -578,6 +578,15 @@ will be *failobj*. + .. method:: get_content_disposition() + + Return the lowercased value (without parameters) of the message's + :mailheader:`Content-Disposition` header if it has one, or ``None``. The + possible values for this method are *inline*, *attachment* or ``None`` + if the message follows :rfc:`2183`. + + .. versionadded:: 3.5 + .. method:: walk() The :meth:`walk` method is an all-purpose generator which can be used to diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -348,6 +348,14 @@ *module* contains no docstrings instead of raising :exc:`ValueError`. (Contributed by Glenn Jones in :issue:`15916`.) +email +----- + +* A new method :meth:`~email.message.Message.get_content_disposition` provides + easy access to a canonical value for the :mailheader:`Content-Disposition` + header (``None`` if there is no such header). (Contributed by Abhilash Raj + in :issue:`21083`.) + glob ---- diff --git a/Lib/email/message.py b/Lib/email/message.py --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -927,6 +927,18 @@ """ return [part.get_content_charset(failobj) for part in self.walk()] + def get_content_disposition(self): + """Return the message's content-disposition if it exists, or None. + + The return values can be either 'inline', 'attachment' or None + according to the rfc2183. + """ + value = self.get('content-disposition') + if value is None: + return None + c_d = _splitparam(value)[0].lower() + return c_d + # I.e. def walk(self): ... from email.iterators import walk diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -586,6 +586,17 @@ eq(msg.values(), ['One Hundred', 'Twenty', 'Three', 'Eleven']) self.assertRaises(KeyError, msg.replace_header, 'Fourth', 'Missing') + def test_get_content_disposition(self): + msg = Message() + self.assertIsNone(msg.get_content_disposition()) + msg.add_header('Content-Disposition', 'attachment', + filename='random.avi') + self.assertEqual(msg.get_content_disposition(), 'attachment') + msg.replace_header('Content-Disposition', 'inline') + self.assertEqual(msg.get_content_disposition(), 'inline') + msg.replace_header('Content-Disposition', 'InlinE') + self.assertEqual(msg.get_content_disposition(), 'inline') + # test_defect_handling:test_invalid_chars_in_base64_payload def test_broken_base64_payload(self): x = 'AwDp0P7//y6LwKEAcPa/6Q=9' diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1134,6 +1134,7 @@ Ram Rachum J?r?me Radix Burton Radons +Abhilash Raj Shorya Raj Jeff Ramnani Brodie Rao -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 22:21:31 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 16 May 2015 20:21:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324210=3A_Silence_?= =?utf-8?q?more_PendingDeprecationWarning_warnings_in_tests=2E?= Message-ID: <20150516202131.39261.28489@psf.io> https://hg.python.org/cpython/rev/e73182301a61 changeset: 96104:e73182301a61 user: Berker Peksag date: Sat May 16 23:21:26 2015 +0300 summary: Issue #24210: Silence more PendingDeprecationWarning warnings in tests. files: Lib/test/test_platform.py | 18 ++++++++++++++++-- Lib/test/test_ssl.py | 22 +++++++++++++++------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -236,7 +236,14 @@ self.assertEqual(sts, 0) def test_dist(self): - res = platform.dist() + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + 'dist\(\) and linux_distribution\(\) ' + 'functions are deprecated .*', + PendingDeprecationWarning, + ) + res = platform.dist() def test_libc_ver(self): import os @@ -305,7 +312,14 @@ f.write('Fedora release 19 (Schr\xf6dinger\u2019s Cat)\n') with mock.patch('platform._UNIXCONFDIR', tempdir): - distname, version, distid = platform.linux_distribution() + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + 'dist\(\) and linux_distribution\(\) ' + 'functions are deprecated .*', + PendingDeprecationWarning, + ) + distname, version, distid = platform.linux_distribution() self.assertEqual(distname, 'Fedora') self.assertEqual(version, '19') diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -3294,18 +3294,26 @@ def test_main(verbose=False): if support.verbose: + import warnings plats = { 'Linux': platform.linux_distribution, 'Mac': platform.mac_ver, 'Windows': platform.win32_ver, } - for name, func in plats.items(): - plat = func() - if plat and plat[0]: - plat = '%s %r' % (name, plat) - break - else: - plat = repr(platform.platform()) + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + 'dist\(\) and linux_distribution\(\) ' + 'functions are deprecated .*', + PendingDeprecationWarning, + ) + for name, func in plats.items(): + plat = func() + if plat and plat[0]: + plat = '%s %r' % (name, plat) + break + else: + plat = repr(platform.platform()) print("test_ssl: testing with %r %r" % (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO)) print(" under %s" % plat) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 16 22:29:36 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 16 May 2015 20:29:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_versionadded_directive?= =?utf-8?q?_for_BoundArguments=2Eapply=5Fdefaults=28=29=2E?= Message-ID: <20150516202936.32305.45342@psf.io> https://hg.python.org/cpython/rev/28ef716d3703 changeset: 96105:28ef716d3703 user: Berker Peksag date: Sat May 16 23:29:31 2015 +0300 summary: Add versionadded directive for BoundArguments.apply_defaults(). files: Doc/library/inspect.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -702,6 +702,8 @@ >>> ba.arguments OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())]) + .. versionadded:: 3.5 + The :attr:`args` and :attr:`kwargs` properties can be used to invoke functions:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 00:31:54 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 22:31:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150516223154.26560.3265@psf.io> https://hg.python.org/cpython/rev/92307870268d changeset: 96107:92307870268d parent: 96105:28ef716d3703 parent: 96106:44fc6db34b69 user: Terry Jan Reedy date: Sat May 16 18:31:32 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/__main__.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/__main__.py b/Lib/idlelib/__main__.py --- a/Lib/idlelib/__main__.py +++ b/Lib/idlelib/__main__.py @@ -3,7 +3,6 @@ Run IDLE as python -m idlelib """ - - import idlelib.PyShell idlelib.PyShell.main() +# This file does not work for 2.7; See issue 24212. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 00:31:54 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 22:31:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjEy?= =?utf-8?q?=3A_Put_reference_in_idle=2E=5F=5Fmain=5F=5F_to_issue_with_expl?= =?utf-8?q?anation=2E?= Message-ID: <20150516223154.10824.39677@psf.io> https://hg.python.org/cpython/rev/44fc6db34b69 changeset: 96106:44fc6db34b69 branch: 3.4 parent: 96098:955dffec3d94 user: Terry Jan Reedy date: Sat May 16 18:31:15 2015 -0400 summary: Issue #24212: Put reference in idle.__main__ to issue with explanation. files: Lib/idlelib/__main__.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/__main__.py b/Lib/idlelib/__main__.py --- a/Lib/idlelib/__main__.py +++ b/Lib/idlelib/__main__.py @@ -3,7 +3,6 @@ Run IDLE as python -m idlelib """ - - import idlelib.PyShell idlelib.PyShell.main() +# This file does not work for 2.7; See issue 24212. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 01:23:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 16 May 2015 23:23:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_issue_=2316314_test_?= =?utf-8?q?for_the_case_when_lzma_is_not_available=2E?= Message-ID: <20150516232346.21158.25233@psf.io> https://hg.python.org/cpython/rev/25cb42a4bce9 changeset: 96108:25cb42a4bce9 user: Serhiy Storchaka date: Sun May 17 02:23:02 2015 +0300 summary: Fixed issue #16314 test for the case when lzma is not available. files: Lib/distutils/tests/test_archive_util.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/distutils/tests/test_archive_util.py b/Lib/distutils/tests/test_archive_util.py --- a/Lib/distutils/tests/test_archive_util.py +++ b/Lib/distutils/tests/test_archive_util.py @@ -325,7 +325,7 @@ self.assertEqual(os.path.basename(res), 'archive.tar.bz2') self.assertEqual(self._tarinfo(res), self._created_files) - @unittest.skipUnless(bz2, 'Need xz support to run') + @unittest.skipUnless(lzma, 'Need xz support to run') def test_make_archive_xztar(self): base_dir = self._create_files() base_name = os.path.join(self.mkdtemp() , 'archive') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 01:34:09 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 23:34:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTk5?= =?utf-8?q?=3A_Make_idlever_module_self_updating=2E_Syop_using_it_in_about?= =?utf-8?q?Dialog=2E?= Message-ID: <20150516233409.4233.50726@psf.io> https://hg.python.org/cpython/rev/c862166060ed changeset: 96110:c862166060ed branch: 3.4 parent: 96106:44fc6db34b69 user: Terry Jan Reedy date: Sat May 16 19:28:32 2015 -0400 summary: Issue #24199: Make idlever module self updating. Syop using it in aboutDialog. files: Lib/idlelib/aboutDialog.py | 15 +++++++-------- Lib/idlelib/idlever.py | 6 +++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -2,12 +2,10 @@ """ +import os +from sys import version from tkinter import * -import os -import sys - from idlelib import textView -from idlelib import idlever class AboutDialog(Toplevel): """Modal about dialog for idle @@ -38,6 +36,7 @@ self.wait_window() def CreateWidgets(self): + release = version[:version.index(' ')] frameMain = Frame(self, borderwidth=2, relief=SUNKEN) frameButtons = Frame(self) frameButtons.pack(side=BOTTOM, fill=X) @@ -64,14 +63,14 @@ labelEmail.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) labelWWW = Label(frameBg, text='https://docs.python.org/' + - sys.version[:3] + '/library/idle.html', + version[:3] + '/library/idle.html', justify=LEFT, fg=self.fg, bg=self.bg) labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg, text='Python version: ' + \ - sys.version.split()[0], fg=self.fg, bg=self.bg) + labelPythonVer = Label(frameBg, text='Python version: ' + + release, fg=self.fg, bg=self.bg) labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) tkVer = self.tk.call('info', 'patchlevel') labelTkVer = Label(frameBg, text='Tk version: '+ @@ -94,7 +93,7 @@ Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, + idle_v = Label(frameBg, text='IDLE version: ' + release, fg=self.fg, bg=self.bg) idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_button_f = Frame(frameBg, bg=self.bg) diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,5 @@ -IDLE_VERSION = "3.4.3" +"""Unused by Idle: there is no separate Idle version anymore. +Kept only for possible existing extension use.""" +from sys import version +IDLE_VERSION = version[:version.index(' ')] + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 01:34:09 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 23:34:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150516233409.16304.55828@psf.io> https://hg.python.org/cpython/rev/7444e7752bed changeset: 96111:7444e7752bed parent: 96108:25cb42a4bce9 parent: 96110:c862166060ed user: Terry Jan Reedy date: Sat May 16 19:33:32 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/aboutDialog.py | 15 +++++++-------- Lib/idlelib/idlever.py | 5 ++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -2,12 +2,10 @@ """ +import os +from sys import version from tkinter import * -import os -import sys - from idlelib import textView -from idlelib import idlever class AboutDialog(Toplevel): """Modal about dialog for idle @@ -38,6 +36,7 @@ self.wait_window() def CreateWidgets(self): + release = version[:version.index(' ')] frameMain = Frame(self, borderwidth=2, relief=SUNKEN) frameButtons = Frame(self) frameButtons.pack(side=BOTTOM, fill=X) @@ -64,14 +63,14 @@ labelEmail.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) labelWWW = Label(frameBg, text='https://docs.python.org/' + - sys.version[:3] + '/library/idle.html', + version[:3] + '/library/idle.html', justify=LEFT, fg=self.fg, bg=self.bg) labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg, text='Python version: ' + \ - sys.version.split()[0], fg=self.fg, bg=self.bg) + labelPythonVer = Label(frameBg, text='Python version: ' + + release, fg=self.fg, bg=self.bg) labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) tkVer = self.tk.call('info', 'patchlevel') labelTkVer = Label(frameBg, text='Tk version: '+ @@ -94,7 +93,7 @@ Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, + idle_v = Label(frameBg, text='IDLE version: ' + release, fg=self.fg, bg=self.bg) idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_button_f = Frame(frameBg, bg=self.bg) diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,4 @@ -IDLE_VERSION = "3.5.0a4" +"""Unused by Idle: there is no separate Idle version anymore. +Kept only for possible existing extension use.""" +from sys import version +IDLE_VERSION = version[:version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 01:34:09 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 16 May 2015 23:34:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTk5?= =?utf-8?q?=3A_Stop_using_idelver_in_aboutdialog=2E?= Message-ID: <20150516233409.39245.25150@psf.io> https://hg.python.org/cpython/rev/c473ac171041 changeset: 96109:c473ac171041 branch: 2.7 parent: 96097:6570e4e9b1f3 user: Terry Jan Reedy date: Sat May 16 19:28:27 2015 -0400 summary: Issue #24199: Stop using idelver in aboutdialog. files: Lib/idlelib/aboutDialog.py | 15 +++++++-------- 1 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -1,12 +1,10 @@ """About Dialog for IDLE """ - +import os +from sys import version from Tkinter import * -import os - from idlelib import textView -from idlelib import idlever class AboutDialog(Toplevel): """Modal about dialog for idle @@ -37,6 +35,7 @@ self.wait_window() def CreateWidgets(self): + release = version[:version.index(' ')] frameMain = Frame(self, borderwidth=2, relief=SUNKEN) frameButtons = Frame(self) frameButtons.pack(side=BOTTOM, fill=X) @@ -63,14 +62,14 @@ labelEmail.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) labelWWW = Label(frameBg, text='https://docs.python.org/' + - sys.version[:3] + '/library/idle.html', + version[:3] + '/library/idle.html', justify=LEFT, fg=self.fg, bg=self.bg) labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg, text='Python version: ' + \ - sys.version.split()[0], fg=self.fg, bg=self.bg) + labelPythonVer = Label(frameBg, text='Python version: ' + + release, fg=self.fg, bg=self.bg) labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) tkVer = self.tk.call('info', 'patchlevel') labelTkVer = Label(frameBg, text='Tk version: '+ @@ -93,7 +92,7 @@ Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, + idle_v = Label(frameBg, text='IDLE version: ' + release, fg=self.fg, bg=self.bg) idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_button_f = Frame(frameBg, bg=self.bg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 04:12:27 2015 From: python-checkins at python.org (chris.angelico) Date: Sun, 17 May 2015 02:12:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Apply_Chris=27s_changes=2C_in?= =?utf-8?q?cluding_an_acceptance_mark?= Message-ID: <20150517021227.21144.86257@psf.io> https://hg.python.org/peps/rev/f876276ce076 changeset: 5854:f876276ce076 user: Chris Angelico date: Sun May 17 12:12:19 2015 +1000 summary: Apply Chris's changes, including an acceptance mark files: pep-0485.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0485.txt b/pep-0485.txt --- a/pep-0485.txt +++ b/pep-0485.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Christopher Barker -Status: Draft +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 20-Jan-2015 @@ -391,9 +391,9 @@ The most common use case is expected to be small tolerances -- on order of the default 1e-9. However there may be use cases where a user wants to know if two fairly disparate values are within a particular range of each other: "is a -within 200% (rel_tol = 2.0) of b? In this case, the string test would never +within 200% (rel_tol = 2.0) of b? In this case, the strong test would never indicate that two values are within that range of each other if one of them is -zero. The strong case, however would use the larger (non-zero) value for the +zero. The weak case, however would use the larger (non-zero) value for the test, and thus return true if one value is zero. For example: is 0 within 200% of 10? 200% of ten is 20, so the range within 200% of ten is -10 to +30. Zero falls within that range, so it will return True. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 17 05:46:06 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 17 May 2015 03:46:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Ignore_PCbuild/=2Evs_direc?= =?utf-8?q?tory=2E?= Message-ID: <20150517034606.39263.91047@psf.io> https://hg.python.org/cpython/rev/f581cbaedc87 changeset: 96112:f581cbaedc87 user: Zachary Ware date: Sat May 16 22:45:27 2015 -0500 summary: Ignore PCbuild/.vs directory. Also fix a couple other ignored PCbuild directories in .gitignore files: .gitignore | 5 +++-- .hgignore | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -49,9 +49,10 @@ PCbuild/*.*sdf PCbuild/*-pgi PCbuild/*-pgo +PCbuild/.vs/ PCbuild/amd64/ -PCbuild/obj -PCBuild/win32 +PCbuild/obj/ +PCBuild/win32/ .purify Parser/pgen __pycache__ diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -73,6 +73,7 @@ PCbuild/*.*sdf PCbuild/*-pgi PCbuild/*-pgo +PCbuild/.vs PCbuild/amd64 PCbuild/obj PCbuild/win32 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 06:14:11 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 17 May 2015 04:14:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_http_-=3E_https?= Message-ID: <20150517041411.10826.20766@psf.io> https://hg.python.org/peps/rev/dc165c7bcd6d changeset: 5855:dc165c7bcd6d user: Benjamin Peterson date: Sun May 17 00:14:10 2015 -0400 summary: http -> https files: pep-0101.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -88,7 +88,7 @@ As much as possible, the release steps are automated and guided by the release script, which is available in a separate repository: - http://hg.python.org/release/ + https://hg.python.org/release/ We use the following conventions in the examples below. Where a release number is given, it is of the form X.Y.ZaN, e.g. 3.3.0a3 for Python 3.3.0 -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Sun May 17 10:49:02 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 17 May 2015 08:49:02 +0000 Subject: [Python-checkins] Daily reference leaks (f581cbaedc87): sum=4 Message-ID: <20150517084902.4243.32854@psf.io> results for f581cbaedc87 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogA8VWbg', '--timeout', '7200'] From python-checkins at python.org Sun May 17 12:54:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 17 May 2015 10:54:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1ODA5?= =?utf-8?q?=3A_IDLE_shell_now_uses_locale_encoding_instead_of_Latin1_for?= Message-ID: <20150517105415.44671.95761@psf.io> https://hg.python.org/cpython/rev/247f003b42ea changeset: 96113:247f003b42ea branch: 2.7 parent: 96109:c473ac171041 user: Serhiy Storchaka date: Sun May 17 13:53:54 2015 +0300 summary: Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for decoding unicode literals. files: Lib/idlelib/PyShell.py | 8 +++++--- Lib/idlelib/run.py | 2 ++ Misc/NEWS | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -34,6 +34,7 @@ from idlelib import Debugger from idlelib import RemoteDebugger from idlelib import macosxSupport +from idlelib import IOBinding IDENTCHARS = string.ascii_letters + string.digits + "_" HOST = '127.0.0.1' # python execution server on localhost loopback @@ -668,10 +669,11 @@ self.more = 0 self.save_warnings_filters = warnings.filters[:] warnings.filterwarnings(action="error", category=SyntaxWarning) - if isinstance(source, unicode): - from idlelib import IOBinding + if isinstance(source, unicode) and IOBinding.encoding != 'utf-8': try: - source = source.encode(IOBinding.encoding) + source = '# -*- coding: %s -*-\n%s' % ( + IOBinding.encoding, + source.encode(IOBinding.encoding)) except UnicodeError: self.tkconsole.resetoutput() self.write("Unsupported characters in input\n") diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -210,6 +210,8 @@ fn, ln, nm, line = tb[i] if nm == '?': nm = "-toplevel-" + if fn.startswith(" https://hg.python.org/cpython/rev/ba271f116f94 changeset: 96114:ba271f116f94 branch: 3.4 parent: 96110:c862166060ed user: R David Murray date: Sun May 17 10:16:37 2015 -0400 summary: #24216: fix typo files: Doc/library/stdtypes.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2483,7 +2483,7 @@ Return a bytes or bytearray object which is the concatenation of the binary data sequences in the :term:`iterable` *iterable*. A :exc:`TypeError` will be raised if there are any values in *iterable* - that are note :term:`bytes-like objects `, including + that are not :term:`bytes-like objects `, including :class:`str` objects. The separator between elements is the contents of the bytes or bytearray object providing this method. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 16:17:45 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 17 May 2015 14:17:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2324216=3A_fix_typo?= Message-ID: <20150517141745.32287.31020@psf.io> https://hg.python.org/cpython/rev/91ac3040a28d changeset: 96115:91ac3040a28d parent: 96112:f581cbaedc87 parent: 96114:ba271f116f94 user: R David Murray date: Sun May 17 10:17:35 2015 -0400 summary: Merge: #24216: fix typo files: Doc/library/stdtypes.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2509,7 +2509,7 @@ Return a bytes or bytearray object which is the concatenation of the binary data sequences in the :term:`iterable` *iterable*. A :exc:`TypeError` will be raised if there are any values in *iterable* - that are note :term:`bytes-like objects `, including + that are not :term:`bytes-like objects `, including :class:`str` objects. The separator between elements is the contents of the bytes or bytearray object providing this method. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 17:07:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 17 May 2015 15:07:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Fix_=27async_with?= =?utf-8?q?=27_equivalent_code?= Message-ID: <20150517150729.16304.1892@psf.io> https://hg.python.org/peps/rev/136a9ac535fe changeset: 5856:136a9ac535fe user: Yury Selivanov date: Sun May 17 11:07:25 2015 -0400 summary: pep-492: Fix 'async with' equivalent code files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -357,8 +357,8 @@ aenter = type(mgr).__aenter__(mgr) exc = True + VAR = await aenter try: - VAR = await aenter BLOCK except: if not await aexit(mgr, *sys.exc_info()): -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 17 17:15:51 2015 From: python-checkins at python.org (chris.angelico) Date: Sun, 17 May 2015 15:15:51 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_Resolution_header_to_now-?= =?utf-8?q?accepted_PEP_485?= Message-ID: <20150517151551.10810.60746@psf.io> https://hg.python.org/peps/rev/f3841e46991d changeset: 5857:f3841e46991d user: Chris Angelico date: Mon May 18 01:14:55 2015 +1000 summary: Add Resolution header to now-accepted PEP 485 files: pep-0485.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0485.txt b/pep-0485.txt --- a/pep-0485.txt +++ b/pep-0485.txt @@ -9,6 +9,7 @@ Created: 20-Jan-2015 Python-Version: 3.5 Post-History: +Resolution: https://mail.python.org/pipermail/python-dev/2015-February/138598.html Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 17 17:29:50 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 17 May 2015 15:29:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2324211=3A_Add_RFC6532_su?= =?utf-8?q?pport_to_the_email_library=2E?= Message-ID: <20150517152949.125536.57608@psf.io> https://hg.python.org/cpython/rev/9f0d5e33230f changeset: 96116:9f0d5e33230f user: R David Murray date: Sun May 17 11:29:21 2015 -0400 summary: #24211: Add RFC6532 support to the email library. This could use more edge case tests, but the basic functionality is tested. (Note that this changeset does not add tailored support for the RFC 6532 message/global MIME type, but the email package generic facilities will handle it.) Reviewed by Maciej Szulik. files: Doc/library/email.policy.rst | 8 +++++ Doc/whatsnew/3.5.rst | 6 ++++ Lib/email/_header_value_parser.py | 11 ++++-- Lib/email/policy.py | 15 +++++++++- Lib/test/test_email/test_generator.py | 22 +++++++++++++++ Lib/test/test_email/test_policy.py | 4 ++ Misc/NEWS | 3 ++ 7 files changed, 64 insertions(+), 5 deletions(-) diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -378,6 +378,14 @@ In addition to the settable attributes listed above that apply to all policies, this policy adds the following additional attributes: + .. attribute:: utf8 + + If ``False``, follow :rfc:`5322`, supporting non-ASCII characters in + headers by encoding them as "encoded words". If ``True``, follow + :rfc:`6532` and use ``utf-8`` encoding for headers. Messages + formatted in this way may be passed to SMTP servers that support + the ``SMTPUTF8`` extension (:rfc:`6531`). + .. attribute:: refold_source If the value for a header in the ``Message`` object originated from a diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -356,6 +356,12 @@ header (``None`` if there is no such header). (Contributed by Abhilash Raj in :issue:`21083`.) +* A new policy option :attr:`~email.policy.EmailPolicy.utf8` can be set + ``True`` to encode email headers using the utf8 charset instead of using + encoded words. This allows ``Messages`` to be formatted according to + :rfc:`6532` and used with an SMTP server that supports the :rfc:`6531` + ``SMTPUTF8`` extension. (Contributed by R. David Murray in :issue:`24211`.) + glob ---- diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -320,17 +320,18 @@ return ''.join(res) def _fold(self, folded): + encoding = 'utf-8' if folded.policy.utf8 else 'ascii' for part in self.parts: tstr = str(part) tlen = len(tstr) try: - str(part).encode('us-ascii') + str(part).encode(encoding) except UnicodeEncodeError: if any(isinstance(x, errors.UndecodableBytesDefect) for x in part.all_defects): charset = 'unknown-8bit' else: - # XXX: this should be a policy setting + # XXX: this should be a policy setting when utf8 is False. charset = 'utf-8' tstr = part.cte_encode(charset, folded.policy) tlen = len(tstr) @@ -394,11 +395,12 @@ def _fold(self, folded): last_ew = None + encoding = 'utf-8' if folded.policy.utf8 else 'ascii' for part in self.parts: tstr = str(part) is_ew = False try: - str(part).encode('us-ascii') + str(part).encode(encoding) except UnicodeEncodeError: if any(isinstance(x, errors.UndecodableBytesDefect) for x in part.all_defects): @@ -475,12 +477,13 @@ # comment that becomes a barrier across which we can't compose encoded # words. last_ew = None + encoding = 'utf-8' if folded.policy.utf8 else 'ascii' for part in self.parts: tstr = str(part) tlen = len(tstr) has_ew = False try: - str(part).encode('us-ascii') + str(part).encode(encoding) except UnicodeEncodeError: if any(isinstance(x, errors.UndecodableBytesDefect) for x in part.all_defects): diff --git a/Lib/email/policy.py b/Lib/email/policy.py --- a/Lib/email/policy.py +++ b/Lib/email/policy.py @@ -35,6 +35,13 @@ In addition to the settable attributes listed above that apply to all Policies, this policy adds the following additional attributes: + utf8 -- if False (the default) message headers will be + serialized as ASCII, using encoded words to encode + any non-ASCII characters in the source strings. If + True, the message headers will be serialized using + utf8 and will not contain encoded words (see RFC + 6532 for more on this serialization format). + refold_source -- if the value for a header in the Message object came from the parsing of some source, this attribute indicates whether or not a generator should refold @@ -72,6 +79,7 @@ """ + utf8 = False refold_source = 'long' header_factory = HeaderRegistry() content_manager = raw_data_manager @@ -175,9 +183,13 @@ refold_header setting, since there is no way to know whether the binary data consists of single byte characters or multibyte characters. + If utf8 is true, headers are encoded to utf8, otherwise to ascii with + non-ASCII unicode rendered as encoded words. + """ folded = self._fold(name, value, refold_binary=self.cte_type=='7bit') - return folded.encode('ascii', 'surrogateescape') + charset = 'utf8' if self.utf8 else 'ascii' + return folded.encode(charset, 'surrogateescape') def _fold(self, name, value, refold_binary=False): if hasattr(value, 'name'): @@ -199,3 +211,4 @@ strict = default.clone(raise_on_defect=True) SMTP = default.clone(linesep='\r\n') HTTP = default.clone(linesep='\r\n', max_line_length=None) +SMTPUTF8 = SMTP.clone(utf8=True) diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -2,6 +2,7 @@ import textwrap import unittest from email import message_from_string, message_from_bytes +from email.message import EmailMessage from email.generator import Generator, BytesGenerator from email import policy from test.test_email import TestEmailBase, parameterize @@ -194,6 +195,27 @@ g.flatten(msg) self.assertEqual(s.getvalue(), expected) + def test_smtputf8_policy(self): + msg = EmailMessage() + msg['From'] = "P?olo " + msg['To'] = 'Dinsdale' + msg['Subject'] = 'Nudge nudge, wink, wink \u1F609' + msg.set_content("oh l? l?, know what I mean, know what I mean?") + expected = textwrap.dedent("""\ + From: P?olo + To: Dinsdale + Subject: Nudge nudge, wink, wink \u1F609 + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: 8bit + MIME-Version: 1.0 + + oh l? l?, know what I mean, know what I mean? + """).encode('utf-8').replace(b'\n', b'\r\n') + s = io.BytesIO() + g = BytesGenerator(s, policy=policy.SMTPUTF8) + g.flatten(msg) + self.assertEqual(s.getvalue(), expected) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py --- a/Lib/test/test_email/test_policy.py +++ b/Lib/test/test_email/test_policy.py @@ -27,6 +27,7 @@ # If any of these defaults change, the docs must be updated. policy_defaults = compat32_defaults.copy() policy_defaults.update({ + 'utf8': False, 'raise_on_defect': False, 'header_factory': email.policy.EmailPolicy.header_factory, 'refold_source': 'long', @@ -42,6 +43,9 @@ email.policy.default: make_defaults(policy_defaults, {}), email.policy.SMTP: make_defaults(policy_defaults, {'linesep': '\r\n'}), + email.policy.SMTPUTF8: make_defaults(policy_defaults, + {'linesep': '\r\n', + 'utf8': True}), email.policy.HTTP: make_defaults(policy_defaults, {'linesep': '\r\n', 'max_line_length': None}), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Library ------- +- Issue #24211: The email library now supports RFC 6532: it can generate + headers using utf-8 instead of encoded words. + - Issue #16314: Added support for the LZMA compression in distutils. - Issue #21804: poplib now supports RFC 6856 (UTF8). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 18:22:04 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 17 May 2015 16:22:04 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Properly_terminate_Emacs_vari?= =?utf-8?q?able_list_at_end_of_PEP_485=2E?= Message-ID: <20150517162204.16292.60099@psf.io> https://hg.python.org/peps/rev/2cdaf76775a6 changeset: 5858:2cdaf76775a6 user: Guido van Rossum date: Sun May 17 09:21:53 2015 -0700 summary: Properly terminate Emacs variable list at end of PEP 485. files: pep-0485.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0485.txt b/pep-0485.txt --- a/pep-0485.txt +++ b/pep-0485.txt @@ -636,3 +636,4 @@ sentence-end-double-space: t fill-column: 70 coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 17 20:24:48 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 17 May 2015 18:24:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320098=3A_add_mangle=5Ff?= =?utf-8?q?rom=5F_policy_option=2E?= Message-ID: <20150517182448.26580.45887@psf.io> https://hg.python.org/cpython/rev/df81f9b67736 changeset: 96117:df81f9b67736 user: R David Murray date: Sun May 17 14:24:33 2015 -0400 summary: #20098: add mangle_from_ policy option. This defaults to True in the compat32 policy for backward compatibility, but to False for all new policies. Patch by Milan Oberkirch, with a few tweaks. files: Doc/library/email.policy.rst | 27 +++++++++++++++ Doc/whatsnew/3.5.rst | 6 +++ Lib/email/_policybase.py | 8 ++++ Lib/email/generator.py | 13 ++++-- Lib/test/test_email/test_generator.py | 22 ++++++++++++ Lib/test/test_email/test_policy.py | 2 + Misc/NEWS | 3 + 7 files changed, 76 insertions(+), 5 deletions(-) diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -187,6 +187,18 @@ :const:`False` (the default), defects will be passed to the :meth:`register_defect` method. + + + .. attribute:: mangle_from\_ + + If :const:`True`, lines starting with *"From "* in the body are + escaped by putting a ``>`` in front of them. This parameter is used when + the message is being serialized by a generator. + Default: :const:`False`. + + .. versionadded:: 3.5 + The *mangle_from_* parameter. + The following :class:`Policy` method is intended to be called by code using the email library to create policy instances with custom settings: @@ -319,6 +331,13 @@ :const:`compat32`, that is used as the default policy. Thus the default behavior of the email package is to maintain compatibility with Python 3.2. + The following attributes have values that are different from the + :class:`Policy` default: + + .. attribute:: mangle_from_ + + The default is ``True``. + The class provides the following concrete implementations of the abstract methods of :class:`Policy`: @@ -356,6 +375,14 @@ line breaks and any (RFC invalid) binary data it may contain. +An instance of :class:`Compat32` is provided as a module constant: + +.. data:: compat32 + + An instance of :class:`Compat32`, providing backward compatibility with the + behavior of the email package in Python 3.2. + + .. note:: The documentation below describes new policies that are included in the diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -351,6 +351,12 @@ email ----- +* A new policy option :attr:`~email.policy.Policy.mangle_from_` controls + whether or not lines that start with "From " in email bodies are prefixed with + a '>' character by generators. The default is ``True`` for + :attr:`~email.policy.compat32` and ``False`` for all other policies. + (Contributed by Milan Oberkirch in :issue:`20098`.) + * A new method :meth:`~email.message.Message.get_content_disposition` provides easy access to a canonical value for the :mailheader:`Content-Disposition` header (``None`` if there is no such header). (Contributed by Abhilash Raj diff --git a/Lib/email/_policybase.py b/Lib/email/_policybase.py --- a/Lib/email/_policybase.py +++ b/Lib/email/_policybase.py @@ -149,12 +149,18 @@ during serialization. None or 0 means no line wrapping is done. Default is 78. + mangle_from_ -- a flag that, when True escapes From_ lines in the + body of the message by putting a `>' in front of + them. This is used when the message is being + serialized by a generator. Default: True. + """ raise_on_defect = False linesep = '\n' cte_type = '8bit' max_line_length = 78 + mangle_from_ = False def handle_defect(self, obj, defect): """Based on policy, either raise defect or call register_defect. @@ -266,6 +272,8 @@ replicates the behavior of the email package version 5.1. """ + mangle_from_ = True + def _sanitize_header(self, name, value): # If the header value contains surrogates, return a Header using # the unknown-8bit charset to encode the bytes as encoded words. diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -32,16 +32,16 @@ # Public interface # - def __init__(self, outfp, mangle_from_=True, maxheaderlen=None, *, + def __init__(self, outfp, mangle_from_=None, maxheaderlen=None, *, policy=None): """Create the generator for message flattening. outfp is the output file-like object for writing the message to. It must have a write() method. - Optional mangle_from_ is a flag that, when True (the default), escapes - From_ lines in the body of the message by putting a `>' in front of - them. + Optional mangle_from_ is a flag that, when True (the default if policy + is not set), escapes From_ lines in the body of the message by putting + a `>' in front of them. Optional maxheaderlen specifies the longest length for a non-continued header. When a header line is longer (in characters, with tabs @@ -56,6 +56,9 @@ flatten method is used. """ + + if mangle_from_ is None: + mangle_from_ = True if policy is None else policy.mangle_from_ self._fp = outfp self._mangle_from_ = mangle_from_ self.maxheaderlen = maxheaderlen @@ -449,7 +452,7 @@ Like the Generator base class, except that non-text parts are substituted with a format string representing the part. """ - def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None): + def __init__(self, outfp, mangle_from_=None, maxheaderlen=78, fmt=None): """Like Generator.__init__() except that an additional optional argument is allowed. diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -140,6 +140,28 @@ g.flatten(msg, linesep='\n') self.assertEqual(s.getvalue(), self.typ(expected)) + def test_set_mangle_from_via_policy(self): + source = textwrap.dedent("""\ + Subject: test that + from is mangeld in the body! + + From time to time I write a rhyme. + """) + variants = ( + (None, True), + (policy.compat32, True), + (policy.default, False), + (policy.default.clone(mangle_from_=True), True), + ) + for p, mangle in variants: + expected = source.replace('From ', '>From ') if mangle else source + with self.subTest(policy=p, mangle_from_=mangle): + msg = self.msgmaker(self.typ(source)) + s = self.ioclass() + g = self.genclass(s, policy=p) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + class TestGenerator(TestGeneratorBase, TestEmailBase): diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py --- a/Lib/test/test_email/test_policy.py +++ b/Lib/test/test_email/test_policy.py @@ -22,6 +22,7 @@ 'linesep': '\n', 'cte_type': '8bit', 'raise_on_defect': False, + 'mangle_from_': True, } # These default values are the ones set on email.policy.default. # If any of these defaults change, the docs must be updated. @@ -32,6 +33,7 @@ 'header_factory': email.policy.EmailPolicy.header_factory, 'refold_source': 'long', 'content_manager': email.policy.EmailPolicy.content_manager, + 'mangle_from_': False, }) # For each policy under test, we give here what we expect the defaults to diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Library ------- +- Issue #20098: New mangle_from_ policy option for email, default True + for compat32, but False for all other policies. + - Issue #24211: The email library now supports RFC 6532: it can generate headers using utf-8 instead of encoded words. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 20:50:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 17 May 2015 18:50:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMTU1?= =?utf-8?q?=3A_Add_File_Handlers_subsection_with_createfilehandler_to_Tkin?= =?utf-8?q?ter?= Message-ID: <20150517185021.4233.41743@psf.io> https://hg.python.org/cpython/rev/e8dd65c7fb6b changeset: 96118:e8dd65c7fb6b branch: 2.7 parent: 96113:247f003b42ea user: Terry Jan Reedy date: Sun May 17 14:49:20 2015 -0400 summary: Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter doc. Remove obsolete example from FAQ. Patch by Martin Panter. files: Doc/faq/gui.rst | 25 +------------ Doc/library/tkinter.rst | 50 +++++++++++++++++++++++++++++ Misc/NEWS | 6 +++ 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -125,30 +125,11 @@ Can I have Tk events handled while waiting for I/O? --------------------------------------------------- -Yes, and you don't even need threads! But you'll have to restructure your I/O +On platforms other than Windows, yes, and you don't even +need threads! But you'll have to restructure your I/O code a bit. Tk has the equivalent of Xt's :c:func:`XtAddInput()` call, which allows you to register a callback function which will be called from the Tk mainloop when -I/O is possible on a file descriptor. Here's what you need:: - - from Tkinter import tkinter - tkinter.createfilehandler(file, mask, callback) - -The file may be a Python file or socket object (actually, anything with a -fileno() method), or an integer file descriptor. The mask is one of the -constants tkinter.READABLE or tkinter.WRITABLE. The callback is called as -follows:: - - callback(file, mask) - -You must unregister the callback when you're done, using :: - - tkinter.deletefilehandler(file) - -Note: since you don't know *how many bytes* are available for reading, you can't -use the Python file object's read or readline methods, since these will insist -on reading a predefined number of bytes. For sockets, the :meth:`recv` or -:meth:`recvfrom` methods will work fine; for other files, use -``os.read(file.fileno(), maxbytecount)``. +I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. I can't get key bindings to work in Tkinter: why? diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -817,3 +817,53 @@ deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used. + +.. _tkinter-file-handlers: + +File Handlers +------------- + +Tk allows you to register and unregister a callback function which will be +called from the Tk mainloop when I/O is possible on a file descriptor. +Only one handler may be registered per file descriptor. Example code:: + + import Tkinter + widget = Tkinter.Tk() + mask = Tkinter.READABLE | Tkinter.WRITABLE + widget.tk.createfilehandler(file, mask, callback) + ... + widget.tk.deletefilehandler(file) + +This feature is not available on Windows. + +Since you don't know how many bytes are available for reading, you may not +want to use the :class:`~io.BufferedIOBase` or :class:`~io.TextIOBase` +:meth:`~io.BufferedIOBase.read` or :meth:`~io.IOBase.readline` methods, +since these will insist on reading a predefined number of bytes. +For sockets, the :meth:`~socket.socket.recv` or +:meth:`~socket.socket.recvfrom` methods will work fine; for other files, +use raw reads or ``os.read(file.fileno(), maxbytecount)``. + + +.. method:: Widget.tk.createfilehandler(file, mask, func) + + Registers the file handler callback function *func*. The *file* argument + may either be an object with a :meth:`~io.IOBase.fileno` method (such as + a file or socket object), or an integer file descriptor. The *mask* + argument is an ORed combination of any of the three constants below. + The callback is called as follows:: + + callback(file, mask) + + +.. method:: Widget.tk.deletefilehandler(file) + + Unregisters a file handler. + + +.. data:: READABLE + WRITABLE + EXCEPTION + + Constants used in the *mask* arguments. + diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,12 @@ - Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for decoding unicode literals. + +Documentation +------------- + +- Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter + doc. Remove obsolete example from FAQ. Patch by Martin Panter. What's New in Python 2.7.10 release candidate 1? -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 20:50:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 17 May 2015 18:50:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150517185021.21148.54903@psf.io> https://hg.python.org/cpython/rev/c060d20651fa changeset: 96120:c060d20651fa parent: 96117:df81f9b67736 parent: 96119:1efcb7b6ec8a user: Terry Jan Reedy date: Sun May 17 14:50:06 2015 -0400 summary: Merge with 3.4 files: Doc/faq/gui.rst | 25 +------------ Doc/library/tkinter.rst | 50 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -139,30 +139,11 @@ Can I have Tk events handled while waiting for I/O? --------------------------------------------------- -Yes, and you don't even need threads! But you'll have to restructure your I/O +On platforms other than Windows, yes, and you don't even +need threads! But you'll have to restructure your I/O code a bit. Tk has the equivalent of Xt's :c:func:`XtAddInput()` call, which allows you to register a callback function which will be called from the Tk mainloop when -I/O is possible on a file descriptor. Here's what you need:: - - from Tkinter import tkinter - tkinter.createfilehandler(file, mask, callback) - -The file may be a Python file or socket object (actually, anything with a -fileno() method), or an integer file descriptor. The mask is one of the -constants tkinter.READABLE or tkinter.WRITABLE. The callback is called as -follows:: - - callback(file, mask) - -You must unregister the callback when you're done, using :: - - tkinter.deletefilehandler(file) - -Note: since you don't know *how many bytes* are available for reading, you can't -use the Python file object's read or readline methods, since these will insist -on reading a predefined number of bytes. For sockets, the :meth:`recv` or -:meth:`recvfrom` methods will work fine; for other files, use -``os.read(file.fileno(), maxbytecount)``. +I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. I can't get key bindings to work in Tkinter: why? diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -794,3 +794,53 @@ reference to the image. When the last Python reference to the image object is deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used. + + +.. _tkinter-file-handlers: + +File Handlers +------------- + +Tk allows you to register and unregister a callback function which will be +called from the Tk mainloop when I/O is possible on a file descriptor. +Only one handler may be registered per file descriptor. Example code:: + + import tkinter + widget = tkinter.Tk() + mask = tkinter.READABLE | tkinter.WRITABLE + widget.tk.createfilehandler(file, mask, callback) + ... + widget.tk.deletefilehandler(file) + +This feature is not available on Windows. + +Since you don't know how many bytes are available for reading, you may not +want to use the :class:`~io.BufferedIOBase` or :class:`~io.TextIOBase` +:meth:`~io.BufferedIOBase.read` or :meth:`~io.IOBase.readline` methods, +since these will insist on reading a predefined number of bytes. +For sockets, the :meth:`~socket.socket.recv` or +:meth:`~socket.socket.recvfrom` methods will work fine; for other files, +use raw reads or ``os.read(file.fileno(), maxbytecount)``. + + +.. method:: Widget.tk.createfilehandler(file, mask, func) + + Registers the file handler callback function *func*. The *file* argument + may either be an object with a :meth:`~io.IOBase.fileno` method (such as + a file or socket object), or an integer file descriptor. The *mask* + argument is an ORed combination of any of the three constants below. + The callback is called as follows:: + + callback(file, mask) + + +.. method:: Widget.tk.deletefilehandler(file) + + Unregisters a file handler. + + +.. data:: READABLE + WRITABLE + EXCEPTION + + Constants used in the *mask* arguments. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 20:50:21 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 17 May 2015 18:50:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTU1?= =?utf-8?q?=3A_Add_File_Handlers_subsection_with_createfilehandler_to_tkin?= =?utf-8?q?ter?= Message-ID: <20150517185021.21166.93012@psf.io> https://hg.python.org/cpython/rev/1efcb7b6ec8a changeset: 96119:1efcb7b6ec8a branch: 3.4 parent: 96114:ba271f116f94 user: Terry Jan Reedy date: Sun May 17 14:49:26 2015 -0400 summary: Issue #22155: Add File Handlers subsection with createfilehandler to tkinter doc. Remove obsolete example from FAQ. Patch by Martin Panter. files: Doc/faq/gui.rst | 25 +------------ Doc/library/tkinter.rst | 50 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -139,30 +139,11 @@ Can I have Tk events handled while waiting for I/O? --------------------------------------------------- -Yes, and you don't even need threads! But you'll have to restructure your I/O +On platforms other than Windows, yes, and you don't even +need threads! But you'll have to restructure your I/O code a bit. Tk has the equivalent of Xt's :c:func:`XtAddInput()` call, which allows you to register a callback function which will be called from the Tk mainloop when -I/O is possible on a file descriptor. Here's what you need:: - - from Tkinter import tkinter - tkinter.createfilehandler(file, mask, callback) - -The file may be a Python file or socket object (actually, anything with a -fileno() method), or an integer file descriptor. The mask is one of the -constants tkinter.READABLE or tkinter.WRITABLE. The callback is called as -follows:: - - callback(file, mask) - -You must unregister the callback when you're done, using :: - - tkinter.deletefilehandler(file) - -Note: since you don't know *how many bytes* are available for reading, you can't -use the Python file object's read or readline methods, since these will insist -on reading a predefined number of bytes. For sockets, the :meth:`recv` or -:meth:`recvfrom` methods will work fine; for other files, use -``os.read(file.fileno(), maxbytecount)``. +I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. I can't get key bindings to work in Tkinter: why? diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -794,3 +794,53 @@ reference to the image. When the last Python reference to the image object is deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used. + + +.. _tkinter-file-handlers: + +File Handlers +------------- + +Tk allows you to register and unregister a callback function which will be +called from the Tk mainloop when I/O is possible on a file descriptor. +Only one handler may be registered per file descriptor. Example code:: + + import tkinter + widget = tkinter.Tk() + mask = tkinter.READABLE | tkinter.WRITABLE + widget.tk.createfilehandler(file, mask, callback) + ... + widget.tk.deletefilehandler(file) + +This feature is not available on Windows. + +Since you don't know how many bytes are available for reading, you may not +want to use the :class:`~io.BufferedIOBase` or :class:`~io.TextIOBase` +:meth:`~io.BufferedIOBase.read` or :meth:`~io.IOBase.readline` methods, +since these will insist on reading a predefined number of bytes. +For sockets, the :meth:`~socket.socket.recv` or +:meth:`~socket.socket.recvfrom` methods will work fine; for other files, +use raw reads or ``os.read(file.fileno(), maxbytecount)``. + + +.. method:: Widget.tk.createfilehandler(file, mask, func) + + Registers the file handler callback function *func*. The *file* argument + may either be an object with a :meth:`~io.IOBase.fileno` method (such as + a file or socket object), or an integer file descriptor. The *mask* + argument is an ORed combination of any of the three constants below. + The callback is called as follows:: + + callback(file, mask) + + +.. method:: Widget.tk.deletefilehandler(file) + + Unregisters a file handler. + + +.. data:: READABLE + WRITABLE + EXCEPTION + + Constants used in the *mask* arguments. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 20:56:31 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 17 May 2015 18:56:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTU1?= =?utf-8?q?=3A_News_entry=2E?= Message-ID: <20150517185631.32309.30535@psf.io> https://hg.python.org/cpython/rev/8bd9da5635fe changeset: 96121:8bd9da5635fe branch: 3.4 parent: 96119:1efcb7b6ec8a user: Terry Jan Reedy date: Sun May 17 14:53:28 2015 -0400 summary: Issue #22155: News entry. files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -265,6 +265,9 @@ Documentation ------------- +- Issue #22155: Add File Handlers subsection with createfilehandler to tkinter + doc. Remove obsolete example from FAQ. Patch by Martin Panter. + - Issue #24029: Document the name binding behavior for submodule imports. - Issue #24077: Fix typo in man page for -I command option: -s, not -S. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 20:56:31 2015 From: python-checkins at python.org (terry.reedy) Date: Sun, 17 May 2015 18:56:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322155=3A_News_entry=2E?= Message-ID: <20150517185631.21156.35365@psf.io> https://hg.python.org/cpython/rev/850cbd54cc73 changeset: 96122:850cbd54cc73 parent: 96120:c060d20651fa parent: 96121:8bd9da5635fe user: Terry Jan Reedy date: Sun May 17 14:56:20 2015 -0400 summary: Issue #22155: News entry. files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -160,6 +160,9 @@ Documentation ------------- +- Issue #22155: Add File Handlers subsection with createfilehandler to tkinter + doc. Remove obsolete example from FAQ. Patch by Martin Panter. + - Issue #24029: Document the name binding behavior for submodule imports. - Issue #24077: Fix typo in man page for -I command option: -s, not -S -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 23:37:46 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 17 May 2015 21:37:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNzU3?= =?utf-8?q?=3A__Only_call_the_concrete_list_API_for_exact_lists=2E?= Message-ID: <20150517213745.39253.8584@psf.io> https://hg.python.org/cpython/rev/b6121a4afad7 changeset: 96123:b6121a4afad7 branch: 2.7 parent: 96118:e8dd65c7fb6b user: Raymond Hettinger date: Sun May 17 14:37:39 2015 -0700 summary: Issue #23757: Only call the concrete list API for exact lists. files: Lib/test/seq_tests.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Objects/abstract.c | 2 +- 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -84,6 +84,14 @@ 'Test multiple tiers of iterators' return chain(imap(lambda x:x, iterfunc(IterGen(Sequence(seqn))))) +class LyingTuple(tuple): + def __iter__(self): + yield 1 + +class LyingList(list): + def __iter__(self): + yield 1 + class CommonTest(unittest.TestCase): # The type to be tested type2test = None @@ -130,6 +138,10 @@ self.assertRaises(TypeError, self.type2test, IterNoNext(s)) self.assertRaises(ZeroDivisionError, self.type2test, IterGenExc(s)) + # Issue #23757 + self.assertEqual(self.type2test(LyingTuple((2,))), self.type2test((1,))) + self.assertEqual(self.type2test(LyingList([2])), self.type2test([1])) + def test_truth(self): self.assertFalse(self.type2test()) self.assertTrue(self.type2test([42])) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -51,6 +51,9 @@ - Issue #23971: Fix underestimated presizing in dict.fromkeys(). +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API + when the data was a list subclass. + - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2169,7 +2169,7 @@ Py_INCREF(v); return v; } - if (PyList_Check(v)) + if (PyList_CheckExact(v)) return PyList_AsTuple(v); /* Get iterator. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 23:47:09 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 17 May 2015 21:47:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzU3?= =?utf-8?q?=3A__Only_call_the_concrete_list_API_for_exact_lists=2E?= Message-ID: <20150517214709.4229.10206@psf.io> https://hg.python.org/cpython/rev/c79530e08985 changeset: 96124:c79530e08985 branch: 3.4 parent: 96121:8bd9da5635fe user: Raymond Hettinger date: Sun May 17 14:45:58 2015 -0700 summary: Issue #23757: Only call the concrete list API for exact lists. files: Lib/test/seq_tests.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Objects/abstract.c | 2 +- 3 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -85,6 +85,14 @@ 'Test multiple tiers of iterators' return chain(map(lambda x:x, iterfunc(IterGen(Sequence(seqn))))) +class LyingTuple(tuple): + def __iter__(self): + yield 1 + +class LyingList(list): + def __iter__(self): + yield 1 + class CommonTest(unittest.TestCase): # The type to be tested type2test = None @@ -131,6 +139,10 @@ self.assertRaises(TypeError, self.type2test, IterNoNext(s)) self.assertRaises(ZeroDivisionError, self.type2test, IterGenExc(s)) + # Issue #23757 + self.assertEqual(self.type2test(LyingTuple((2,))), self.type2test((1,))) + self.assertEqual(self.type2test(LyingList([2])), self.type2test([1])) + def test_truth(self): self.assertFalse(self.type2test()) self.assertTrue(self.type2test([42])) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API + when the data was a list subclass. + - Issue #24096: Make warnings.warn_explicit more robust against mutation of the warnings.filters list. diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1636,7 +1636,7 @@ Py_INCREF(v); return v; } - if (PyList_Check(v)) + if (PyList_CheckExact(v)) return PyList_AsTuple(v); /* Get iterator. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 17 23:47:10 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 17 May 2015 21:47:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150517214710.125538.64651@psf.io> https://hg.python.org/cpython/rev/257ea04df092 changeset: 96125:257ea04df092 parent: 96122:850cbd54cc73 parent: 96124:c79530e08985 user: Raymond Hettinger date: Sun May 17 14:47:00 2015 -0700 summary: merge files: Lib/test/seq_tests.py | 12 ++++++++++++ Objects/abstract.c | 2 +- 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -85,6 +85,14 @@ 'Test multiple tiers of iterators' return chain(map(lambda x:x, iterfunc(IterGen(Sequence(seqn))))) +class LyingTuple(tuple): + def __iter__(self): + yield 1 + +class LyingList(list): + def __iter__(self): + yield 1 + class CommonTest(unittest.TestCase): # The type to be tested type2test = None @@ -131,6 +139,10 @@ self.assertRaises(TypeError, self.type2test, IterNoNext(s)) self.assertRaises(ZeroDivisionError, self.type2test, IterGenExc(s)) + # Issue #23757 + self.assertEqual(self.type2test(LyingTuple((2,))), self.type2test((1,))) + self.assertEqual(self.type2test(LyingList([2])), self.type2test([1])) + def test_truth(self): self.assertFalse(self.type2test()) self.assertTrue(self.type2test([42])) diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1681,7 +1681,7 @@ Py_INCREF(v); return v; } - if (PyList_Check(v)) + if (PyList_CheckExact(v)) return PyList_AsTuple(v); /* Get iterator. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 01:38:13 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 17 May 2015 23:38:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2324211=3A_Add_missing_do?= =?utf-8?q?cs_for_SMTPUTF8_policy_instance=2E?= Message-ID: <20150517233813.26568.95224@psf.io> https://hg.python.org/cpython/rev/4a254750ad20 changeset: 96127:4a254750ad20 user: R David Murray date: Sun May 17 19:36:16 2015 -0400 summary: #24211: Add missing docs for SMTPUTF8 policy instance. files: Doc/library/email.policy.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -534,6 +534,14 @@ Like ``default``, but with ``linesep`` set to ``\r\n``, which is RFC compliant. +.. data:: SMTPUTF8 + + The same as ``SMTP`` except that :attr:`~EmailPolicy.utf8` is ``True``. + Useful for serializing messages to a message store without using encoded + words in the headers. Should only be used for SMTP trasmission if the + sender or recipient addresses have non-ASCII characters (the + :meth:`smtplib.SMTP.send_message` method handles this automatically). + .. data:: HTTP Suitable for serializing headers with for use in HTTP traffic. Like -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 01:38:13 2015 From: python-checkins at python.org (r.david.murray) Date: Sun, 17 May 2015 23:38:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2324218=3A_Add_SMTPUTF8_s?= =?utf-8?q?upport_to_send=5Fmessage=2E?= Message-ID: <20150517233813.44681.22800@psf.io> https://hg.python.org/cpython/rev/30795a477f85 changeset: 96126:30795a477f85 user: R David Murray date: Sun May 17 19:27:22 2015 -0400 summary: #24218: Add SMTPUTF8 support to send_message. Reviewed by Maciej Szulik. files: Doc/library/smtplib.rst | 12 +++++- Doc/whatsnew/3.5.rst | 6 ++- Lib/smtplib.py | 29 +++++++++++++++- Lib/test/test_smtplib.py | 47 +++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -467,7 +467,7 @@ If *from_addr* is ``None`` or *to_addrs* is ``None``, ``send_message`` fills those arguments with addresses extracted from the headers of *msg* as - specified in :rfc:`2822`\: *from_addr* is set to the :mailheader:`Sender` + specified in :rfc:`5322`\: *from_addr* is set to the :mailheader:`Sender` field if it is present, and otherwise to the :mailheader:`From` field. *to_adresses* combines the values (if any) of the :mailheader:`To`, :mailheader:`Cc`, and :mailheader:`Bcc` fields from *msg*. If exactly one @@ -482,10 +482,18 @@ calls :meth:`sendmail` to transmit the resulting message. Regardless of the values of *from_addr* and *to_addrs*, ``send_message`` does not transmit any :mailheader:`Bcc` or :mailheader:`Resent-Bcc` headers that may appear - in *msg*. + in *msg*. If any of the addresses in *from_addr* and *to_addrs* contain + non-ASCII characters and the server does not advertise ``SMTPUTF8`` support, + an :exc:`SMTPNotSupported` error is raised. Otherwise the ``Message`` is + serialized with a clone of its :mod:`~email.policy` with the + :attr:`~email.policy.EmailPolicy.utf8` attribute set to ``True``, and + ``SMTPUTF8`` and ``BODY=8BITMIME`` are added to *mail_options*. .. versionadded:: 3.2 + .. versionadded:: 3.5 + Support for internationalized addresses (``SMTPUTF8``). + .. method:: SMTP.quit() diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -557,8 +557,10 @@ :class:`smtplib.SMTP`. (Contributed by Gavin Chappell and Maciej Szulik in :issue:`16914`.) -* :mod:`smtplib` now support :rfc:`6531` (SMTPUTF8). (Contributed by - Milan Oberkirch and R. David Murray in :issue:`22027`.) +* :mod:`smtplib` now supports :rfc:`6531` (SMTPUTF8) in both the + :meth:`~smtplib.SMTP.sendmail` and :meth:`~smtplib.SMTP.send_message` + commands. (Contributed by Milan Oberkirch and R. David Murray in + :issue:`22027`.) sndhdr ------ diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -872,7 +872,13 @@ to_addr, any Bcc field (or Resent-Bcc field, when the Message is a resent) of the Message object won't be transmitted. The Message object is then serialized using email.generator.BytesGenerator and - sendmail is called to transmit the message. + sendmail is called to transmit the message. If the sender or any of + the recipient addresses contain non-ASCII and the server advertises the + SMTPUTF8 capability, the policy is cloned with utf8 set to True for the + serialization, and SMTPUTF8 and BODY=8BITMIME are asserted on the send. + If the server does not support SMTPUTF8, an SMPTNotSupported error is + raised. Otherwise the generator is called without modifying the + policy. """ # 'Resent-Date' is a mandatory field if the Message is resent (RFC 2822 @@ -885,6 +891,7 @@ # option allowing the user to enable the heuristics. (It should be # possible to guess correctly almost all of the time.) + self.ehlo_or_helo_if_needed() resent = msg.get_all('Resent-Date') if resent is None: header_prefix = '' @@ -900,14 +907,30 @@ if to_addrs is None: addr_fields = [f for f in (msg[header_prefix + 'To'], msg[header_prefix + 'Bcc'], - msg[header_prefix + 'Cc']) if f is not None] + msg[header_prefix + 'Cc']) + if f is not None] to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)] # Make a local copy so we can delete the bcc headers. msg_copy = copy.copy(msg) del msg_copy['Bcc'] del msg_copy['Resent-Bcc'] + international = False + try: + ''.join([from_addr, *to_addrs]).encode('ascii') + except UnicodeEncodeError: + if not self.has_extn('smtputf8'): + raise SMTPNotSupportedError( + "One or more source or delivery addresses require" + " internationalized email support, but the server" + " does not advertise the required SMTPUTF8 capability") + international = True with io.BytesIO() as bytesmsg: - g = email.generator.BytesGenerator(bytesmsg) + if international: + g = email.generator.BytesGenerator( + bytesmsg, policy=msg.policy.clone(utf8=True)) + mail_options += ['SMTPUTF8', 'BODY=8BITMIME'] + else: + g = email.generator.BytesGenerator(bytesmsg) g.flatten(msg_copy, linesep='\r\n') flatmsg = bytesmsg.getvalue() return self.sendmail(from_addr, to_addrs, flatmsg, mail_options, diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -1,5 +1,6 @@ import asyncore import email.mime.text +from email.message import EmailMessage import email.utils import socket import smtpd @@ -10,7 +11,7 @@ import time import select import errno -import base64 +import textwrap import unittest from test import support, mock_socket @@ -1029,6 +1030,8 @@ @unittest.skipUnless(threading, 'Threading required for this test.') class SMTPUTF8SimTests(unittest.TestCase): + maxDiff = None + def setUp(self): self.real_getfqdn = socket.getfqdn socket.getfqdn = mock_socket.getfqdn @@ -1096,6 +1099,48 @@ self.assertIn('SMTPUTF8', self.serv.last_mail_options) self.assertEqual(self.serv.last_rcpt_options, []) + def test_send_message_uses_smtputf8_if_addrs_non_ascii(self): + msg = EmailMessage() + msg['From'] = "P?olo " + msg['To'] = 'Dinsdale' + msg['Subject'] = 'Nudge nudge, wink, wink \u1F609' + # XXX I don't know why I need two \n's here, but this is an existing + # bug (if it is one) and not a problem with the new functionality. + msg.set_content("oh l? l?, know what I mean, know what I mean?\n\n") + # XXX smtpd converts received /r/n to /n, so we can't easily test that + # we are successfully sending /r/n :(. + expected = textwrap.dedent("""\ + From: P?olo + To: Dinsdale + Subject: Nudge nudge, wink, wink \u1F609 + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: 8bit + MIME-Version: 1.0 + + oh l? l?, know what I mean, know what I mean? + """) + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + self.assertEqual(smtp.send_message(msg), {}) + self.assertEqual(self.serv.last_mailfrom, 'f?o at bar.com') + self.assertEqual(self.serv.last_rcpttos, ['Dinsdale']) + self.assertEqual(self.serv.last_message.decode(), expected) + self.assertIn('BODY=8BITMIME', self.serv.last_mail_options) + self.assertIn('SMTPUTF8', self.serv.last_mail_options) + self.assertEqual(self.serv.last_rcpt_options, []) + + def test_send_message_error_on_non_ascii_addrs_if_no_smtputf8(self): + msg = EmailMessage() + msg['From'] = "P?olo " + msg['To'] = 'Dinsdale' + msg['Subject'] = 'Nudge nudge, wink, wink \u1F609' + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', timeout=3) + self.addCleanup(smtp.close) + self.assertRaises(smtplib.SMTPNotSupportedError, + smtp.send_message(msg)) + @support.reap_threads def test_main(verbose=None): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 02:45:00 2015 From: python-checkins at python.org (r.david.murray) Date: Mon, 18 May 2015 00:45:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313866=3A_add_*quo?= =?utf-8?q?te=5Fvia*_argument_to_urlencode=2E?= Message-ID: <20150518004500.4233.30130@psf.io> https://hg.python.org/cpython/rev/c7d82a7a9dea changeset: 96128:c7d82a7a9dea user: R David Murray date: Sun May 17 20:44:50 2015 -0400 summary: Issue #13866: add *quote_via* argument to urlencode. Patch by samwyse, completed by Arnon Yaari, and reviewed by Martin Panter. files: Doc/library/urllib.parse.rst | 20 +++++++++++++--- Doc/whatsnew/3.5.rst | 4 +++ Lib/test/test_urlparse.py | 10 ++++++++ Lib/urllib/parse.py | 29 ++++++++++++----------- Misc/NEWS | 2 + 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -519,7 +519,8 @@ Example: ``unquote_to_bytes('a%26%EF')`` yields ``b'a&\xef'``. -.. function:: urlencode(query, doseq=False, safe='', encoding=None, errors=None) +.. function:: urlencode(query, doseq=False, safe='', encoding=None, \ + errors=None, quote_via=quote_plus) Convert a mapping object or a sequence of two-element tuples, which may contain :class:`str` or :class:`bytes` objects, to a "percent-encoded" @@ -528,8 +529,16 @@ properly encoded to bytes, otherwise it would result in a :exc:`TypeError`. The resulting string is a series of ``key=value`` pairs separated by ``'&'`` - characters, where both *key* and *value* are quoted using :func:`quote_plus` - above. When a sequence of two-element tuples is used as the *query* + characters, where both *key* and *value* are quoted using the *quote_via* + function. By default, :func:`quote_plus` is used to quote the values, which + means spaces are quoted as a ``'+'`` character and '/' characters are + encoded as ``%2F``, which follows the standard for GET requests + (``application/x-www-form-urlencoded``). An alternate function that can be + passed as *quote_via* is :func:`quote`, which will encode spaces as ``%20`` + and not encode '/' characters. For maximum control of what is quoted, use + ``quote`` and specify a value for *safe*. + + When a sequence of two-element tuples is used as the *query* argument, the first element of each tuple is a key and the second is a value. The value element in itself can be a sequence and in that case, if the optional parameter *doseq* is evaluates to *True*, individual @@ -538,7 +547,7 @@ string will match the order of parameter tuples in the sequence. The *safe*, *encoding*, and *errors* parameters are passed down to - :func:`quote_plus` (the *encoding* and *errors* parameters are only passed + *quote_via* (the *encoding* and *errors* parameters are only passed when a query element is a :class:`str`). To reverse this encoding process, :func:`parse_qs` and :func:`parse_qsl` are @@ -550,6 +559,9 @@ .. versionchanged:: 3.2 Query parameter supports bytes and string objects. + .. versionadded:: 3.5 + *quote_via* parameter. + .. seealso:: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -622,6 +622,10 @@ sent. (Contributed by Matej Cepl in :issue:`19494` and Akshit Khurana in :issue:`7159`.) +* A new :func:`~urllib.parse.urlencode` parameter *quote_via* provides a way to + control the encoding of query parts if needed. (Contributed by Samwyse and + Arnon Yaari in :issue:`13866`.) + wsgiref ------- diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -785,6 +785,16 @@ result = urllib.parse.urlencode({'a': Trivial()}, True) self.assertEqual(result, 'a=trivial') + def test_urlencode_quote_via(self): + result = urllib.parse.urlencode({'a': 'some value'}) + self.assertEqual(result, "a=some+value") + result = urllib.parse.urlencode({'a': 'some value/another'}, + quote_via=urllib.parse.quote) + self.assertEqual(result, "a=some%20value%2Fanother") + result = urllib.parse.urlencode({'a': 'some value/another'}, + safe='/', quote_via=urllib.parse.quote) + self.assertEqual(result, "a=some%20value/another") + def test_quote_from_bytes(self): self.assertRaises(TypeError, urllib.parse.quote_from_bytes, 'foo') result = urllib.parse.quote_from_bytes(b'archaeological arcana') diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -750,7 +750,8 @@ _safe_quoters[safe] = quoter = Quoter(safe).__getitem__ return ''.join([quoter(char) for char in bs]) -def urlencode(query, doseq=False, safe='', encoding=None, errors=None): +def urlencode(query, doseq=False, safe='', encoding=None, errors=None, + quote_via=quote_plus): """Encode a dict or sequence of two-element tuples into a URL query string. If any values in the query arg are sequences and doseq is true, each @@ -762,8 +763,8 @@ The components of a query arg may each be either a string or a bytes type. - The safe, encoding, and errors parameters are passed down to quote_plus() - (encoding and errors only if a component is a str). + The safe, encoding, and errors parameters are passed down to the function + specified by quote_via (encoding and errors only if a component is a str). """ if hasattr(query, "items"): @@ -789,27 +790,27 @@ if not doseq: for k, v in query: if isinstance(k, bytes): - k = quote_plus(k, safe) + k = quote_via(k, safe) else: - k = quote_plus(str(k), safe, encoding, errors) + k = quote_via(str(k), safe, encoding, errors) if isinstance(v, bytes): - v = quote_plus(v, safe) + v = quote_via(v, safe) else: - v = quote_plus(str(v), safe, encoding, errors) + v = quote_via(str(v), safe, encoding, errors) l.append(k + '=' + v) else: for k, v in query: if isinstance(k, bytes): - k = quote_plus(k, safe) + k = quote_via(k, safe) else: - k = quote_plus(str(k), safe, encoding, errors) + k = quote_via(str(k), safe, encoding, errors) if isinstance(v, bytes): - v = quote_plus(v, safe) + v = quote_via(v, safe) l.append(k + '=' + v) elif isinstance(v, str): - v = quote_plus(v, safe, encoding, errors) + v = quote_via(v, safe, encoding, errors) l.append(k + '=' + v) else: try: @@ -817,15 +818,15 @@ x = len(v) except TypeError: # not a sequence - v = quote_plus(str(v), safe, encoding, errors) + v = quote_via(str(v), safe, encoding, errors) l.append(k + '=' + v) else: # loop over the sequence for elt in v: if isinstance(elt, bytes): - elt = quote_plus(elt, safe) + elt = quote_via(elt, safe) else: - elt = quote_plus(str(elt), safe, encoding, errors) + elt = quote_via(str(elt), safe, encoding, errors) l.append(k + '=' + elt) return '&'.join(l) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,8 @@ Library ------- +- Issue #13866: *quote_via* argument added to urllib.parse.urlencode. + - Issue #20098: New mangle_from_ policy option for email, default True for compat32, but False for all other policies. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 03:59:28 2015 From: python-checkins at python.org (zach.ware) Date: Mon, 18 May 2015 01:59:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321337=3A_Add_bare?= =?utf-8?q?-bones_Tix_test?= Message-ID: <20150518015928.10800.26522@psf.io> https://hg.python.org/cpython/rev/eeea91d0506b changeset: 96129:eeea91d0506b user: Zachary Ware date: Sun May 17 20:55:42 2015 -0500 summary: Issue #21337: Add bare-bones Tix test All this does is confirm that Tix is available on Windows, which should always be the case (if _tkinter itself is available). files: Lib/test/test_tcl.py | 707 +------------------------------ 1 files changed, 18 insertions(+), 689 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tix.py copy from Lib/test/test_tcl.py copy to Lib/test/test_tix.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tix.py @@ -1,703 +1,32 @@ import unittest -import re +from test import support import sys -import os -from test import support # Skip this test if the _tkinter module wasn't built. _tkinter = support.import_module('_tkinter') -# Make sure tkinter._fix runs to set up the environment -tkinter = support.import_fresh_module('tkinter') +# Skip test if tk cannot be initialized. +support.requires('gui') -from tkinter import Tcl -from _tkinter import TclError +from tkinter import tix, TclError -try: - from _testcapi import INT_MAX, PY_SSIZE_T_MAX -except ImportError: - INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) - -_tk_patchlevel = None -def get_tk_patchlevel(): - global _tk_patchlevel - if _tk_patchlevel is None: - tcl = Tcl() - patchlevel = tcl.call('info', 'patchlevel') - m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel) - major, minor, releaselevel, serial = m.groups() - major, minor, serial = int(major), int(minor), int(serial) - releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] - if releaselevel == 'final': - _tk_patchlevel = major, minor, serial, releaselevel, 0 - else: - _tk_patchlevel = major, minor, 0, releaselevel, serial - return _tk_patchlevel - - -class TkinterTest(unittest.TestCase): - - def testFlattenLen(self): - # flatten() - self.assertRaises(TypeError, _tkinter._flatten, True) - - -class TclTest(unittest.TestCase): +class TestTix(unittest.TestCase): def setUp(self): - self.interp = Tcl() - self.wantobjects = self.interp.tk.wantobjects() + try: + self.root = tix.Tk() + except TclError: + if sys.platform.startswith('win'): + self.fail('Tix should always be available on Windows') + self.skipTest('Tix not available') + else: + self.addCleanup(self.root.destroy) - def testEval(self): - tcl = self.interp - tcl.eval('set a 1') - self.assertEqual(tcl.eval('set a'),'1') + def test_tix_available(self): + # this test is just here to make setUp run + pass - def test_eval_null_in_result(self): - tcl = self.interp - self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b') - def testEvalException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.eval,'set a') - - def testEvalException2(self): - tcl = self.interp - self.assertRaises(TclError,tcl.eval,'this is wrong') - - def testCall(self): - tcl = self.interp - tcl.call('set','a','1') - self.assertEqual(tcl.call('set','a'),'1') - - def testCallException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.call,'set','a') - - def testCallException2(self): - tcl = self.interp - self.assertRaises(TclError,tcl.call,'this','is','wrong') - - def testSetVar(self): - tcl = self.interp - tcl.setvar('a','1') - self.assertEqual(tcl.eval('set a'),'1') - - def testSetVarArray(self): - tcl = self.interp - tcl.setvar('a(1)','1') - self.assertEqual(tcl.eval('set a(1)'),'1') - - def testGetVar(self): - tcl = self.interp - tcl.eval('set a 1') - self.assertEqual(tcl.getvar('a'),'1') - - def testGetVarArray(self): - tcl = self.interp - tcl.eval('set a(1) 1') - self.assertEqual(tcl.getvar('a(1)'),'1') - - def testGetVarException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.getvar,'a') - - def testGetVarArrayException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.getvar,'a(1)') - - def testUnsetVar(self): - tcl = self.interp - tcl.setvar('a',1) - self.assertEqual(tcl.eval('info exists a'),'1') - tcl.unsetvar('a') - self.assertEqual(tcl.eval('info exists a'),'0') - - def testUnsetVarArray(self): - tcl = self.interp - tcl.setvar('a(1)',1) - tcl.setvar('a(2)',2) - self.assertEqual(tcl.eval('info exists a(1)'),'1') - self.assertEqual(tcl.eval('info exists a(2)'),'1') - tcl.unsetvar('a(1)') - self.assertEqual(tcl.eval('info exists a(1)'),'0') - self.assertEqual(tcl.eval('info exists a(2)'),'1') - - def testUnsetVarException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.unsetvar,'a') - - def get_integers(self): - integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63) - # bignum was added in Tcl 8.5, but its support is able only since 8.5.8 - if (get_tk_patchlevel() >= (8, 6, 0, 'final') or - (8, 5, 8) <= get_tk_patchlevel() < (8, 6)): - integers += (2**63, -2**63-1, 2**1000, -2**1000) - return integers - - def test_getint(self): - tcl = self.interp.tk - for i in self.get_integers(): - self.assertEqual(tcl.getint(' %d ' % i), i) - if tcl_version >= (8, 5): - self.assertEqual(tcl.getint(' %#o ' % i), i) - self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i) - self.assertEqual(tcl.getint(' %#x ' % i), i) - if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - self.assertRaises(TclError, tcl.getint, str(2**1000)) - self.assertEqual(tcl.getint(42), 42) - self.assertRaises(TypeError, tcl.getint) - self.assertRaises(TypeError, tcl.getint, '42', '10') - self.assertRaises(TypeError, tcl.getint, b'42') - self.assertRaises(TypeError, tcl.getint, 42.0) - self.assertRaises(TclError, tcl.getint, 'a') - self.assertRaises((TypeError, ValueError, TclError), - tcl.getint, '42\0') - self.assertRaises((UnicodeEncodeError, ValueError, TclError), - tcl.getint, '42\ud800') - - def test_getdouble(self): - tcl = self.interp.tk - self.assertEqual(tcl.getdouble(' 42 '), 42.0) - self.assertEqual(tcl.getdouble(' 42.5 '), 42.5) - self.assertEqual(tcl.getdouble(42.5), 42.5) - self.assertEqual(tcl.getdouble(42), 42.0) - self.assertRaises(TypeError, tcl.getdouble) - self.assertRaises(TypeError, tcl.getdouble, '42.5', '10') - self.assertRaises(TypeError, tcl.getdouble, b'42.5') - self.assertRaises(TclError, tcl.getdouble, 'a') - self.assertRaises((TypeError, ValueError, TclError), - tcl.getdouble, '42.5\0') - self.assertRaises((UnicodeEncodeError, ValueError, TclError), - tcl.getdouble, '42.5\ud800') - - def test_getboolean(self): - tcl = self.interp.tk - self.assertIs(tcl.getboolean('on'), True) - self.assertIs(tcl.getboolean('1'), True) - self.assertIs(tcl.getboolean(42), True) - self.assertIs(tcl.getboolean(0), False) - self.assertRaises(TypeError, tcl.getboolean) - self.assertRaises(TypeError, tcl.getboolean, 'on', '1') - self.assertRaises(TypeError, tcl.getboolean, b'on') - self.assertRaises(TypeError, tcl.getboolean, 1.0) - self.assertRaises(TclError, tcl.getboolean, 'a') - self.assertRaises((TypeError, ValueError, TclError), - tcl.getboolean, 'on\0') - self.assertRaises((UnicodeEncodeError, ValueError, TclError), - tcl.getboolean, 'on\ud800') - - def testEvalFile(self): - tcl = self.interp - with open(support.TESTFN, 'w') as f: - self.addCleanup(support.unlink, support.TESTFN) - f.write("""set a 1 - set b 2 - set c [ expr $a + $b ] - """) - tcl.evalfile(support.TESTFN) - self.assertEqual(tcl.eval('set a'),'1') - self.assertEqual(tcl.eval('set b'),'2') - self.assertEqual(tcl.eval('set c'),'3') - - def test_evalfile_null_in_result(self): - tcl = self.interp - with open(support.TESTFN, 'w') as f: - self.addCleanup(support.unlink, support.TESTFN) - f.write(""" - set a "a\0b" - set b "a\\0b" - """) - tcl.evalfile(support.TESTFN) - self.assertEqual(tcl.eval('set a'), 'a\x00b') - self.assertEqual(tcl.eval('set b'), 'a\x00b') - - def testEvalFileException(self): - tcl = self.interp - filename = "doesnotexists" - try: - os.remove(filename) - except Exception as e: - pass - self.assertRaises(TclError,tcl.evalfile,filename) - - def testPackageRequireException(self): - tcl = self.interp - self.assertRaises(TclError,tcl.eval,'package require DNE') - - @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows') - def testLoadWithUNC(self): - # Build a UNC path from the regular path. - # Something like - # \\%COMPUTERNAME%\c$\python27\python.exe - - fullname = os.path.abspath(sys.executable) - if fullname[1] != ':': - raise unittest.SkipTest('Absolute path should have drive part') - unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], - fullname[0], - fullname[3:]) - if not os.path.exists(unc_name): - raise unittest.SkipTest('Cannot connect to UNC Path') - - with support.EnvironmentVarGuard() as env: - env.unset("TCL_LIBRARY") - f = os.popen('%s -c "import tkinter; print(tkinter)"' % (unc_name,)) - - self.assertIn('tkinter', f.read()) - # exit code must be zero - self.assertEqual(f.close(), None) - - def test_exprstring(self): - tcl = self.interp - tcl.call('set', 'a', 3) - tcl.call('set', 'b', 6) - def check(expr, expected): - result = tcl.exprstring(expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, str) - - self.assertRaises(TypeError, tcl.exprstring) - self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6') - self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6') - self.assertRaises(TclError, tcl.exprstring, 'spam') - check('', '0') - check('8.2 + 6', '14.2') - check('3.1 + $a', '6.1') - check('2 + "$a.$b"', '5.6') - check('4*[llength "6 2"]', '8') - check('{word one} < "word $a"', '0') - check('4*2 < 7', '0') - check('hypot($a, 4)', '5.0') - check('5 / 4', '1') - check('5 / 4.0', '1.25') - check('5 / ( [string length "abcd"] + 0.0 )', '1.25') - check('20.0/5.0', '4.0') - check('"0x03" > "2"', '1') - check('[string length "a\xbd\u20ac"]', '3') - check(r'[string length "a\xbd\u20ac"]', '3') - check('"abc"', 'abc') - check('"a\xbd\u20ac"', 'a\xbd\u20ac') - check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') - check(r'"a\0b"', 'a\x00b') - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 - check('2**64', str(2**64)) - - def test_exprdouble(self): - tcl = self.interp - tcl.call('set', 'a', 3) - tcl.call('set', 'b', 6) - def check(expr, expected): - result = tcl.exprdouble(expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, float) - - self.assertRaises(TypeError, tcl.exprdouble) - self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6') - self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6') - self.assertRaises(TclError, tcl.exprdouble, 'spam') - check('', 0.0) - check('8.2 + 6', 14.2) - check('3.1 + $a', 6.1) - check('2 + "$a.$b"', 5.6) - check('4*[llength "6 2"]', 8.0) - check('{word one} < "word $a"', 0.0) - check('4*2 < 7', 0.0) - check('hypot($a, 4)', 5.0) - check('5 / 4', 1.0) - check('5 / 4.0', 1.25) - check('5 / ( [string length "abcd"] + 0.0 )', 1.25) - check('20.0/5.0', 4.0) - check('"0x03" > "2"', 1.0) - check('[string length "a\xbd\u20ac"]', 3.0) - check(r'[string length "a\xbd\u20ac"]', 3.0) - self.assertRaises(TclError, tcl.exprdouble, '"abc"') - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 - check('2**64', float(2**64)) - - def test_exprlong(self): - tcl = self.interp - tcl.call('set', 'a', 3) - tcl.call('set', 'b', 6) - def check(expr, expected): - result = tcl.exprlong(expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, int) - - self.assertRaises(TypeError, tcl.exprlong) - self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6') - self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6') - self.assertRaises(TclError, tcl.exprlong, 'spam') - check('', 0) - check('8.2 + 6', 14) - check('3.1 + $a', 6) - check('2 + "$a.$b"', 5) - check('4*[llength "6 2"]', 8) - check('{word one} < "word $a"', 0) - check('4*2 < 7', 0) - check('hypot($a, 4)', 5) - check('5 / 4', 1) - check('5 / 4.0', 1) - check('5 / ( [string length "abcd"] + 0.0 )', 1) - check('20.0/5.0', 4) - check('"0x03" > "2"', 1) - check('[string length "a\xbd\u20ac"]', 3) - check(r'[string length "a\xbd\u20ac"]', 3) - self.assertRaises(TclError, tcl.exprlong, '"abc"') - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 - self.assertRaises(TclError, tcl.exprlong, '2**64') - - def test_exprboolean(self): - tcl = self.interp - tcl.call('set', 'a', 3) - tcl.call('set', 'b', 6) - def check(expr, expected): - result = tcl.exprboolean(expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, int) - self.assertNotIsInstance(result, bool) - - self.assertRaises(TypeError, tcl.exprboolean) - self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6') - self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6') - self.assertRaises(TclError, tcl.exprboolean, 'spam') - check('', False) - for value in ('0', 'false', 'no', 'off'): - check(value, False) - check('"%s"' % value, False) - check('{%s}' % value, False) - for value in ('1', 'true', 'yes', 'on'): - check(value, True) - check('"%s"' % value, True) - check('{%s}' % value, True) - check('8.2 + 6', True) - check('3.1 + $a', True) - check('2 + "$a.$b"', True) - check('4*[llength "6 2"]', True) - check('{word one} < "word $a"', False) - check('4*2 < 7', False) - check('hypot($a, 4)', True) - check('5 / 4', True) - check('5 / 4.0', True) - check('5 / ( [string length "abcd"] + 0.0 )', True) - check('20.0/5.0', True) - check('"0x03" > "2"', True) - check('[string length "a\xbd\u20ac"]', True) - check(r'[string length "a\xbd\u20ac"]', True) - self.assertRaises(TclError, tcl.exprboolean, '"abc"') - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 - check('2**64', True) - - @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5') - def test_booleans(self): - tcl = self.interp - def check(expr, expected): - result = tcl.call('expr', expr) - if tcl.wantobjects(): - self.assertEqual(result, expected) - self.assertIsInstance(result, int) - else: - self.assertIn(result, (expr, str(int(expected)))) - self.assertIsInstance(result, str) - check('true', True) - check('yes', True) - check('on', True) - check('false', False) - check('no', False) - check('off', False) - check('1 < 2', True) - check('1 > 2', False) - - def test_expr_bignum(self): - tcl = self.interp - for i in self.get_integers(): - result = tcl.call('expr', str(i)) - if self.wantobjects: - self.assertEqual(result, i) - self.assertIsInstance(result, int) - else: - self.assertEqual(result, str(i)) - self.assertIsInstance(result, str) - if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - self.assertRaises(TclError, tcl.call, 'expr', str(2**1000)) - - def test_passing_values(self): - def passValue(value): - return self.interp.call('set', '_', value) - - self.assertEqual(passValue(True), True if self.wantobjects else '1') - self.assertEqual(passValue(False), False if self.wantobjects else '0') - self.assertEqual(passValue('string'), 'string') - self.assertEqual(passValue('string\u20ac'), 'string\u20ac') - self.assertEqual(passValue('str\x00ing'), 'str\x00ing') - self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd') - self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac') - self.assertEqual(passValue(b'str\x00ing'), - b'str\x00ing' if self.wantobjects else 'str\x00ing') - self.assertEqual(passValue(b'str\xc0\x80ing'), - b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing') - self.assertEqual(passValue(b'str\xbding'), - b'str\xbding' if self.wantobjects else 'str\xbding') - for i in self.get_integers(): - self.assertEqual(passValue(i), i if self.wantobjects else str(i)) - if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - self.assertEqual(passValue(2**1000), str(2**1000)) - for f in (0.0, 1.0, -1.0, 1/3, - sys.float_info.min, sys.float_info.max, - -sys.float_info.min, -sys.float_info.max): - if self.wantobjects: - self.assertEqual(passValue(f), f) - else: - self.assertEqual(float(passValue(f)), f) - if self.wantobjects: - f = passValue(float('nan')) - self.assertNotEqual(f, f) - self.assertEqual(passValue(float('inf')), float('inf')) - self.assertEqual(passValue(-float('inf')), -float('inf')) - else: - self.assertEqual(float(passValue(float('inf'))), float('inf')) - self.assertEqual(float(passValue(-float('inf'))), -float('inf')) - # XXX NaN representation can be not parsable by float() - self.assertEqual(passValue((1, '2', (3.4,))), - (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4') - self.assertEqual(passValue(['a', ['b', 'c']]), - ('a', ('b', 'c')) if self.wantobjects else 'a {b c}') - - def test_user_command(self): - result = None - def testfunc(arg): - nonlocal result - result = arg - return arg - self.interp.createcommand('testfunc', testfunc) - self.addCleanup(self.interp.tk.deletecommand, 'testfunc') - def check(value, expected=None, *, eq=self.assertEqual): - if expected is None: - expected = value - nonlocal result - result = None - r = self.interp.call('testfunc', value) - self.assertIsInstance(result, str) - eq(result, expected) - self.assertIsInstance(r, str) - eq(r, expected) - def float_eq(actual, expected): - self.assertAlmostEqual(float(actual), expected, - delta=abs(expected) * 1e-10) - - check(True, '1') - check(False, '0') - check('string') - check('string\xbd') - check('string\u20ac') - check('') - check(b'string', 'string') - check(b'string\xe2\x82\xac', 'string\xe2\x82\xac') - check(b'string\xbd', 'string\xbd') - check(b'', '') - check('str\x00ing') - check('str\x00ing\xbd') - check('str\x00ing\u20ac') - check(b'str\x00ing', 'str\x00ing') - check(b'str\xc0\x80ing', 'str\xc0\x80ing') - check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac') - for i in self.get_integers(): - check(i, str(i)) - if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - check(2**1000, str(2**1000)) - for f in (0.0, 1.0, -1.0): - check(f, repr(f)) - for f in (1/3.0, sys.float_info.min, sys.float_info.max, - -sys.float_info.min, -sys.float_info.max): - check(f, eq=float_eq) - check(float('inf'), eq=float_eq) - check(-float('inf'), eq=float_eq) - # XXX NaN representation can be not parsable by float() - check((), '') - check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}') - check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}') - - def test_splitlist(self): - splitlist = self.interp.tk.splitlist - call = self.interp.tk.call - self.assertRaises(TypeError, splitlist) - self.assertRaises(TypeError, splitlist, 'a', 'b') - self.assertRaises(TypeError, splitlist, 2) - testcases = [ - ('2', ('2',)), - ('', ()), - ('{}', ('',)), - ('""', ('',)), - ('a\n b\t\r c\n ', ('a', 'b', 'c')), - (b'a\n b\t\r c\n ', ('a', 'b', 'c')), - ('a \u20ac', ('a', '\u20ac')), - (b'a \xe2\x82\xac', ('a', '\u20ac')), - (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), - ('a {b c}', ('a', 'b c')), - (r'a b\ c', ('a', 'b c')), - (('a', 'b c'), ('a', 'b c')), - ('a 2', ('a', '2')), - (('a', 2), ('a', 2)), - ('a 3.4', ('a', '3.4')), - (('a', 3.4), ('a', 3.4)), - ((), ()), - ([], ()), - (['a', ['b', 'c']], ('a', ['b', 'c'])), - (call('list', 1, '2', (3.4,)), - (1, '2', (3.4,)) if self.wantobjects else - ('1', '2', '3.4')), - ] - tk_patchlevel = get_tk_patchlevel() - if tcl_version >= (8, 5): - if not self.wantobjects or tk_patchlevel < (8, 5, 5): - # Before 8.5.5 dicts were converted to lists through string - expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4') - else: - expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,)) - testcases += [ - (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), - expected), - ] - dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s' - % (self.wantobjects, tcl_version, tk_patchlevel)) - for arg, res in testcases: - self.assertEqual(splitlist(arg), res, - 'arg=%a, %s' % (arg, dbg_info)) - self.assertRaises(TclError, splitlist, '{') - - def test_split(self): - split = self.interp.tk.split - call = self.interp.tk.call - self.assertRaises(TypeError, split) - self.assertRaises(TypeError, split, 'a', 'b') - self.assertRaises(TypeError, split, 2) - testcases = [ - ('2', '2'), - ('', ''), - ('{}', ''), - ('""', ''), - ('{', '{'), - ('a\n b\t\r c\n ', ('a', 'b', 'c')), - (b'a\n b\t\r c\n ', ('a', 'b', 'c')), - ('a \u20ac', ('a', '\u20ac')), - (b'a \xe2\x82\xac', ('a', '\u20ac')), - (b'a\xc0\x80b', 'a\x00b'), - (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), - (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'), - ('a {b c}', ('a', ('b', 'c'))), - (r'a b\ c', ('a', ('b', 'c'))), - (('a', b'b c'), ('a', ('b', 'c'))), - (('a', 'b c'), ('a', ('b', 'c'))), - ('a 2', ('a', '2')), - (('a', 2), ('a', 2)), - ('a 3.4', ('a', '3.4')), - (('a', 3.4), ('a', 3.4)), - (('a', (2, 3.4)), ('a', (2, 3.4))), - ((), ()), - ([], ()), - (['a', 'b c'], ('a', ('b', 'c'))), - (['a', ['b', 'c']], ('a', ('b', 'c'))), - (call('list', 1, '2', (3.4,)), - (1, '2', (3.4,)) if self.wantobjects else - ('1', '2', '3.4')), - ] - if tcl_version >= (8, 5): - if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): - # Before 8.5.5 dicts were converted to lists through string - expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4') - else: - expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,)) - testcases += [ - (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), - expected), - ] - for arg, res in testcases: - self.assertEqual(split(arg), res, msg=arg) - - def test_splitdict(self): - splitdict = tkinter._splitdict - tcl = self.interp.tk - - arg = '-a {1 2 3} -something foo status {}' - self.assertEqual(splitdict(tcl, arg, False), - {'-a': '1 2 3', '-something': 'foo', 'status': ''}) - self.assertEqual(splitdict(tcl, arg), - {'a': '1 2 3', 'something': 'foo', 'status': ''}) - - arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}') - self.assertEqual(splitdict(tcl, arg, False), - {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'}) - self.assertEqual(splitdict(tcl, arg), - {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'}) - - self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ') - self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c')) - - arg = tcl.call('list', - '-a', (1, 2, 3), '-something', 'foo', 'status', ()) - self.assertEqual(splitdict(tcl, arg), - {'a': (1, 2, 3) if self.wantobjects else '1 2 3', - 'something': 'foo', 'status': ''}) - - if tcl_version >= (8, 5): - arg = tcl.call('dict', 'create', - '-a', (1, 2, 3), '-something', 'foo', 'status', ()) - if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): - # Before 8.5.5 dicts were converted to lists through string - expected = {'a': '1 2 3', 'something': 'foo', 'status': ''} - else: - expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''} - self.assertEqual(splitdict(tcl, arg), expected) - - -class BigmemTclTest(unittest.TestCase): - - def setUp(self): - self.interp = Tcl() - - @support.cpython_only - @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False) - def test_huge_string_call(self, size): - value = ' ' * size - self.assertRaises(OverflowError, self.interp.call, 'set', '_', value) - - @support.cpython_only - @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False) - def test_huge_string_builtins(self, size): - value = '1' + ' ' * size - self.assertRaises(OverflowError, self.interp.tk.getint, value) - self.assertRaises(OverflowError, self.interp.tk.getdouble, value) - self.assertRaises(OverflowError, self.interp.tk.getboolean, value) - self.assertRaises(OverflowError, self.interp.eval, value) - self.assertRaises(OverflowError, self.interp.evalfile, value) - self.assertRaises(OverflowError, self.interp.record, value) - self.assertRaises(OverflowError, self.interp.adderrorinfo, value) - self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a') - self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a') - self.assertRaises(OverflowError, self.interp.unsetvar, value) - self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value) - self.assertRaises(OverflowError, self.interp.adderrorinfo, value) - self.assertRaises(OverflowError, self.interp.exprstring, value) - self.assertRaises(OverflowError, self.interp.exprlong, value) - self.assertRaises(OverflowError, self.interp.exprboolean, value) - self.assertRaises(OverflowError, self.interp.splitlist, value) - self.assertRaises(OverflowError, self.interp.split, value) - self.assertRaises(OverflowError, self.interp.createcommand, value, max) - self.assertRaises(OverflowError, self.interp.deletecommand, value) - - -def setUpModule(): - if support.verbose: - tcl = Tcl() - print('patchlevel =', tcl.call('info', 'patchlevel')) - - -def test_main(): - support.run_unittest(TclTest, TkinterTest, BigmemTclTest) - -if __name__ == "__main__": - test_main() +if __name__ == '__main__': + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 06:57:24 2015 From: python-checkins at python.org (zach.ware) Date: Mon, 18 May 2015 04:57:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323488=3A_Fix_a_sy?= =?utf-8?q?ntax_error_on_big_endian_platforms=2E?= Message-ID: <20150518044717.39253.27196@psf.io> https://hg.python.org/cpython/rev/16d0e3dda31c changeset: 96130:16d0e3dda31c user: Zachary Ware date: Sun May 17 23:46:22 2015 -0500 summary: Issue #23488: Fix a syntax error on big endian platforms. Hopefully this will allow the PPC64 PowerLinux buildbot to finish a test run. files: Modules/_randommodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -266,7 +266,7 @@ { size_t i, j; /* Reverse an array. */ - for (i = 0; j = keyused - 1; i < j; i++, j--) { + for (i = 0, j = keyused - 1; i < j; i++, j--) { PY_UINT32_T tmp = key[i]; key[i] = key[j]; key[j] = tmp; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 07:49:19 2015 From: python-checkins at python.org (zach.ware) Date: Mon, 18 May 2015 05:49:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxOTMx?= =?utf-8?q?=3A_Fix_error_handling_in_msilib=2EFCICreate=28=29=2E?= Message-ID: <20150518054919.21154.62705@psf.io> https://hg.python.org/cpython/rev/41281737d71a changeset: 96131:41281737d71a branch: 3.4 parent: 96124:c79530e08985 user: Zachary Ware date: Mon May 18 00:47:15 2015 -0500 summary: Issue #21931: Fix error handling in msilib.FCICreate(). Patch by Jeffrey Armstrong. files: Misc/NEWS | 4 ++++ PC/_msi.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,10 @@ Library ------- +- Issue #21931: msilib.FCICreate() now raises TypeError in the case of a bad + argument instead of a ValueError with a bogus FCI error number. + Patch by Jeffrey Armstrong. + - Issue #23796: peak and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. diff --git a/PC/_msi.c b/PC/_msi.c --- a/PC/_msi.c +++ b/PC/_msi.c @@ -243,8 +243,13 @@ for (i=0; i < PyList_GET_SIZE(files); i++) { PyObject *item = PyList_GET_ITEM(files, i); char *filename, *cabname; - if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) - goto err; + + if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) { + PyErr_SetString(PyExc_TypeError, "FCICreate expects a list of tuples containing two strings"); + FCIDestroy(hfci); + return NULL; + } + if (!FCIAddFile(hfci, filename, cabname, FALSE, cb_getnextcabinet, cb_status, cb_getopeninfo, tcompTYPE_MSZIP)) @@ -260,7 +265,11 @@ Py_INCREF(Py_None); return Py_None; err: - PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */ + if(erf.fError) + PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */ + else + PyErr_SetString(PyExc_ValueError, "FCI general error"); + FCIDestroy(hfci); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 07:49:20 2015 From: python-checkins at python.org (zach.ware) Date: Mon, 18 May 2015 05:49:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2321931=3A_Merge_with_3=2E4?= Message-ID: <20150518054919.44695.83077@psf.io> https://hg.python.org/cpython/rev/cb0d1d86215e changeset: 96132:cb0d1d86215e parent: 96130:16d0e3dda31c parent: 96131:41281737d71a user: Zachary Ware date: Mon May 18 00:49:15 2015 -0500 summary: Closes #21931: Merge with 3.4 files: Misc/NEWS | 4 ++++ PC/_msi.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,10 @@ Library ------- +- Issue #21931: msilib.FCICreate() now raises TypeError in the case of a bad + argument instead of a ValueError with a bogus FCI error number. + Patch by Jeffrey Armstrong. + - Issue #13866: *quote_via* argument added to urllib.parse.urlencode. - Issue #20098: New mangle_from_ policy option for email, default True diff --git a/PC/_msi.c b/PC/_msi.c --- a/PC/_msi.c +++ b/PC/_msi.c @@ -243,8 +243,13 @@ for (i=0; i < PyList_GET_SIZE(files); i++) { PyObject *item = PyList_GET_ITEM(files, i); char *filename, *cabname; - if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) - goto err; + + if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) { + PyErr_SetString(PyExc_TypeError, "FCICreate expects a list of tuples containing two strings"); + FCIDestroy(hfci); + return NULL; + } + if (!FCIAddFile(hfci, filename, cabname, FALSE, cb_getnextcabinet, cb_status, cb_getopeninfo, tcompTYPE_MSZIP)) @@ -260,7 +265,11 @@ Py_INCREF(Py_None); return Py_None; err: - PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */ + if(erf.fError) + PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */ + else + PyErr_SetString(PyExc_ValueError, "FCI general error"); + FCIDestroy(hfci); return NULL; } -- Repository URL: https://hg.python.org/cpython From yselivanov.ml at gmail.com Sun May 17 17:03:46 2015 From: yselivanov.ml at gmail.com (Yury Selivanov) Date: Sun, 17 May 2015 11:03:46 -0400 Subject: [Python-checkins] peps: Apply Chris's changes, including an acceptance mark In-Reply-To: <20150517021227.21144.86257@psf.io> References: <20150517021227.21144.86257@psf.io> Message-ID: <5558ADD2.7030603@gmail.com> Chris, Could you please add a link to the email where the PEP was accepted? Thanks, Yury On 2015-05-16 10:12 PM, chris.angelico wrote: > https://hg.python.org/peps/rev/f876276ce076 > changeset: 5854:f876276ce076 > user: Chris Angelico > date: Sun May 17 12:12:19 2015 +1000 > summary: > Apply Chris's changes, including an acceptance mark > > files: > pep-0485.txt | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) > > > diff --git a/pep-0485.txt b/pep-0485.txt > --- a/pep-0485.txt > +++ b/pep-0485.txt > @@ -3,7 +3,7 @@ > Version: $Revision$ > Last-Modified: $Date$ > Author: Christopher Barker > -Status: Draft > +Status: Accepted > Type: Standards Track > Content-Type: text/x-rst > Created: 20-Jan-2015 > @@ -391,9 +391,9 @@ > The most common use case is expected to be small tolerances -- on order of the > default 1e-9. However there may be use cases where a user wants to know if two > fairly disparate values are within a particular range of each other: "is a > -within 200% (rel_tol = 2.0) of b? In this case, the string test would never > +within 200% (rel_tol = 2.0) of b? In this case, the strong test would never > indicate that two values are within that range of each other if one of them is > -zero. The strong case, however would use the larger (non-zero) value for the > +zero. The weak case, however would use the larger (non-zero) value for the > test, and thus return true if one value is zero. For example: is 0 within 200% > of 10? 200% of ten is 20, so the range within 200% of ten is -10 to +30. Zero > falls within that range, so it will return True. > > > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins From solipsis at pitrou.net Mon May 18 10:53:08 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 18 May 2015 08:53:08 +0000 Subject: [Python-checkins] Daily reference leaks (16d0e3dda31c): sum=4 Message-ID: <20150518085307.32305.45149@psf.io> results for 16d0e3dda31c on branch "default" -------------------------------------------- test_collections leaked [2, 0, -2] references, sum=0 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogAaz06t', '--timeout', '7200'] From python-checkins at python.org Mon May 18 15:11:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 13:11:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTAy?= =?utf-8?q?=3A_Fixed_exception_type_checking_in_standard_error_handlers=2E?= Message-ID: <20150518131121.10824.12513@psf.io> https://hg.python.org/cpython/rev/68eaa9409818 changeset: 96134:68eaa9409818 branch: 3.4 parent: 96131:41281737d71a user: Serhiy Storchaka date: Mon May 18 16:08:52 2015 +0300 summary: Issue #24102: Fixed exception type checking in standard error handlers. files: Lib/test/test_codeccallbacks.py | 23 +++++++++++ Misc/NEWS | 2 + Python/codecs.c | 42 +++++++++------------ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py --- a/Lib/test/test_codeccallbacks.py +++ b/Lib/test/test_codeccallbacks.py @@ -961,6 +961,29 @@ with self.assertRaises(TypeError): data.decode(encoding, "test.replacing") + def test_fake_error_class(self): + handlers = [ + codecs.strict_errors, + codecs.ignore_errors, + codecs.replace_errors, + codecs.backslashreplace_errors, + codecs.xmlcharrefreplace_errors, + codecs.lookup_error('surrogateescape'), + codecs.lookup_error('surrogatepass'), + ] + for cls in UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError: + class FakeUnicodeError(str): + __class__ = cls + for handler in handlers: + with self.subTest(handler=handler, error_class=cls): + self.assertRaises(TypeError, handler, FakeUnicodeError()) + class FakeUnicodeError(Exception): + __class__ = cls + for handler in handlers: + with self.subTest(handler=handler, error_class=cls): + with self.assertRaises((TypeError, FakeUnicodeError)): + handler(FakeUnicodeError()) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24102: Fixed exception type checking in standard error handlers. + - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -661,18 +661,9 @@ static void wrong_exception_type(PyObject *exc) { - _Py_IDENTIFIER(__class__); - _Py_IDENTIFIER(__name__); - PyObject *type = _PyObject_GetAttrId(exc, &PyId___class__); - if (type != NULL) { - PyObject *name = _PyObject_GetAttrId(type, &PyId___name__); - Py_DECREF(type); - if (name != NULL) { - PyErr_Format(PyExc_TypeError, - "don't know how to handle %S in error callback", name); - Py_DECREF(name); - } - } + PyErr_Format(PyExc_TypeError, + "don't know how to handle %.200s in error callback", + exc->ob_type->tp_name); } PyObject *PyCodec_StrictErrors(PyObject *exc) @@ -688,15 +679,16 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -712,7 +704,7 @@ { Py_ssize_t start, end, i, len; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *res; int kind; void *data; @@ -731,14 +723,14 @@ assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; return Py_BuildValue("(Cn)", (int)Py_UNICODE_REPLACEMENT_CHARACTER, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { PyObject *res; int kind; void *data; @@ -765,7 +757,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -863,7 +855,7 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -1007,7 +999,8 @@ Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { unsigned char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1078,7 +1071,7 @@ Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { unsigned char *p; Py_UCS4 ch = 0; if (PyUnicodeDecodeError_GetStart(exc, &start)) @@ -1157,7 +1150,8 @@ Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1188,7 +1182,7 @@ Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { PyObject *str; unsigned char *p; Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 15:11:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 13:11:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324102=3A_Fixed_exception_type_checking_in_stand?= =?utf-8?q?ard_error_handlers=2E?= Message-ID: <20150518131121.26556.50755@psf.io> https://hg.python.org/cpython/rev/510819e5855e changeset: 96135:510819e5855e parent: 96132:cb0d1d86215e parent: 96134:68eaa9409818 user: Serhiy Storchaka date: Mon May 18 16:10:40 2015 +0300 summary: Issue #24102: Fixed exception type checking in standard error handlers. files: Lib/test/test_codeccallbacks.py | 24 ++++++++++ Misc/NEWS | 2 + Python/codecs.c | 48 +++++++++----------- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py --- a/Lib/test/test_codeccallbacks.py +++ b/Lib/test/test_codeccallbacks.py @@ -1046,6 +1046,30 @@ with self.assertRaises(TypeError): data.decode(encoding, "test.replacing") + def test_fake_error_class(self): + handlers = [ + codecs.strict_errors, + codecs.ignore_errors, + codecs.replace_errors, + codecs.backslashreplace_errors, + codecs.namereplace_errors, + codecs.xmlcharrefreplace_errors, + codecs.lookup_error('surrogateescape'), + codecs.lookup_error('surrogatepass'), + ] + for cls in UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError: + class FakeUnicodeError(str): + __class__ = cls + for handler in handlers: + with self.subTest(handler=handler, error_class=cls): + self.assertRaises(TypeError, handler, FakeUnicodeError()) + class FakeUnicodeError(Exception): + __class__ = cls + for handler in handlers: + with self.subTest(handler=handler, error_class=cls): + with self.assertRaises((TypeError, FakeUnicodeError)): + handler(FakeUnicodeError()) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24102: Fixed exception type checking in standard error handlers. + - Issue #15027: The UTF-32 encoder is now 3x to 7x faster. - Issue #23290: Optimize set_merge() for cases where the target is empty. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -662,18 +662,9 @@ static void wrong_exception_type(PyObject *exc) { - _Py_IDENTIFIER(__class__); - _Py_IDENTIFIER(__name__); - PyObject *type = _PyObject_GetAttrId(exc, &PyId___class__); - if (type != NULL) { - PyObject *name = _PyObject_GetAttrId(type, &PyId___name__); - Py_DECREF(type); - if (name != NULL) { - PyErr_Format(PyExc_TypeError, - "don't know how to handle %S in error callback", name); - Py_DECREF(name); - } - } + PyErr_Format(PyExc_TypeError, + "don't know how to handle %.200s in error callback", + exc->ob_type->tp_name); } PyObject *PyCodec_StrictErrors(PyObject *exc) @@ -689,15 +680,16 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -713,7 +705,7 @@ { Py_ssize_t start, end, i, len; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *res; int kind; void *data; @@ -732,14 +724,14 @@ assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; return Py_BuildValue("(Cn)", (int)Py_UNICODE_REPLACEMENT_CHARACTER, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { PyObject *res; int kind; void *data; @@ -766,7 +758,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -873,7 +865,7 @@ int ressize; Py_UCS4 c; - if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { unsigned char *p; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; @@ -903,7 +895,7 @@ Py_DECREF(object); return Py_BuildValue("(Nn)", res, end); } - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -911,7 +903,7 @@ if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetStart(exc, &start)) return NULL; if (PyUnicodeTranslateError_GetEnd(exc, &end)) @@ -977,7 +969,7 @@ PyObject *PyCodec_NameReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -1150,7 +1142,8 @@ Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { unsigned char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1227,7 +1220,7 @@ Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { unsigned char *p; Py_UCS4 ch = 0; if (PyUnicodeDecodeError_GetStart(exc, &start)) @@ -1312,7 +1305,8 @@ Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1343,7 +1337,7 @@ Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { PyObject *str; unsigned char *p; Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 15:11:24 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 13:11:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTAy?= =?utf-8?q?=3A_Fixed_exception_type_checking_in_standard_error_handlers=2E?= Message-ID: <20150518131120.21164.34652@psf.io> https://hg.python.org/cpython/rev/547bc11e3357 changeset: 96133:547bc11e3357 branch: 2.7 parent: 96123:b6121a4afad7 user: Serhiy Storchaka date: Mon May 18 16:08:38 2015 +0300 summary: Issue #24102: Fixed exception type checking in standard error handlers. files: Lib/test/test_codeccallbacks.py | 20 ++++++++++++++++++++ Misc/NEWS | 2 ++ Python/codecs.c | 17 +++++++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py --- a/Lib/test/test_codeccallbacks.py +++ b/Lib/test/test_codeccallbacks.py @@ -836,6 +836,26 @@ text = u'abcghi'*n text.translate(charmap) + def test_fake_error_class(self): + handlers = [ + codecs.strict_errors, + codecs.ignore_errors, + codecs.replace_errors, + codecs.backslashreplace_errors, + codecs.xmlcharrefreplace_errors, + ] + for cls in UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError: + class FakeUnicodeError(str): + __class__ = cls + for handler in handlers: + self.assertRaises(TypeError, handler, FakeUnicodeError()) + class FakeUnicodeError(Exception): + __class__ = cls + for handler in handlers: + with self.assertRaises((TypeError, FakeUnicodeError)): + handler(FakeUnicodeError()) + + def test_main(): test.test_support.run_unittest(CodecCallbackTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24102: Fixed exception type checking in standard error handlers. + Library ------- diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -472,15 +472,16 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -500,7 +501,7 @@ Py_ssize_t end; Py_ssize_t i; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *res; Py_UNICODE *p; if (PyUnicodeEncodeError_GetStart(exc, &start)) @@ -517,13 +518,13 @@ Py_DECREF(res); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER; if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; return Py_BuildValue("(u#n)", &res, (Py_ssize_t)1, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { PyObject *res; Py_UNICODE *p; if (PyUnicodeTranslateError_GetStart(exc, &start)) @@ -548,7 +549,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t start; @@ -673,7 +674,7 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t start; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 16:26:58 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 14:26:58 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489_changes?= Message-ID: <20150518142658.16314.29942@psf.io> https://hg.python.org/peps/rev/ee324ce5f16a changeset: 5859:ee324ce5f16a user: Berker Peksag date: Mon May 18 17:27:02 2015 +0300 summary: PEP 489 changes Summary by Petr Viktorin: - Reuse the PyInit_* hook, instead of adding PyModuleExport_*; add the PyModuleDef_Init helper - Per-module state is allocated at the beginning of the execute step - Docstrings & methods from the def are added unconditionally - Rename PEP to better reflect what it ended up doing - Mention built-in modules, which get the same changes - Several rewordings and clarifications files: pep-0489.txt | 268 ++++++++++++++++++++++---------------- 1 files changed, 155 insertions(+), 113 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -1,5 +1,5 @@ PEP: 489 -Title: Redesigning extension module loading +Title: Multi-phase extension module initialization Version: $Revision$ Last-Modified: $Date$ Author: Petr Viktorin , @@ -18,8 +18,8 @@ Abstract ======== -This PEP proposes a redesign of the way in which extension modules interact -with the import machinery. This was last revised for Python 3.0 in PEP +This PEP proposes a redesign of the way in which built-in and extension modules +interact with the import machinery. This was last revised for Python 3.0 in PEP 3121, but did not solve all problems at the time. The goal is to solve them by bringing extension modules closer to the way Python modules behave; specifically to hook into the ModuleSpec-based loading mechanism @@ -45,12 +45,12 @@ ========== Python modules and extension modules are not being set up in the same way. -For Python modules, the module is created and set up first, then the module -code is being executed (PEP 302). +For Python modules, the module object is created and set up first, then the +module code is being executed (PEP 302). A ModuleSpec object (PEP 451) is used to hold information about the module, and passed to the relevant hooks. -For extensions, i.e. shared libraries, the module +For extensions (i.e. shared libraries) and built-in modules, the module init function is executed straight away and does both the creation and initialization. The initialization function is not passed the ModuleSpec, or any information it contains, such as the __file__ or fully-qualified @@ -59,8 +59,8 @@ In Py3, modules are also not being added to sys.modules, which means that a (potentially transitive) re-import of the module will really try to re-import it and thus run into an infinite loop when it executes the module init function -again. Without the FQMN, it is not trivial to correctly add the module to -sys.modules either. +again. Without access to the fully-qualified module name, it is not trivial to +correctly add the module to sys.modules either. This is specifically a problem for Cython generated modules, for which it's not uncommon that the module init code has the same level of complexity as that of any 'regular' Python module. Also, the lack of __file__ and __name__ @@ -81,15 +81,15 @@ The current process =================== -Currently, extension modules export an initialization function named -"PyInit_modulename", named after the file name of the shared library. This -function is executed by the import machinery and must return either NULL in -the case of an exception, or a fully initialized module object. The -function receives no arguments, so it has no way of knowing about its +Currently, extension and built-in modules export an initialization function +named "PyInit_modulename", named after the file name of the shared library. +This function is executed by the import machinery and must return a fully +initialized module object. +The function receives no arguments, so it has no way of knowing about its import context. During its execution, the module init function creates a module object -based on a PyModuleDef struct. It then continues to initialize it by adding +based on a PyModuleDef object. It then continues to initialize it by adding attributes to the module dict, creating types, etc. In the back, the shared library loader keeps a note of the fully qualified @@ -103,31 +103,15 @@ The proposal ============ -The current extension module initialization will be deprecated in favor of -a new initialization scheme. Since the current scheme will continue to be -available, existing code will continue to work unchanged, including binary -compatibility. +The initialization function (PyInit_modulename) will be allowed to return +a pointer to a PyModuleDef object. The import machinery will be in charge +of constructing the module object, calling hooks provided in the PyModuleDef +in the relevant phases of initialization (as described below). -Extension modules that support the new initialization scheme must export -the public symbol "PyModuleExport_", where "modulename" -is the name of the module. (For modules with non-ASCII names the symbol name -is slightly different, see "Export Hook Name" below.) - -If defined, this symbol must resolve to a C function with the following -signature:: - - PyModuleDef* (*PyModuleExportFunction)(void) - -For cross-platform compatibility, the function should be declared as:: - - PyMODEXPORT_FUNC PyModuleExport_(void) - -The function must return a pointer to a PyModuleDef structure. -This structure must be available for the lifetime of the module created from -it ? usually, it will be declared statically. - -Alternatively, this function can return NULL, in which case it is as if the -symbol was not defined ? see the "Legacy Init" section. +This multi-phase initialization is an additional possibility. Single-phase +initialization, the current practice of returning a fully initialized module +object, will still be accepted, so existing code will work unchanged, +including binary compatibility. The PyModuleDef structure will be changed to contain a list of slots, similarly to PEP 384's PyType_Spec for types. @@ -172,15 +156,30 @@ Unknown slot IDs will cause the import to fail with SystemError. -When using the new import mechanism, m_size must not be negative. -Also, the *m_name* field of PyModuleDef will not be unused during importing; -the module name will be taken from the ModuleSpec. +When using multi-phase initialization, the *m_name* field of PyModuleDef will +not be used during importing; the module name will be taken from the ModuleSpec. +To prevent crashes when the module is loaded in older versions of Python, +the PyModuleDef object must be initialized using the newly added +PyModuleDef_Init function. +For example, an extension module "example" would be exported as:: -Module Creation ---------------- + static PyModuleDef example_def = {...} -Module creation ? that is, the implementation of + PyMODINIT_FUNC + PyInit_example(void) + { + return PyModuleDef_Init(&example_def); + } + +The PyModuleDef object must be available for the lifetime of the module created +from it ? usually, it will be declared statically. + + +Module Creation Phase +--------------------- + +Creation of the module object ? that is, the implementation of ExecutionLoader.create_module ? is governed by the Py_mod_create slot. The Py_mod_create slot @@ -216,30 +215,30 @@ will fail with SystemError. If Py_mod_create is not specified, the import machinery will create a normal -module object by PyModule_New. The name is taken from *spec*. +module object using PyModule_New. The name is taken from *spec*. Post-creation steps ................... If the Py_mod_create function returns an instance of types.ModuleType -(or subclass), or if a Py_mod_create slot is not present, the import machinery -will do the following steps after the module is created: - -* If *m_size* is specified, per-module state is allocated and made accessible - through PyModule_GetState -* The PyModuleDef is associated with the module, making it accessible to - PyModule_GetDef, and enabling the m_traverse, m_clear and m_free hooks. -* The docstring is set from m_doc. -* The module's functions are initialized from m_methods. +or a subclass (or if a Py_mod_create slot is not present), the import +machinery will associate the PyModuleDef with the module, making it accessible +to PyModule_GetDef, and enabling the m_traverse, m_clear and m_free hooks. If the Py_mod_create function does not return a module subclass, then m_size -must be 0 or negative, and m_traverse, m_clear and m_free must all be NULL. +must be 0, and m_traverse, m_clear and m_free must all be NULL. Otherwise, SystemError is raised. +Additionally, initial attributes specified in the PyModuleDef are set on the +module object, regardless of its type: -Module Execution ----------------- +* The docstring is set from m_doc, if non-NULL. +* The module's functions are initialized from m_methods, if any. + + +Module Execution Phase +---------------------- Module execution -- that is, the implementation of ExecutionLoader.exec_module -- is governed by "execution slots". @@ -253,6 +252,14 @@ to sys.modules. +Pre-Execution steps +------------------- + +Before processing the execution slots, per-module state is allocated for the +module. From this point on, per-module state is accessible through +PyModule_GetState. + + The Py_mod_exec slot .................... @@ -266,9 +273,8 @@ If PyModuleExec replaces the module's entry in sys.modules, the new object will be used and returned by importlib machinery. -(This mirrors the behavior of Python modules. Note that for extensions, -implementing Py_mod_create is usually a better solution for the use cases -this serves.) +(This mirrors the behavior of Python modules. Note that implementing +Py_mod_create is usually a better solution for the use cases this serves.) The function must return ``0`` on success, or, on error, set an exception and return ``-1``. @@ -277,20 +283,19 @@ Legacy Init ----------- -If the PyModuleExport function is not defined, or if it returns NULL, the -import machinery will try to initialize the module using the -"PyInit_" hook, as described in PEP 3121. +The backwards-compatible single-phase initialization continues to be supported. +In this scheme, the PyInit function returns a fully initialized module rather +than a PyModuleDef object. +In this case, the PyInit hook implements the creation phase, and the execution +phase is a no-op. -If the PyModuleExport function is defined, the PyInit function will be ignored. -Modules requiring compatibility with previous versions of CPython may implement -the PyInit function in addition to the new hook. +Modules that need to work unchanged on older versions of Python should not +use multi-phase initialization, because the benefits it brings can't be +back-ported. +Nevertheless, here is an example of a module that supports multi-phase +initialization, and falls back to single-phase when compiled for an older +version of CPython:: -Modules using the legacy init API will be initialized entirely in the -Loader.create_module step; Loader.exec_module will be a no-op. - -A module that supports older CPython versions can be coded as:: - - #define Py_LIMITED_API #include static int spam_exec(PyObject *module) { @@ -298,10 +303,12 @@ return 0; } + #ifdef Py_mod_exec static PyModuleDef_Slot spam_slots[] = { {Py_mod_exec, spam_exec}, {0, NULL} }; + #endif static PyModuleDef spam_def = { PyModuleDef_HEAD_INIT, /* m_base */ @@ -309,18 +316,21 @@ PyDoc_STR("Utilities for cooking spam"), /* m_doc */ 0, /* m_size */ NULL, /* m_methods */ + #ifdef Py_mod_exec spam_slots, /* m_slots */ + #else + NULL, + #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; - PyModuleDef* PyModuleExport_spam(void) { - return &spam_def; - } - PyMODINIT_FUNC PyInit_spam(void) { + #ifdef Py_mod_exec + return PyModuleDef_Init(&spam_def); + #else PyObject *module; module = PyModule_Create(&spam_def); if (module == NULL) return NULL; @@ -329,15 +339,20 @@ return NULL; } return module; + #endif } -Note that this must be *compiled* on a new CPython version, but the resulting -shared library will be backwards compatible. -(Source-level compatibility is possible with preprocessor directives.) -If a Py_mod_create slot is used, PyInit should call its function instead of -PyModule_Create. Keep in mind that the ModuleSpec object is not available in -the legacy init scheme. +Built-In modules +---------------- + +Any extension module can be used as a built-in module by linking it into +the executable, and including it in the inittab (either at runtime with +PyImport_AppendInittab, or at configuration time, using tools like *freeze*). + +To keep this possibility, all changes to extension module loading introduced +in this PEP will also apply to built-in modules. +The only exception is non-ASCII module names, explained below. Subinterpreters and Interpreter Reloading @@ -354,18 +369,19 @@ A simple rule of thumb is: Do not define any static data, except built-in types with no mutable or user-settable class attributes. -Behavior of existing module creation functions ----------------------------------------------- + +Functions incompatible with multi-phase initialization +------------------------------------------------------ The PyModule_Create function will fail when used on a PyModuleDef structure -with a non-NULL m_slots pointer. +with a non-NULL *m_slots* pointer. The function doesn't have access to the ModuleSpec object necessary for -"new style" module creation. +multi-phase initialization. The PyState_FindModule function will return NULL, and PyState_AddModule -and PyState_RemoveModule will fail with SystemError. -PyState registration is disabled because multiple module objects may be -created from the same PyModuleDef. +and PyState_RemoveModule will also fail on modules with non-NULL *m_slots*. +PyState registration is disabled because multiple module objects may be created +from the same PyModuleDef. Module state and C-level callbacks @@ -380,7 +396,7 @@ * Methods of classes, which receive a reference to the class, but not to the class's module * Libraries with C-level callbacks, unless the callbacks can receive custom - data set at cllback registration + data set at callback registration Fixing these cases is outside of the scope of this PEP, but will be needed for the new mechanism to be useful to all modules. Proper fixes have been discussed @@ -393,7 +409,7 @@ New Functions ------------- -A new function and macro will be added to implement module creation. +A new function and macro implementing the module creation phase will be added. These are similar to PyModule_Create and PyModule_Create2, except they take an additional ModuleSpec argument, and handle module definitions with non-NULL slots:: @@ -402,10 +418,20 @@ PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version) -A new function will be added to run "execution slots" on a module:: +A new function implementing the module execution phase will be added. +This allocates per-module state (if not allocated already), and *always* +processes execution slots. The import machinery calls this method when +a module is executed, unless the module is being reloaded:: PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def) +Another function will be introduced to initialize a PyModuleDef object. +This idempotent function fills in the type, refcount, and module index. +It returns its argument cast to PyObject*, so it can be returned directly +from a PyInit function:: + + PyObject * PyModuleDef_Init(PyModuleDef *); + Additionally, two helpers will be added for setting the docstring and methods on a module:: @@ -417,13 +443,13 @@ ---------------- As portable C identifiers are limited to ASCII, module names -must be encoded to form the PyModuleExport hook name. +must be encoded to form the PyInit hook name. For ASCII module names, the import hook is named -PyModuleExport_, where is the name of the module. +PyInit_, where is the name of the module. For module names containing non-ASCII characters, the import hook is named -PyModuleExportU_, where the name is encoded using CPython's +PyInitU_, where the name is encoded using CPython's "punycode" encoding (Punycode [#rfc-3492]_ with a lowercase suffix), with hyphens ("-") replaced by underscores ("_"). @@ -435,17 +461,22 @@ suffix = b'_' + name.encode('ascii') except UnicodeEncodeError: suffix = b'U_' + name.encode('punycode').replace(b'-', b'_') - return b'PyModuleExport' + suffix + return b'PyInit' + suffix Examples: -============= =========================== -Module name Export hook name -============= =========================== -spam PyModuleExport_spam -lan?m?t PyModuleExportU_lanmt_2sa6t -??? PyModuleExportU_zck5b2b -============= =========================== +============= =================== +Module name Init hook name +============= =================== +spam PyInit_spam +lan?m?t PyInitU_lanmt_2sa6t +??? PyInitU_zck5b2b +============= =================== + +For modules with non-ASCII names, single-phase initialization is not supported. + +In the initial implementation of this PEP, built-in modules with non-ASCII +names will not be supported. Module Reloading @@ -468,11 +499,11 @@ ------------------------------- To support multiple Python modules in one shared library, the library can -export additional PyModuleExport* symbols besides the one that corresponds +export additional PyInit* symbols besides the one that corresponds to the library's filename. Note that this mechanism can currently only be used to *load* extra modules, -not to *find* them. +but not to *find* them. Given the filesystem location of a shared library and a module name, a module may be loaded with:: @@ -493,19 +524,19 @@ Testing and initial implementations ----------------------------------- -For testing, a new built-in module ``_testmoduleexport`` will be created. +For testing, a new built-in module ``_testmultiphase`` will be created. The library will export several additional modules using the mechanism described in "Multiple modules in one library". -The ``_testcapi`` module will be unchanged, and will use the old API -indefinitely (or until the old API is removed). +The ``_testcapi`` module will be unchanged, and will use single-phase +initialization indefinitely (or until it is no longer supported). -The ``array`` and ``xx*`` modules will be converted to the new API as -part of the initial implementation. +The ``array`` and ``xx*`` modules will be converted to use multi-phase +initialization as part of the initial implementation. -API Changes and Additions -------------------------- +Summary of API Changes and Additions +------------------------------------ New functions: @@ -514,13 +545,17 @@ * PyModule_ExecDef * PyModule_SetDocString * PyModule_AddFunctions +* PyModuleDef_Init New macros: -* PyMODEXPORT_FUNC * Py_mod_create * Py_mod_exec +New types: + +* PyModuleDef_Type will be exposed + New structures: * PyModuleDef_Slot @@ -586,6 +621,13 @@ are initialized, but it was later recognized that this isn't an important goal. The current PEP describes a simpler solution. +A further iteration used a "PyModuleExport" hook as an alternative to PyInit, +where PyInit was used for existing scheme, and PyModuleExport for multi-phase. +However, not being able to determine the hook name based on module name +complicated automatic generation of PyImport_Inittab by tools like freeze. +Keeping only the PyInit hook name, even if it's not entirely appropriate for +exporting a definition, yielded a much simpler solution. + References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon May 18 17:34:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 15:34:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDkx?= =?utf-8?q?=3A_Fixed_various_crashes_in_corner_cases_in_C_implementation_o?= =?utf-8?q?f?= Message-ID: <20150518153409.4229.83539@psf.io> https://hg.python.org/cpython/rev/157c4afca186 changeset: 96137:157c4afca186 branch: 3.4 parent: 96134:68eaa9409818 user: Serhiy Storchaka date: Mon May 18 18:29:33 2015 +0300 summary: Issue #24091: Fixed various crashes in corner cases in C implementation of ElementTree. files: Lib/test/test_xml_etree.py | 122 +++++++++++++++++++++ Misc/NEWS | 3 + Modules/_elementtree.c | 144 ++++++++++++++++-------- 3 files changed, 222 insertions(+), 47 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1709,6 +1709,126 @@ self.assertEqual(e2[0].tag, 'dogs') +class BadElementTest(ElementTestCase, unittest.TestCase): + def test_extend_mutable_list(self): + class X: + @property + def __class__(self): + L[:] = [ET.Element('baz')] + return ET.Element + L = [X()] + e = ET.Element('foo') + try: + e.extend(L) + except TypeError: + pass + + class Y(X, ET.Element): + pass + L = [Y('x')] + e = ET.Element('foo') + e.extend(L) + + def test_extend_mutable_list2(self): + class X: + @property + def __class__(self): + del L[:] + return ET.Element + L = [X(), ET.Element('baz')] + e = ET.Element('foo') + try: + e.extend(L) + except TypeError: + pass + + class Y(X, ET.Element): + pass + L = [Y('bar'), ET.Element('baz')] + e = ET.Element('foo') + e.extend(L) + + def test_remove_with_mutating(self): + class X(ET.Element): + def __eq__(self, o): + del e[:] + return False + e = ET.Element('foo') + e.extend([X('bar')]) + self.assertRaises(ValueError, e.remove, ET.Element('baz')) + + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + self.assertRaises(ValueError, e.remove, X('baz')) + + +class MutatingElementPath(str): + def __new__(cls, elem, *args): + self = str.__new__(cls, *args) + self.elem = elem + return self + def __eq__(self, o): + del self.elem[:] + return True +MutatingElementPath.__hash__ = str.__hash__ + +class BadElementPath(str): + def __eq__(self, o): + raise 1/0 +BadElementPath.__hash__ = str.__hash__ + +class BadElementPathTest(ElementTestCase, unittest.TestCase): + def setUp(self): + super().setUp() + from xml.etree import ElementPath + self.path_cache = ElementPath._cache + ElementPath._cache = {} + + def tearDown(self): + from xml.etree import ElementPath + ElementPath._cache = self.path_cache + super().tearDown() + + def test_find_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.find(MutatingElementPath(e, 'x')) + + def test_find_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.find(BadElementPath('x')) + except ZeroDivisionError: + pass + + def test_findtext_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.findtext(MutatingElementPath(e, 'x')) + + def test_findtext_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.findtext(BadElementPath('x')) + except ZeroDivisionError: + pass + + def test_findall_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.findall(MutatingElementPath(e, 'x')) + + def test_findall_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.findall(BadElementPath('x')) + except ZeroDivisionError: + pass + + class ElementTreeTypeTest(unittest.TestCase): def test_istype(self): self.assertIsInstance(ET.ParseError, type) @@ -2556,6 +2676,8 @@ ModuleTest, ElementSlicingTest, BasicElementTest, + BadElementTest, + BadElementPathTest, ElementTreeTest, IOTest, ParseErrorTest, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #24091: Fixed various crashes in corner cases in C implementation of + ElementTree. + - Issue #21931: msilib.FCICreate() now raises TypeError in the case of a bad argument instead of a ValueError with a bogus FCI error number. Patch by Jeffrey Armstrong. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1036,7 +1036,7 @@ element_extend(ElementObject* self, PyObject* args) { PyObject* seq; - Py_ssize_t i, seqlen = 0; + Py_ssize_t i; PyObject* seq_in; if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) @@ -1051,22 +1051,25 @@ return NULL; } - seqlen = PySequence_Size(seq); - for (i = 0; i < seqlen; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) { PyObject* element = PySequence_Fast_GET_ITEM(seq, i); - if (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) { - Py_DECREF(seq); + Py_INCREF(element); + if (!PyObject_TypeCheck(element, (PyTypeObject *)&Element_Type)) { PyErr_Format( PyExc_TypeError, "expected an Element, not \"%.200s\"", Py_TYPE(element)->tp_name); + Py_DECREF(seq); + Py_DECREF(element); return NULL; } if (element_add_subelement(self, element) < 0) { Py_DECREF(seq); + Py_DECREF(element); return NULL; } + Py_DECREF(element); } Py_DECREF(seq); @@ -1099,11 +1102,16 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { - Py_INCREF(item); + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ); + if (rc > 0) return item; - } + Py_DECREF(item); + if (rc < 0) + return NULL; } Py_RETURN_NONE; @@ -1136,14 +1144,24 @@ for (i = 0; i < self->extra->length; i++) { ElementObject* item = (ElementObject*) self->extra->children[i]; - if (Element_CheckExact(item) && - (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) { + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(item->tag, tag, Py_EQ); + if (rc > 0) { PyObject* text = element_get_text(item); - if (text == Py_None) + if (text == Py_None) { + Py_DECREF(item); return PyUnicode_New(0, 0); + } Py_XINCREF(text); + Py_DECREF(item); return text; } + Py_DECREF(item); + if (rc < 0) + return NULL; } Py_INCREF(default_value); @@ -1180,13 +1198,17 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { - if (PyList_Append(out, item) < 0) { - Py_DECREF(out); - return NULL; - } + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ); + if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) { + Py_DECREF(item); + Py_DECREF(out); + return NULL; } + Py_DECREF(item); } return out; @@ -1403,8 +1425,10 @@ element_remove(ElementObject* self, PyObject* args) { int i; - + int rc; PyObject* element; + PyObject* found; + if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element)) return NULL; @@ -1420,11 +1444,14 @@ for (i = 0; i < self->extra->length; i++) { if (self->extra->children[i] == element) break; - if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1) + rc = PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ); + if (rc > 0) break; + if (rc < 0) + return NULL; } - if (i == self->extra->length) { + if (i >= self->extra->length) { /* element is not in children, so raise exception */ PyErr_SetString( PyExc_ValueError, @@ -1433,13 +1460,13 @@ return NULL; } - Py_DECREF(self->extra->children[i]); + found = self->extra->children[i]; self->extra->length--; - for (; i < self->extra->length; i++) self->extra->children[i] = self->extra->children[i+1]; + Py_DECREF(found); Py_RETURN_NONE; } @@ -2012,6 +2039,7 @@ */ ElementObject *cur_parent; Py_ssize_t child_index; + int rc; while (1) { /* Handle the case reached in the beginning and end of iteration, where @@ -2033,14 +2061,22 @@ } it->root_done = 1; - if (it->sought_tag == Py_None || - PyObject_RichCompareBool(it->root_element->tag, - it->sought_tag, Py_EQ) == 1) { + rc = (it->sought_tag == Py_None); + if (!rc) { + rc = PyObject_RichCompareBool(it->root_element->tag, + it->sought_tag, Py_EQ); + if (rc < 0) + return NULL; + } + if (rc) { if (it->gettext) { PyObject *text = element_get_text(it->root_element); if (!text) return NULL; - if (PyObject_IsTrue(text)) { + rc = PyObject_IsTrue(text); + if (rc < 0) + return NULL; + if (rc) { Py_INCREF(text); return text; } @@ -2072,18 +2108,26 @@ PyObject *text = element_get_text(child); if (!text) return NULL; - if (PyObject_IsTrue(text)) { + rc = PyObject_IsTrue(text); + if (rc < 0) + return NULL; + if (rc) { Py_INCREF(text); return text; } - } else if (it->sought_tag == Py_None || - PyObject_RichCompareBool(child->tag, - it->sought_tag, Py_EQ) == 1) { - Py_INCREF(child); - return (PyObject *)child; + } else { + rc = (it->sought_tag == Py_None); + if (!rc) { + rc = PyObject_RichCompareBool(child->tag, + it->sought_tag, Py_EQ); + if (rc < 0) + return NULL; + } + if (rc) { + Py_INCREF(child); + return (PyObject *)child; + } } - else - continue; } else { PyObject *tail; @@ -2103,9 +2147,14 @@ * this is because itertext() is supposed to only return *inner* * text, not text following the element it began iteration with. */ - if (it->parent_stack->parent && PyObject_IsTrue(tail)) { - Py_INCREF(tail); - return tail; + if (it->parent_stack->parent) { + rc = PyObject_IsTrue(tail); + if (rc < 0) + return NULL; + if (rc) { + Py_INCREF(tail); + return tail; + } } } } @@ -2163,20 +2212,21 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext) { ElementIterObject *it; - PyObject *star = NULL; it = PyObject_GC_New(ElementIterObject, &ElementIter_Type); if (!it) return NULL; - if (PyUnicode_Check(tag)) - star = PyUnicode_FromString("*"); - else if (PyBytes_Check(tag)) - star = PyBytes_FromString("*"); - - if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1) - tag = Py_None; - Py_XDECREF(star); + if (PyUnicode_Check(tag)) { + if (PyUnicode_READY(tag) < 0) + return NULL; + if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*') + tag = Py_None; + } + else if (PyBytes_Check(tag)) { + if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*') + tag = Py_None; + } Py_INCREF(tag); it->sought_tag = tag; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 17:34:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 15:34:10 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MDkx?= =?utf-8?q?=3A_Fixed_various_crashes_in_corner_cases_in_cElementTree=2E?= Message-ID: <20150518153408.32315.79808@psf.io> https://hg.python.org/cpython/rev/34523e53a342 changeset: 96136:34523e53a342 branch: 2.7 parent: 96133:547bc11e3357 user: Serhiy Storchaka date: Mon May 18 18:28:57 2015 +0300 summary: Issue #24091: Fixed various crashes in corner cases in cElementTree. files: Misc/NEWS | 2 + Modules/_elementtree.c | 65 ++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,8 @@ Library ------- +- Issue #24091: Fixed various crashes in corner cases in cElementTree. + - Issue #15267: HTTPConnection.request() now is compatibile with old-style classes (such as TemporaryFile). Original patch by Atsuo Ishimoto. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -756,7 +756,7 @@ element_extend(ElementObject* self, PyObject* args) { PyObject* seq; - Py_ssize_t i, seqlen = 0; + Py_ssize_t i; PyObject* seq_in; if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) @@ -771,8 +771,7 @@ return NULL; } - seqlen = PySequence_Size(seq); - for (i = 0; i < seqlen; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) { PyObject* element = PySequence_Fast_GET_ITEM(seq, i); if (element_add_subelement(self, element) < 0) { Py_DECREF(seq); @@ -805,11 +804,16 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { - Py_INCREF(item); + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(((ElementObject*)item)->tag, tag); + if (rc == 0) return item; - } + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) + return NULL; } Py_RETURN_NONE; @@ -838,13 +842,24 @@ for (i = 0; i < self->extra->length; i++) { ElementObject* item = (ElementObject*) self->extra->children[i]; - if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(item->tag, tag); + if (rc == 0) { PyObject* text = element_get_text(item); - if (text == Py_None) + if (text == Py_None) { + Py_DECREF(item); return PyString_FromString(""); + } Py_XINCREF(text); + Py_DECREF(item); return text; } + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) + return NULL; } Py_INCREF(default_value); @@ -876,12 +891,17 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { - if (PyList_Append(out, item) < 0) { - Py_DECREF(out); - return NULL; - } + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(((ElementObject*)item)->tag, tag); + if (rc == 0) + rc = PyList_Append(out, item); + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) { + Py_DECREF(out); + return NULL; } } @@ -1147,8 +1167,10 @@ element_remove(ElementObject* self, PyObject* args) { int i; - + int rc; PyObject* element; + PyObject* found; + if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element)) return NULL; @@ -1164,11 +1186,14 @@ for (i = 0; i < self->extra->length; i++) { if (self->extra->children[i] == element) break; - if (PyObject_Compare(self->extra->children[i], element) == 0) + rc = PyObject_Compare(self->extra->children[i], element); + if (rc == 0) break; + if (rc < 0 && PyErr_Occurred()) + return NULL; } - if (i == self->extra->length) { + if (i >= self->extra->length) { /* element is not in children, so raise exception */ PyErr_SetString( PyExc_ValueError, @@ -1177,13 +1202,13 @@ return NULL; } - Py_DECREF(self->extra->children[i]); + found = self->extra->children[i]; self->extra->length--; - for (; i < self->extra->length; i++) self->extra->children[i] = self->extra->children[i+1]; + Py_DECREF(found); Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 17:34:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 15:34:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324091=3A_Fixed_various_crashes_in_corner_cases_?= =?utf-8?q?in_C_implementation_of?= Message-ID: <20150518153409.39261.29938@psf.io> https://hg.python.org/cpython/rev/a8b8d1b211fe changeset: 96138:a8b8d1b211fe parent: 96135:510819e5855e parent: 96137:157c4afca186 user: Serhiy Storchaka date: Mon May 18 18:33:31 2015 +0300 summary: Issue #24091: Fixed various crashes in corner cases in C implementation of ElementTree. files: Lib/test/test_xml_etree.py | 122 +++++++++++++++++++++ Misc/NEWS | 3 + Modules/_elementtree.c | 142 ++++++++++++++++-------- 3 files changed, 221 insertions(+), 46 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1709,6 +1709,126 @@ self.assertEqual(e2[0].tag, 'dogs') +class BadElementTest(ElementTestCase, unittest.TestCase): + def test_extend_mutable_list(self): + class X: + @property + def __class__(self): + L[:] = [ET.Element('baz')] + return ET.Element + L = [X()] + e = ET.Element('foo') + try: + e.extend(L) + except TypeError: + pass + + class Y(X, ET.Element): + pass + L = [Y('x')] + e = ET.Element('foo') + e.extend(L) + + def test_extend_mutable_list2(self): + class X: + @property + def __class__(self): + del L[:] + return ET.Element + L = [X(), ET.Element('baz')] + e = ET.Element('foo') + try: + e.extend(L) + except TypeError: + pass + + class Y(X, ET.Element): + pass + L = [Y('bar'), ET.Element('baz')] + e = ET.Element('foo') + e.extend(L) + + def test_remove_with_mutating(self): + class X(ET.Element): + def __eq__(self, o): + del e[:] + return False + e = ET.Element('foo') + e.extend([X('bar')]) + self.assertRaises(ValueError, e.remove, ET.Element('baz')) + + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + self.assertRaises(ValueError, e.remove, X('baz')) + + +class MutatingElementPath(str): + def __new__(cls, elem, *args): + self = str.__new__(cls, *args) + self.elem = elem + return self + def __eq__(self, o): + del self.elem[:] + return True +MutatingElementPath.__hash__ = str.__hash__ + +class BadElementPath(str): + def __eq__(self, o): + raise 1/0 +BadElementPath.__hash__ = str.__hash__ + +class BadElementPathTest(ElementTestCase, unittest.TestCase): + def setUp(self): + super().setUp() + from xml.etree import ElementPath + self.path_cache = ElementPath._cache + ElementPath._cache = {} + + def tearDown(self): + from xml.etree import ElementPath + ElementPath._cache = self.path_cache + super().tearDown() + + def test_find_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.find(MutatingElementPath(e, 'x')) + + def test_find_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.find(BadElementPath('x')) + except ZeroDivisionError: + pass + + def test_findtext_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.findtext(MutatingElementPath(e, 'x')) + + def test_findtext_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.findtext(BadElementPath('x')) + except ZeroDivisionError: + pass + + def test_findall_with_mutating(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + e.findall(MutatingElementPath(e, 'x')) + + def test_findall_with_error(self): + e = ET.Element('foo') + e.extend([ET.Element('bar')]) + try: + e.findall(BadElementPath('x')) + except ZeroDivisionError: + pass + + class ElementTreeTypeTest(unittest.TestCase): def test_istype(self): self.assertIsInstance(ET.ParseError, type) @@ -2556,6 +2676,8 @@ ModuleTest, ElementSlicingTest, BasicElementTest, + BadElementTest, + BadElementPathTest, ElementTreeTest, IOTest, ParseErrorTest, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,9 @@ Library ------- +- Issue #24091: Fixed various crashes in corner cases in C implementation of + ElementTree. + - Issue #21931: msilib.FCICreate() now raises TypeError in the case of a bad argument instead of a ValueError with a bogus FCI error number. Patch by Jeffrey Armstrong. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1094,7 +1094,7 @@ /*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/ { PyObject* seq; - Py_ssize_t i, seqlen = 0; + Py_ssize_t i; seq = PySequence_Fast(elements, ""); if (!seq) { @@ -1105,22 +1105,25 @@ return NULL; } - seqlen = PySequence_Size(seq); - for (i = 0; i < seqlen; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) { PyObject* element = PySequence_Fast_GET_ITEM(seq, i); - if (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) { - Py_DECREF(seq); + Py_INCREF(element); + if (!PyObject_TypeCheck(element, (PyTypeObject *)&Element_Type)) { PyErr_Format( PyExc_TypeError, "expected an Element, not \"%.200s\"", Py_TYPE(element)->tp_name); + Py_DECREF(seq); + Py_DECREF(element); return NULL; } if (element_add_subelement(self, element) < 0) { Py_DECREF(seq); + Py_DECREF(element); return NULL; } + Py_DECREF(element); } Py_DECREF(seq); @@ -1156,11 +1159,16 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ) == 1) { - Py_INCREF(item); + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ); + if (rc > 0) return item; - } + Py_DECREF(item); + if (rc < 0) + return NULL; } Py_RETURN_NONE; @@ -1197,14 +1205,24 @@ for (i = 0; i < self->extra->length; i++) { ElementObject* item = (ElementObject*) self->extra->children[i]; - if (Element_CheckExact(item) && - (PyObject_RichCompareBool(item->tag, path, Py_EQ) == 1)) { + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(item->tag, path, Py_EQ); + if (rc > 0) { PyObject* text = element_get_text(item); - if (text == Py_None) + if (text == Py_None) { + Py_DECREF(item); return PyUnicode_New(0, 0); + } Py_XINCREF(text); + Py_DECREF(item); return text; } + Py_DECREF(item); + if (rc < 0) + return NULL; } Py_INCREF(default_value); @@ -1245,13 +1263,17 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) { - if (PyList_Append(out, item) < 0) { - Py_DECREF(out); - return NULL; - } + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ); + if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) { + Py_DECREF(item); + Py_DECREF(out); + return NULL; } + Py_DECREF(item); } return out; @@ -1507,6 +1529,8 @@ /*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/ { Py_ssize_t i; + int rc; + PyObject *found; if (!self->extra) { /* element has no children, so raise exception */ @@ -1520,11 +1544,14 @@ for (i = 0; i < self->extra->length; i++) { if (self->extra->children[i] == subelement) break; - if (PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ) == 1) + rc = PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ); + if (rc > 0) break; + if (rc < 0) + return NULL; } - if (i == self->extra->length) { + if (i >= self->extra->length) { /* subelement is not in children, so raise exception */ PyErr_SetString( PyExc_ValueError, @@ -1533,13 +1560,13 @@ return NULL; } - Py_DECREF(self->extra->children[i]); + found = self->extra->children[i]; self->extra->length--; - for (; i < self->extra->length; i++) self->extra->children[i] = self->extra->children[i+1]; + Py_DECREF(found); Py_RETURN_NONE; } @@ -2033,6 +2060,7 @@ */ ElementObject *cur_parent; Py_ssize_t child_index; + int rc; while (1) { /* Handle the case reached in the beginning and end of iteration, where @@ -2054,14 +2082,22 @@ } it->root_done = 1; - if (it->sought_tag == Py_None || - PyObject_RichCompareBool(it->root_element->tag, - it->sought_tag, Py_EQ) == 1) { + rc = (it->sought_tag == Py_None); + if (!rc) { + rc = PyObject_RichCompareBool(it->root_element->tag, + it->sought_tag, Py_EQ); + if (rc < 0) + return NULL; + } + if (rc) { if (it->gettext) { PyObject *text = element_get_text(it->root_element); if (!text) return NULL; - if (PyObject_IsTrue(text)) { + rc = PyObject_IsTrue(text); + if (rc < 0) + return NULL; + if (rc) { Py_INCREF(text); return text; } @@ -2093,18 +2129,26 @@ PyObject *text = element_get_text(child); if (!text) return NULL; - if (PyObject_IsTrue(text)) { + rc = PyObject_IsTrue(text); + if (rc < 0) + return NULL; + if (rc) { Py_INCREF(text); return text; } - } else if (it->sought_tag == Py_None || - PyObject_RichCompareBool(child->tag, - it->sought_tag, Py_EQ) == 1) { - Py_INCREF(child); - return (PyObject *)child; + } else { + rc = (it->sought_tag == Py_None); + if (!rc) { + rc = PyObject_RichCompareBool(child->tag, + it->sought_tag, Py_EQ); + if (rc < 0) + return NULL; + } + if (rc) { + Py_INCREF(child); + return (PyObject *)child; + } } - else - continue; } else { PyObject *tail; @@ -2124,9 +2168,14 @@ * this is because itertext() is supposed to only return *inner* * text, not text following the element it began iteration with. */ - if (it->parent_stack->parent && PyObject_IsTrue(tail)) { - Py_INCREF(tail); - return tail; + if (it->parent_stack->parent) { + rc = PyObject_IsTrue(tail); + if (rc < 0) + return NULL; + if (rc) { + Py_INCREF(tail); + return tail; + } } } } @@ -2184,20 +2233,21 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext) { ElementIterObject *it; - PyObject *star = NULL; it = PyObject_GC_New(ElementIterObject, &ElementIter_Type); if (!it) return NULL; - if (PyUnicode_Check(tag)) - star = PyUnicode_FromString("*"); - else if (PyBytes_Check(tag)) - star = PyBytes_FromString("*"); - - if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1) - tag = Py_None; - Py_XDECREF(star); + if (PyUnicode_Check(tag)) { + if (PyUnicode_READY(tag) < 0) + return NULL; + if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*') + tag = Py_None; + } + else if (PyBytes_Check(tag)) { + if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*') + tag = Py_None; + } Py_INCREF(tag); it->sought_tag = tag; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 18:50:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 18 May 2015 16:50:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24226=3A_Fix_parsing?= =?utf-8?q?_of_many_sequential_one-line_=27def=27_statements=2E?= Message-ID: <20150518165056.26834.98613@psf.io> https://hg.python.org/cpython/rev/fb5fcae0cf1f changeset: 96139:fb5fcae0cf1f user: Yury Selivanov date: Mon May 18 12:50:52 2015 -0400 summary: Issue 24226: Fix parsing of many sequential one-line 'def' statements. files: Lib/test/test_coroutines.py | 23 +++++++++++++++++++++++ Lib/test/test_tokenize.py | 11 +++++++++++ Parser/tokenizer.c | 25 +++++++++++++++++-------- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -1,4 +1,5 @@ import contextlib +import inspect import sys import types import unittest @@ -87,6 +88,28 @@ import test.badsyntax_async9 +class TokenizerRegrTest(unittest.TestCase): + + def test_oneline_defs(self): + buf = [] + for i in range(500): + buf.append('def i{i}(): return {i}'.format(i=i)) + buf = '\n'.join(buf) + + # Test that 500 consequent, one-line defs is OK + ns = {} + exec(buf, ns, ns) + self.assertEqual(ns['i499'](), 499) + + # Test that 500 consequent, one-line defs *and* + # one 'async def' following them is OK + buf += '\nasync def foo():\n return' + ns = {} + exec(buf, ns, ns) + self.assertEqual(ns['i499'](), 499) + self.assertTrue(inspect.iscoroutinefunction(ns['foo'])) + + class CoroutineTest(unittest.TestCase): def test_gen_1(self): diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1289,6 +1289,17 @@ self.assertTrue(encoding_used, encoding) + def test_oneline_defs(self): + buf = [] + for i in range(500): + buf.append('def i{i}(): return {i}'.format(i=i)) + buf.append('OK') + buf = '\n'.join(buf) + + # Test that 500 consequent, one-line defs is OK + toks = list(tokenize(BytesIO(buf.encode('utf-8')).readline)) + self.assertEqual(toks[-2].string, 'OK') # [-1] is always ENDMARKER + def assertExactTypeEqual(self, opstr, *optypes): tokens = list(tokenize(BytesIO(opstr.encode('utf-8')).readline)) num_optypes = len(optypes) diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1501,17 +1501,20 @@ tok_len = tok->cur - tok->start; if (tok_len == 3 && memcmp(tok->start, "def", 3) == 0) { - - if (tok->def + 1 >= MAXINDENT) { - tok->done = E_TOODEEP; - tok->cur = tok->inp; - return ERRORTOKEN; - } - if (tok->def && tok->deftypestack[tok->def] == 3) { tok->deftypestack[tok->def] = 2; } - else { + else if (tok->defstack[tok->def] < tok->indent) { + /* We advance defs stack only when we see "def" *and* + the indentation level was increased relative to the + previous "def". */ + + if (tok->def + 1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return ERRORTOKEN; + } + tok->def++; tok->defstack[tok->def] = tok->indent; tok->deftypestack[tok->def] = 1; @@ -1528,6 +1531,12 @@ ahead_tok.cur - ahead_tok.start == 3 && memcmp(ahead_tok.start, "def", 3) == 0) { + if (tok->def + 1 >= MAXINDENT) { + tok->done = E_TOODEEP; + tok->cur = tok->inp; + return ERRORTOKEN; + } + tok->def++; tok->defstack[tok->def] = tok->indent; tok->deftypestack[tok->def] = 3; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 19:32:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 18 May 2015 17:32:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Few_minor_fixes=2E?= Message-ID: <20150518173244.26578.75110@psf.io> https://hg.python.org/peps/rev/a504b339f54d changeset: 5860:a504b339f54d user: Yury Selivanov date: Mon May 18 13:32:41 2015 -0400 summary: pep-492: Few minor fixes. files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1331,8 +1331,8 @@ 6. New functions: ``sys.set_coroutine_wrapper(callback)``, ``sys.get_coroutine_wrapper()``, ``types.coroutine(gen)``, - ``inspect.iscoroutinefunction()``, ``inspect.iscoroutine()``, - and ``inspect.isawaitable()``. + ``inspect.iscoroutinefunction(func)``, ``inspect.iscoroutine(obj)``, + and ``inspect.isawaitable(obj)``. 7. New ``CO_COROUTINE`` and ``CO_ITERABLE_COROUTINE`` bit flags for code objects. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon May 18 21:20:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 19:20:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_typos_in_comments=2E?= Message-ID: <20150518192039.26830.48447@psf.io> https://hg.python.org/cpython/rev/bc6ed8360312 changeset: 96141:bc6ed8360312 parent: 96139:fb5fcae0cf1f parent: 96140:3d5bf6174c4b user: Serhiy Storchaka date: Mon May 18 22:20:18 2015 +0300 summary: Fixed typos in comments. files: Objects/stringlib/codecs.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -660,7 +660,7 @@ if (ch < 0xd800) *out++ = ch; else if (ch < 0xe000) - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; #if STRINGLIB_MAX_CHAR >= 0x10000 else if (ch >= 0x10000) { @@ -695,7 +695,7 @@ if (ch < 0xd800) *out++ = SWAB2((Py_UCS2)ch); else if (ch < 0xe000) - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; #if STRINGLIB_MAX_CHAR >= 0x10000 else if (ch >= 0x10000) { @@ -760,7 +760,7 @@ ch = *in++; #if STRINGLIB_SIZEOF_CHAR > 1 if (Py_UNICODE_IS_SURROGATE(ch)) { - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; } #endif @@ -788,7 +788,7 @@ Py_UCS4 ch = *in++; #if STRINGLIB_SIZEOF_CHAR > 1 if (Py_UNICODE_IS_SURROGATE(ch)) { - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; } #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 21:20:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 18 May 2015 19:20:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_typos_in?= =?utf-8?q?_comments=2E?= Message-ID: <20150518192039.21170.11455@psf.io> https://hg.python.org/cpython/rev/3d5bf6174c4b changeset: 96140:3d5bf6174c4b branch: 3.4 parent: 96137:157c4afca186 user: Serhiy Storchaka date: Mon May 18 22:19:42 2015 +0300 summary: Fixed typos in comments. files: Objects/stringlib/codecs.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -660,7 +660,7 @@ if (ch < 0xd800) *out++ = ch; else if (ch < 0xe000) - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; #if STRINGLIB_MAX_CHAR >= 0x10000 else if (ch >= 0x10000) { @@ -695,7 +695,7 @@ if (ch < 0xd800) *out++ = SWAB2((Py_UCS2)ch); else if (ch < 0xe000) - /* reject surrogate characters (U+DC800-U+DFFF) */ + /* reject surrogate characters (U+D800-U+DFFF) */ goto fail; #if STRINGLIB_MAX_CHAR >= 0x10000 else if (ch >= 0x10000) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 18 21:37:49 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 18 May 2015 19:37:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MjIy?= =?utf-8?q?=3A_Fix_regression_introduced_with_idlelib/PyShell=2Epy_future_?= =?utf-8?q?print?= Message-ID: <20150518193749.26582.80526@psf.io> https://hg.python.org/cpython/rev/cebd51686565 changeset: 96142:cebd51686565 branch: 2.7 parent: 96136:34523e53a342 user: Terry Jan Reedy date: Mon May 18 15:37:37 2015 -0400 summary: Issue #24222: Fix regression introduced with idlelib/PyShell.py future print import. Idle -c "code", -r file.py again compile with print statement. files: Lib/idlelib/PyShell.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -652,7 +652,7 @@ if source is None: source = open(filename, "r").read() try: - code = compile(source, filename, "exec") + code = compile(source, filename, "exec", dont_inherit=True) except (OverflowError, SyntaxError): self.tkconsole.resetoutput() print('*** Error in script or command!\n' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:22:27 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:22:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_typo_in_Ni?= =?utf-8?q?sc/NEWS=2E?= Message-ID: <20150518222227.26852.67400@psf.io> https://hg.python.org/cpython/rev/e6e1847aa6da changeset: 96143:e6e1847aa6da branch: 3.4 parent: 96140:3d5bf6174c4b user: Berker Peksag date: Tue May 19 01:21:28 2015 +0300 summary: Fix typo in Nisc/NEWS. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,7 +57,7 @@ argument instead of a ValueError with a bogus FCI error number. Patch by Jeffrey Armstrong. -- Issue #23796: peak and read1 methods of BufferedReader now raise ValueError +- Issue #23796: peek and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. - Issue #24094: Fix possible crash in json.encode with poorly behaved dict -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:22:27 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:22:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fix_typo_in_Misc/NEWS=2E?= Message-ID: <20150518222227.26840.67817@psf.io> https://hg.python.org/cpython/rev/ec4fa4227139 changeset: 96144:ec4fa4227139 parent: 96141:bc6ed8360312 parent: 96143:e6e1847aa6da user: Berker Peksag date: Tue May 19 01:22:29 2015 +0300 summary: Fix typo in Misc/NEWS. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -87,7 +87,7 @@ - Issue #22682: Added support for the kz1048 encoding. -- Issue #23796: peak and read1 methods of BufferedReader now raise ValueError +- Issue #23796: peek and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. - Issue #21795: smtpd now supports the 8BITMIME extension whenever -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:28:06 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:28:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_Sphinx_compile_error?= =?utf-8?q?=2E?= Message-ID: <20150518222805.32293.99331@psf.io> https://hg.python.org/cpython/rev/51b1187c9917 changeset: 96145:51b1187c9917 user: Berker Peksag date: Tue May 19 01:28:07 2015 +0300 summary: Fix Sphinx compile error. ../../Misc/NEWS:60: ERROR: Unknown target name: "mangle_from". files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,7 +58,7 @@ - Issue #13866: *quote_via* argument added to urllib.parse.urlencode. -- Issue #20098: New mangle_from_ policy option for email, default True +- Issue #20098: New mangle_from policy option for email, default True for compat32, but False for all other policies. - Issue #24211: The email library now supports RFC 6532: it can generate -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:31:23 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:31:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjMz?= =?utf-8?q?=3A_Add_a_proper_link_to_socket=2Egetfqdn=28=29_documentation?= =?utf-8?q?=2E?= Message-ID: <20150518223123.4251.65427@psf.io> https://hg.python.org/cpython/rev/f6e7953b5431 changeset: 96146:f6e7953b5431 branch: 3.4 parent: 96143:e6e1847aa6da user: Berker Peksag date: Tue May 19 01:31:00 2015 +0300 summary: Issue #24233: Add a proper link to socket.getfqdn() documentation. Patch by Ville Skytt?. files: Doc/library/socket.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -513,7 +513,7 @@ always hold. Note: :func:`gethostname` doesn't always return the fully qualified domain - name; use ``getfqdn()`` (see above). + name; use :func:`getfqdn` for that. .. function:: gethostbyaddr(ip_address) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:31:24 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:31:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324233=3A_Add_a_proper_link_to_socket=2Egetfqdn?= =?utf-8?q?=28=29_documentation=2E?= Message-ID: <20150518223123.39245.64519@psf.io> https://hg.python.org/cpython/rev/0d6902537062 changeset: 96147:0d6902537062 parent: 96145:51b1187c9917 parent: 96146:f6e7953b5431 user: Berker Peksag date: Tue May 19 01:31:24 2015 +0300 summary: Issue #24233: Add a proper link to socket.getfqdn() documentation. Patch by Ville Skytt?. files: Doc/library/socket.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -530,7 +530,7 @@ always hold. Note: :func:`gethostname` doesn't always return the fully qualified domain - name; use ``getfqdn()`` (see above). + name; use :func:`getfqdn` for that. .. function:: gethostbyaddr(ip_address) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:38:03 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:38:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324232=3A_Fix_typos=2E_Patch_by_Ville_Skytt?= =?utf-8?b?w6Qu?= Message-ID: <20150518223803.26580.30951@psf.io> https://hg.python.org/cpython/rev/fc2eed9fc2d0 changeset: 96149:fc2eed9fc2d0 parent: 96147:0d6902537062 parent: 96148:fd7ef3972215 user: Berker Peksag date: Tue May 19 01:38:05 2015 +0300 summary: Issue #24232: Fix typos. Patch by Ville Skytt?. files: Doc/howto/clinic.rst | 2 +- Doc/howto/logging-cookbook.rst | 2 +- Doc/library/collections.rst | 2 +- Doc/library/poplib.rst | 2 +- Doc/library/ssl.rst | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -1495,7 +1495,7 @@ the ``buffer`` preset. Suppresses the ``impl_prototype``, write the ``docstring_definition`` - and ``parser_defintion`` to ``buffer``, write everything else to ``block``. + and ``parser_definition`` to ``buffer``, write everything else to ``block``. The third new directive is ``destination``:: diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1417,7 +1417,7 @@ def worker_process(config): """ A number of these are spawned for the purpose of illustration. In - practice, they could be a heterogenous bunch of processes rather than + practice, they could be a heterogeneous bunch of processes rather than ones which are identical to each other. This initialises logging according to the specified configuration, diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -333,7 +333,7 @@ >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2}) -Unary addition and substraction are shortcuts for adding an empty counter +Unary addition and subtraction are shortcuts for adding an empty counter or subtracting from an empty counter. >>> c = Counter(a=2, b=-4) diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -197,7 +197,7 @@ .. method:: POP3.utf8() - Try to switch to UTF-8 mode. Returns the server response if sucessful, + Try to switch to UTF-8 mode. Returns the server response if successful, raises :class:`error_proto` if not. Specified in :RFC:`6856`. .. versionadded:: 3.5 diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1381,7 +1381,7 @@ .. attribute:: SSLContext.check_hostname - Wether to match the peer cert's hostname with :func:`match_hostname` in + Whether to match the peer cert's hostname with :func:`match_hostname` in :meth:`SSLSocket.do_handshake`. The context's :attr:`~SSLContext.verify_mode` must be set to :data:`CERT_OPTIONAL` or :data:`CERT_REQUIRED`, and you must pass *server_hostname* to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 00:38:04 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 18 May 2015 22:38:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjMy?= =?utf-8?q?=3A_Fix_typos=2E_Patch_by_Ville_Skytt=C3=A4=2E?= Message-ID: <20150518223803.32313.17503@psf.io> https://hg.python.org/cpython/rev/fd7ef3972215 changeset: 96148:fd7ef3972215 branch: 3.4 parent: 96146:f6e7953b5431 user: Berker Peksag date: Tue May 19 01:36:55 2015 +0300 summary: Issue #24232: Fix typos. Patch by Ville Skytt?. files: Doc/howto/clinic.rst | 2 +- Doc/howto/logging-cookbook.rst | 2 +- Doc/library/collections.rst | 2 +- Doc/library/ssl.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -1498,7 +1498,7 @@ the ``buffer`` preset. Suppresses the ``impl_prototype``, write the ``docstring_definition`` - and ``parser_defintion`` to ``buffer``, write everything else to ``block``. + and ``parser_definition`` to ``buffer``, write everything else to ``block``. The third new directive is ``destination``:: diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1408,7 +1408,7 @@ def worker_process(config): """ A number of these are spawned for the purpose of illustration. In - practice, they could be a heterogenous bunch of processes rather than + practice, they could be a heterogeneous bunch of processes rather than ones which are identical to each other. This initialises logging according to the specified configuration, diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -333,7 +333,7 @@ >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2}) -Unary addition and substraction are shortcuts for adding an empty counter +Unary addition and subtraction are shortcuts for adding an empty counter or subtracting from an empty counter. >>> c = Counter(a=2, b=-4) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1269,7 +1269,7 @@ .. attribute:: SSLContext.check_hostname - Wether to match the peer cert's hostname with :func:`match_hostname` in + Whether to match the peer cert's hostname with :func:`match_hostname` in :meth:`SSLSocket.do_handshake`. The context's :attr:`~SSLContext.verify_mode` must be set to :data:`CERT_OPTIONAL` or :data:`CERT_REQUIRED`, and you must pass *server_hostname* to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 03:43:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 19 May 2015 01:43:46 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_update_since_2=2E7=2E0_was_lo?= =?utf-8?q?ng_ago?= Message-ID: <20150519014346.39239.21525@psf.io> https://hg.python.org/peps/rev/031dbdb38d00 changeset: 5861:031dbdb38d00 user: Benjamin Peterson date: Mon May 18 21:43:44 2015 -0400 summary: update since 2.7.0 was long ago files: pep-0373.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0373.txt b/pep-0373.txt --- a/pep-0373.txt +++ b/pep-0373.txt @@ -49,7 +49,7 @@ Release Schedule ================ -The current schedule is: +The release schedule for 2.7.0 was: - 2.7 alpha 1 2009-12-05 - 2.7 alpha 2 2010-01-09 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 19 06:27:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 19 May 2015 04:27:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24205=3A_Improve_ins?= =?utf-8?q?pect=2ESignature=2Ebind=28=29_error_messages=2E?= Message-ID: <20150519042754.125540.76031@psf.io> https://hg.python.org/cpython/rev/3cc368d334c5 changeset: 96150:3cc368d334c5 user: Yury Selivanov date: Tue May 19 00:27:49 2015 -0400 summary: Issue 24205: Improve inspect.Signature.bind() error messages. files: Lib/inspect.py | 16 ++++++++---- Lib/test/test_inspect.py | 34 +++++++++++++++++---------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2762,7 +2762,7 @@ parameters_ex = (param,) break else: - msg = '{arg!r} parameter lacking default value' + msg = 'missing a required argument: {arg!r}' msg = msg.format(arg=param.name) raise TypeError(msg) from None else: @@ -2775,7 +2775,8 @@ if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): # Looks like we have no parameter for this positional # argument - raise TypeError('too many positional arguments') + raise TypeError( + 'too many positional arguments') from None if param.kind == _VAR_POSITIONAL: # We have an '*args'-like argument, let's fill it with @@ -2787,8 +2788,9 @@ break if param.name in kwargs: - raise TypeError('multiple values for argument ' - '{arg!r}'.format(arg=param.name)) + raise TypeError( + 'multiple values for argument {arg!r}'.format( + arg=param.name)) from None arguments[param.name] = arg_val @@ -2817,7 +2819,7 @@ # arguments. if (not partial and param.kind != _VAR_POSITIONAL and param.default is _empty): - raise TypeError('{arg!r} parameter lacking default value'. \ + raise TypeError('missing a required argument: {arg!r}'. \ format(arg=param_name)) from None else: @@ -2836,7 +2838,9 @@ # Process our '**kwargs'-like parameter arguments[kwargs_param.name] = kwargs else: - raise TypeError('too many keyword arguments') + raise TypeError( + 'got an unexpected keyword argument {arg!r}'.format( + arg=next(iter(kwargs)))) return self._bound_arguments_cls(self, arguments) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2891,7 +2891,9 @@ self.call(test, 1) with self.assertRaisesRegex(TypeError, 'too many positional arguments'): self.call(test, 1, spam=10) - with self.assertRaisesRegex(TypeError, 'too many keyword arguments'): + with self.assertRaisesRegex( + TypeError, "got an unexpected keyword argument 'spam'"): + self.call(test, spam=1) def test_signature_bind_var(self): @@ -2916,10 +2918,12 @@ with self.assertRaisesRegex(TypeError, 'too many positional arguments'): self.call(test, 1, 2, 3, 4) - with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"): + with self.assertRaisesRegex(TypeError, + "missing a required argument: 'b'"): self.call(test, 1) - with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"): + with self.assertRaisesRegex(TypeError, + "missing a required argument: 'a'"): self.call(test) def test(a, b, c=10): @@ -2992,7 +2996,7 @@ def test(a, *, foo=1, bar): return foo with self.assertRaisesRegex(TypeError, - "'bar' parameter lacking default value"): + "missing a required argument: 'bar'"): self.call(test, 1) def test(foo, *, bar): @@ -3000,8 +3004,9 @@ self.assertEqual(self.call(test, 1, bar=2), (1, 2)) self.assertEqual(self.call(test, bar=2, foo=1), (1, 2)) - with self.assertRaisesRegex(TypeError, - 'too many keyword arguments'): + with self.assertRaisesRegex( + TypeError, "got an unexpected keyword argument 'spam'"): + self.call(test, bar=2, foo=1, spam=10) with self.assertRaisesRegex(TypeError, @@ -3012,12 +3017,13 @@ 'too many positional arguments'): self.call(test, 1, 2, bar=2) + with self.assertRaisesRegex( + TypeError, "got an unexpected keyword argument 'spam'"): + + self.call(test, 1, bar=2, spam='ham') + with self.assertRaisesRegex(TypeError, - 'too many keyword arguments'): - self.call(test, 1, bar=2, spam='ham') - - with self.assertRaisesRegex(TypeError, - "'bar' parameter lacking default value"): + "missing a required argument: 'bar'"): self.call(test, 1) def test(foo, *, bar, **bin): @@ -3029,7 +3035,7 @@ self.assertEqual(self.call(test, spam='ham', foo=1, bar=2), (1, 2, {'spam': 'ham'})) with self.assertRaisesRegex(TypeError, - "'foo' parameter lacking default value"): + "missing a required argument: 'foo'"): self.call(test, spam='ham', bar=2) self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10), (1, 2, {'bin': 1, 'spam': 10})) @@ -3094,7 +3100,9 @@ return a, args sig = inspect.signature(test) - with self.assertRaisesRegex(TypeError, "too many keyword arguments"): + with self.assertRaisesRegex( + TypeError, "got an unexpected keyword argument 'args'"): + sig.bind(a=0, args=1) def test(*args, **kwargs): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 09:11:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 07:11:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzY1OTg6?= =?utf-8?q?_Increased_time_precision_and_random_number_range_in?= Message-ID: <20150519071105.26830.33211@psf.io> https://hg.python.org/cpython/rev/6969bac411fa changeset: 96151:6969bac411fa branch: 2.7 parent: 96142:cebd51686565 user: Serhiy Storchaka date: Tue May 19 10:09:27 2015 +0300 summary: Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. files: Lib/email/test/test_email.py | 25 +++++++++++++++++++++++- Lib/email/utils.py | 9 +++---- Misc/NEWS | 3 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -12,6 +12,10 @@ import textwrap from cStringIO import StringIO from random import choice +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread import email @@ -33,7 +37,7 @@ from email import base64MIME from email import quopriMIME -from test.test_support import findfile, run_unittest +from test.test_support import findfile, run_unittest, start_threads from email.test import __file__ as landmark @@ -2412,6 +2416,25 @@ addrs = Utils.getaddresses(['User ((nested comment)) ']) eq(addrs[0][1], 'foo at bar.com') + def test_make_msgid_collisions(self): + # Test make_msgid uniqueness, even with multiple threads + class MsgidsThread(Thread): + def run(self): + # generate msgids for 3 seconds + self.msgids = [] + append = self.msgids.append + make_msgid = Utils.make_msgid + clock = time.clock + tfin = clock() + 3.0 + while clock() < tfin: + append(make_msgid()) + + threads = [MsgidsThread() for i in range(5)] + with start_threads(threads): + pass + all_ids = sum([t.msgids for t in threads], []) + self.assertEqual(len(set(all_ids)), len(all_ids)) + def test_utils_quote_unquote(self): eq = self.assertEqual msg = Message() diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -177,21 +177,20 @@ def make_msgid(idstring=None): """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: - <20020201195627.33539.96671 at nightshade.la.mastaler.com> + <142480216486.20800.16526388040877946887 at nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the uniqueness of the message id. """ - timeval = time.time() - utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + timeval = int(time.time()*100) pid = os.getpid() - randint = random.randrange(100000) + randint = random.getrandbits(64) if idstring is None: idstring = '' else: idstring = '.' + idstring idhost = socket.getfqdn() - msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost) + msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, idhost) return msgid diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #6598: Increased time precision and random number range in + email.utils.make_msgid() to strengthen the uniqueness of the message ID. + - Issue #24091: Fixed various crashes in corner cases in cElementTree. - Issue #15267: HTTPConnection.request() now is compatibile with old-style -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 09:11:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 07:11:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzY1OTg6?= =?utf-8?q?_Increased_time_precision_and_random_number_range_in?= Message-ID: <20150519071106.21164.47801@psf.io> https://hg.python.org/cpython/rev/ea878f847eee changeset: 96152:ea878f847eee branch: 3.4 parent: 96148:fd7ef3972215 user: Serhiy Storchaka date: Tue May 19 10:09:42 2015 +0300 summary: Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. files: Lib/email/utils.py | 9 +++--- Lib/test/test_email/test_email.py | 25 ++++++++++++++++++- Misc/NEWS | 3 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -202,24 +202,23 @@ def make_msgid(idstring=None, domain=None): """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: - <20020201195627.33539.96671 at nightshade.la.mastaler.com> + <142480216486.20800.16526388040877946887 at nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the uniqueness of the message id. Optional domain if given provides the portion of the message id after the '@'. It defaults to the locally defined hostname. """ - timeval = time.time() - utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + timeval = int(time.time()*100) pid = os.getpid() - randint = random.randrange(100000) + randint = random.getrandbits(64) if idstring is None: idstring = '' else: idstring = '.' + idstring if domain is None: domain = socket.getfqdn() - msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, domain) + msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, domain) return msgid diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -11,6 +11,10 @@ from io import StringIO, BytesIO from itertools import chain from random import choice +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread import email import email.policy @@ -34,7 +38,7 @@ from email import base64mime from email import quoprimime -from test.support import unlink +from test.support import unlink, start_threads from test.test_email import openfile, TestEmailBase # These imports are documented to work, but we are testing them using a @@ -3152,6 +3156,25 @@ addrs = utils.getaddresses(['User ((nested comment)) ']) eq(addrs[0][1], 'foo at bar.com') + def test_make_msgid_collisions(self): + # Test make_msgid uniqueness, even with multiple threads + class MsgidsThread(Thread): + def run(self): + # generate msgids for 3 seconds + self.msgids = [] + append = self.msgids.append + make_msgid = utils.make_msgid + clock = time.clock + tfin = clock() + 3.0 + while clock() < tfin: + append(make_msgid(domain='testdomain-string')) + + threads = [MsgidsThread() for i in range(5)] + with start_threads(threads): + pass + all_ids = sum([t.msgids for t in threads], []) + self.assertEqual(len(set(all_ids)), len(all_ids)) + def test_utils_quote_unquote(self): eq = self.assertEqual msg = Message() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #6598: Increased time precision and random number range in + email.utils.make_msgid() to strengthen the uniqueness of the message ID. + - Issue #24091: Fixed various crashes in corner cases in C implementation of ElementTree. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 09:11:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 07:11:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=236598=3A_Increased_time_precision_and_random_num?= =?utf-8?q?ber_range_in?= Message-ID: <20150519071106.4237.63887@psf.io> https://hg.python.org/cpython/rev/933addbc7041 changeset: 96153:933addbc7041 parent: 96150:3cc368d334c5 parent: 96152:ea878f847eee user: Serhiy Storchaka date: Tue May 19 10:10:15 2015 +0300 summary: Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. files: Lib/email/utils.py | 9 +++--- Lib/test/test_email/test_email.py | 25 ++++++++++++++++++- Misc/NEWS | 3 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -202,24 +202,23 @@ def make_msgid(idstring=None, domain=None): """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: - <20020201195627.33539.96671 at nightshade.la.mastaler.com> + <142480216486.20800.16526388040877946887 at nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the uniqueness of the message id. Optional domain if given provides the portion of the message id after the '@'. It defaults to the locally defined hostname. """ - timeval = time.time() - utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + timeval = int(time.time()*100) pid = os.getpid() - randint = random.randrange(100000) + randint = random.getrandbits(64) if idstring is None: idstring = '' else: idstring = '.' + idstring if domain is None: domain = socket.getfqdn() - msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, domain) + msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, domain) return msgid diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -11,6 +11,10 @@ from io import StringIO, BytesIO from itertools import chain from random import choice +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread import email import email.policy @@ -34,7 +38,7 @@ from email import base64mime from email import quoprimime -from test.support import unlink +from test.support import unlink, start_threads from test.test_email import openfile, TestEmailBase # These imports are documented to work, but we are testing them using a @@ -3167,6 +3171,25 @@ addrs = utils.getaddresses(['User ((nested comment)) ']) eq(addrs[0][1], 'foo at bar.com') + def test_make_msgid_collisions(self): + # Test make_msgid uniqueness, even with multiple threads + class MsgidsThread(Thread): + def run(self): + # generate msgids for 3 seconds + self.msgids = [] + append = self.msgids.append + make_msgid = utils.make_msgid + clock = time.clock + tfin = clock() + 3.0 + while clock() < tfin: + append(make_msgid(domain='testdomain-string')) + + threads = [MsgidsThread() for i in range(5)] + with start_threads(threads): + pass + all_ids = sum([t.msgids for t in threads], []) + self.assertEqual(len(set(all_ids)), len(all_ids)) + def test_utils_quote_unquote(self): eq = self.assertEqual msg = Message() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,9 @@ Library ------- +- Issue #6598: Increased time precision and random number range in + email.utils.make_msgid() to strengthen the uniqueness of the message ID. + - Issue #24091: Fixed various crashes in corner cases in C implementation of ElementTree. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 10:00:53 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 08:00:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323780=3A_Improved?= =?utf-8?q?_error_message_in_os=2Epath=2Ejoin=28=29_with_single_argument?= =?utf-8?q?=2E?= Message-ID: <20150519080051.125530.40422@psf.io> https://hg.python.org/cpython/rev/84af71e8c051 changeset: 96154:84af71e8c051 user: Serhiy Storchaka date: Tue May 19 11:00:07 2015 +0300 summary: Issue #23780: Improved error message in os.path.join() with single argument. Idea by R. David Murray. files: Lib/macpath.py | 2 ++ Lib/ntpath.py | 2 ++ Lib/posixpath.py | 2 ++ Lib/test/test_genericpath.py | 4 ++++ Misc/NEWS | 2 ++ 5 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Lib/macpath.py b/Lib/macpath.py --- a/Lib/macpath.py +++ b/Lib/macpath.py @@ -53,6 +53,8 @@ try: colon = _get_colon(s) path = s + if not p: + path[:0] + colon #23780: Ensure compatible data type even if p is null. for t in p: if (not path) or isabs(t): path = t diff --git a/Lib/ntpath.py b/Lib/ntpath.py --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -81,6 +81,8 @@ seps = '\\/' colon = ':' try: + if not paths: + path[:0] + sep #23780: Ensure compatible data type even if p is null. result_drive, result_path = splitdrive(path) for p in paths: p_drive, p_path = splitdrive(p) diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -76,6 +76,8 @@ sep = _get_sep(a) path = a try: + if not p: + path[:0] + sep #23780: Ensure compatible data type even if p is null. for b in p: if b.startswith(sep): path = b diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -448,6 +448,10 @@ self.pathmodule.join(42, 'str') with self.assertRaisesRegex(TypeError, errmsg % 'int'): self.pathmodule.join('str', 42) + with self.assertRaisesRegex(TypeError, errmsg % 'int'): + self.pathmodule.join(42) + with self.assertRaisesRegex(TypeError, errmsg % 'list'): + self.pathmodule.join([]) with self.assertRaisesRegex(TypeError, errmsg % 'bytearray'): self.pathmodule.join(bytearray(b'foo'), bytearray(b'bar')) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,8 @@ Library ------- +- Issue #23780: Improved error message in os.path.join() with single argument. + - Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue May 19 10:43:37 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 19 May 2015 08:43:37 +0000 Subject: [Python-checkins] Daily reference leaks (3cc368d334c5): sum=0 Message-ID: <20150519084336.10796.68870@psf.io> results for 3cc368d334c5 on branch "default" -------------------------------------------- test_collections leaked [-2, -2, 0] references, sum=-4 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogIOtZvx', '--timeout', '7200'] From python-checkins at python.org Tue May 19 13:18:50 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 19 May 2015 11:18:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2319662=3A_fix_typo?= Message-ID: <20150519111850.4229.12365@psf.io> https://hg.python.org/cpython/rev/a3f2b171b765 changeset: 96155:a3f2b171b765 user: R David Murray date: Tue May 19 07:18:39 2015 -0400 summary: #19662: fix typo files: Doc/library/smtpd.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst --- a/Doc/library/smtpd.rst +++ b/Doc/library/smtpd.rst @@ -90,7 +90,7 @@ this will always be an empty list. Implementations of ``process_message`` should use the ``**kwargs`` - signature to accept arbitrary keword arguments, since future feature + signature to accept arbitrary keyword arguments, since future feature enhancements may add keys to the kwargs dictionary. Return ``None`` to request a normal ``250 Ok`` response; otherwise -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 14:16:18 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 19 May 2015 12:16:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Back_out_changeset_955dffe?= =?utf-8?q?c3d94_since_it_broke_the_buildbots=2E?= Message-ID: <20150519121611.39265.95599@psf.io> https://hg.python.org/cpython/rev/de9c43fabda6 changeset: 96156:de9c43fabda6 user: R David Murray date: Tue May 19 08:16:04 2015 -0400 summary: Back out changeset 955dffec3d94 since it broke the buildbots. and the situation has not been addressed in several days. files: Lib/test/test_pprint.py | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -91,8 +91,7 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", - bytearray(b"ghi"), True, False, None, + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -162,23 +161,21 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), + for simple in (0, 0, 0+0j, 0.0, "", b"", (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), - (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1), - True, False, None, + range(10, -11, -1) ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -1008,5 +1005,9 @@ self, object, context, maxlevels, level) +def test_main(): + test.support.run_unittest(QueryTestCase) + + if __name__ == "__main__": - unittest.main() + test_main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 14:26:08 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 19 May 2015 12:26:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge=2E?= Message-ID: <20150519122608.26828.21778@psf.io> https://hg.python.org/cpython/rev/abca9f81f408 changeset: 96158:abca9f81f408 parent: 96156:de9c43fabda6 parent: 96157:cf52756f19b6 user: R David Murray date: Tue May 19 08:25:28 2015 -0400 summary: Null merge. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 14:26:08 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 19 May 2015 12:26:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzI0MjE1OiBhbHNv?= =?utf-8?q?_back_out_changeset_that_broke_test=5Ftrace_in_3=2E4=2E?= Message-ID: <20150519122608.32305.75642@psf.io> https://hg.python.org/cpython/rev/cf52756f19b6 changeset: 96157:cf52756f19b6 branch: 3.4 parent: 96152:ea878f847eee user: R David Murray date: Tue May 19 08:24:59 2015 -0400 summary: #24215: also back out changeset that broke test_trace in 3.4. I missed that this change was applied to both branches. files: Lib/test/test_pprint.py | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -58,8 +58,7 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", - bytearray(b"ghi"), True, False, None, + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -129,23 +128,21 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), + for simple in (0, 0, 0+0j, 0.0, "", b"", (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), - (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1), - True, False, None, + range(10, -11, -1) ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -600,5 +597,9 @@ self, object, context, maxlevels, level) +def test_main(): + test.support.run_unittest(QueryTestCase) + + if __name__ == "__main__": - unittest.main() + test_main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 15:02:08 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 19 May 2015 13:02:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_Incorporate_feedba?= =?utf-8?q?ck_from_Tomas_Hoger?= Message-ID: <20150519130208.16304.46721@psf.io> https://hg.python.org/peps/rev/b5e0791f27bf changeset: 5862:b5e0791f27bf user: Nick Coghlan date: Tue May 19 23:02:00 2015 +1000 summary: PEP 493: Incorporate feedback from Tomas Hoger Changes based primarily on design feedback received in https://bugzilla.redhat.com/show_bug.cgi?id=1173041#c21 Some minor issues were pointed out in private email. files: pep-0493.txt | 205 ++++++++++++++++++++++---------------- 1 files changed, 116 insertions(+), 89 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -8,6 +8,7 @@ Content-Type: text/x-rst Created: 10-May-2015 + Abstract ======== @@ -23,6 +24,7 @@ *Note that this PEP is not currently accepted, so it is a *proposed* recommendation, rather than an active one.* + Rationale ========= @@ -69,6 +71,72 @@ version of Python 3 (whether published directly by the Python Software Foundation or by a redistributor). + +Recommendation for an environment variable based security downgrade +=================================================================== + +Some redistributors may wish to provide a per-application option to disable +certificate verification in selected applications that run on or embed CPython +without needing to modify the application itself. + +In these cases, a configuration mechanism is needed that provides: + +* an opt-out model that allows certificate verification to be selectively + turned off for particular applications after upgrading to a version of + Python that verifies certificates by default +* the ability for all users to configure this setting on a per-application + basis, rather than on a per-system, or per-Python-installation basis + +This approach may be used for any redistributor provided version of Python 2.7, +including those that advertise themselves as providing Python 2.7.9 or later. + + +Recommended modifications to the Python standard library +-------------------------------------------------------- + +The recommended approach to providing a per-application configuration setting +for HTTPS certificate verification that doesn't require modifications to the +application itself is to: + +* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment + variable when the module is first imported into a Python process +* set the ``ssl._create_default_https_context`` function to be an alias for + ``ssl._create_unverified_context`` if this environment variable is present + and set to ``'0'`` +* otherwise, set the ``ssl._create_default_https_context`` function to be an + alias for ``ssl.create_default_context`` as usual + + +Example implementation +---------------------- + +:: + + def _get_https_context_factory(): + config_setting = os.environ.get('PYTHONHTTPSVERIFY') + if config_setting == '0': + return _create_unverified_context + return create_default_context + + _create_default_https_context = _get_https_context_factory() + + +Security Considerations +----------------------- + +Relative to an unmodified version of CPython 2.7.9 or later, this approach +does introduce a new downgrade attack against the default security settings +that potentially allows a sufficiently determined attacker to revert Python +to the vulnerable configuration used in CPython 2.7.8 and earlier releases. +Such an attack requires the ability to modify the execution environment of +a Python process prior to the import of the ``ssl`` module. + +Redistributors should balance this marginal increase in risk against the +ability to offer a smoother migration path to their users when deciding whether +or not it is appropriate for them to implement this per-application "opt out" +model. + + Recommendation for backporting to earlier Python versions ========================================================= @@ -82,22 +150,17 @@ Python version where the feature was first backported * the ability for system administrators to set the default behaviour of Python applications and scripts run directly in the system Python installation -* the ability for system administrators to set the default behaviour of Python - applications and scripts run in a ``virtualenv`` created virtual environment * the ability for the redistributor to consider changing the default behaviour of *new* installations at some point in the future without impacting existing installations that have been explicitly configured to skip verifying HTTPS certificates by default -The recommended solution for this scenario should also avoid introducing any -new attack vectors that don't already allow direct attacks against the system -certificate store. - This approach should not be used for any Python installation that advertises itself as providing Python 2.7.9 or later, as most Python users will have the reasonable expectation that all such environments will validate HTTPS certificates by default. + Recommended modifications to the Python standard library -------------------------------------------------------- @@ -107,12 +170,8 @@ * modify the ``ssl`` module to read a system wide configuration file when the module is first imported into a Python process -* default to verifying HTTPS certificates if this configuration file is not - present (this preserves the upstream default behaviour in the absence of the - configuration file) -* if the ``sys.real_prefix`` attribute is defined, read the configuration - setting for virtual environments, otherwise read the configuration setting - for the system Python +* define a platform default behaviour (either verifying or not verifying HTTPS + certificates) to be used if this configuration file is not present * support selection between the following three modes of operation: * ensure HTTPS certificate verification is enabled @@ -123,25 +182,26 @@ either ``ssl.create_default_context`` or ``ssl._create_unverified_context`` based on the given configuration setting. + Recommended file location ------------------------- This approach is currently only defined for \*nix system Python installations. The recommended configuration file name is -(to be confirmed, currently ``/etc/python/cert-verification.cfg``). +``/etc/python/cert-verification.cfg``. The ``.cfg`` filename extension is recommended for consistency with the ``pyvenv.cfg`` used by the ``venv`` module in Python 3's standard library. + Recommended file format ----------------------- The configuration file should use a ConfigParser ini-style format with a -single section named ``[https]`` containing one required setting ``verify``, -and one optional setting ``verify_in_virtualenv``. +single section named ``[https]`` containing one required setting ``verify``. -Permitted values for ``verify`` and ``verify_in_virtualenv`` are: +Permitted values for ``verify`` are: * ``enable``: ensure HTTPS certificate verification is enabled by default * ``disable``: ensure HTTPS certificate verification is disabled by default @@ -152,9 +212,6 @@ ``verify`` setting is set to an unknown value, it should be treated as if the configuration file is not present. -If ``sys.real_prefix`` is set, and the ``verify_in_virtualenv`` setting is -present and set to one of the known options, then it should be used in -preference to the ``verify`` setting. Example implementation ---------------------- @@ -162,29 +219,22 @@ :: def _get_https_context_factory(): - config_file = '/etc/python/cert-verification.conf' + # Check for a system-wide override of the default behaviour + config_file = '/etc/python/cert-verification.cfg' context_factories = { 'enable': create_default_context, 'disable': _create_unverified_context, 'platform_default': _create_unverified_context, # For now :) } - # Check for a system-wide override of the default behaviour - import configparser - config = configparser.RawConfigParser() + import ConfigParser + config = ConfigParser.RawConfigParser() config.read(config_file) - section = 'https' try: verify_mode = config.get('https', 'verify') except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): verify_mode = 'enable' - else: - # Check if there's a different default for a virtual environment - if hasattr(sys, "real_prefix"): - try: - verify_mode = config.get('https', 'verify_in_virtualenv') - except (ConfigParser.NoOptionError): - pass - return context_factories.get(verify_mode, create_default_context) + default_factory = context_factories.get('platform_default') + return context_factories.get(verify_mode, default_factory) _create_default_https_context = _get_https_context_factory() @@ -208,7 +258,7 @@ The intent is that the *only* reason HTTPS verification should be getting turned off system wide when using this approach is because: -* an end user is running a redistributor supported version of CPython rather +* an end user is running a redistributor provided version of CPython rather than running upstream CPython directly * that redistributor has decided to provide a smoother migration path to verifying HTTPS certificates by default than that being provided by the @@ -218,47 +268,21 @@ (at least for the time being) Using an administrator controlled configuration file rather than an environment -variable not only provides compatibility with the ``-E`` switch, but also -ensures that in any situation where an attacker gains sufficient access to allow -them to modify the configuration file, they're likely already in a position to -attack the system certificate store directly. +variable has the essential feature of providing a smoother migraiton path, even +for applications being run with the ``-E`` switch. -Recommendation for an environment variable based security downgrade -=================================================================== -Some redistributors may wish to provide a per-application option to disable -certificate verification in selected applications that run on or embed CPython -without needing to modify the application itself. +Combining the recommendations +============================= -In these cases, a configuration mechanism is needed that provides: +If a redistributor chooses to implement both recommendations, then the +environment variable should take precedence over the system-wide configuration +setting. This allows the setting to be changed for a given user, virtual +environment or application, regardless of the system-wide default behaviour. -* an opt-out model that allows certificate verification to be selectively - turned off for particular applications after upgrading to a version of - Python that verifies certificates by default -* the ability for all users to configure this setting on a per-application - basis, rather than on a per-system, or per-Python-installation basis - -This recommendation is not considered appropriate for system wide Python -installations, but may be suitable for user level Python installations and -versions of Python embedded in or bundled with particular applications. - -This approach may be used for Python installations that advertises -themselves as providing Python 2.7.9 or later. - -Recommended modifications to the Python standard library --------------------------------------------------------- - -The recommended approach to providing a per-application configuration setting -for HTTPS certificate verification that doesn't require modifications to the -application itself is to: - -* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment - variable when the module is first imported into a Python process -* set the ``ssl._create_default_https_context`` function to be an alias for - ``ssl._create_unverified_context`` if this environment variable is present - and set to '0' -* otherwise, set the ``ssl._create_default_https_context`` function to be an - alias for ``ssl.create_default_context`` as usual +In this case, if ``PYTHONHTTPSVERIFY`` environment variable is defined, and set +to anything *other* than ``'0'``, then HTTPS certificate verification should be +enabled. Example implementation ---------------------- @@ -266,30 +290,33 @@ :: def _get_https_context_factory(): + # Check for am environmental override of the default behaviour config_setting = os.environ.get('PYTHONHTTPSVERIFY') - if config_setting == '0': - return _create_unverified_context - return create_default_context + if config_setting is not None: + if config_setting == '0': + return _create_unverified_context + return create_default_context + + # Check for a system-wide override of the default behaviour + config_file = '/etc/python/cert-verification.cfg' + context_factories = { + 'enable': create_default_context, + 'disable': _create_unverified_context, + 'platform_default': _create_unverified_context, # For now :) + } + import ConfigParser + config = ConfigParser.RawConfigParser() + config.read(config_file) + try: + verify_mode = config.get('https', 'verify') + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + verify_mode = 'enable' + default_factory = context_factories.get('platform_default') + return context_factories.get(verify_mode, default_factory) _create_default_https_context = _get_https_context_factory() -Security Considerations ------------------------ - -Relative to an unmodified version of CPython 2.7.9 or later, this approach -does introduce a new downgrade attack against the default security settings -that potentially allows a sufficiently determined attacker to revert Python -to the vulnerable configuration used in CPython 2.7.8 and earlier releases. -Such an attack requires the ability to modify the execution environment of -a Python process prior to the import of the ``ssl`` module. - -Redistributors should balance this marginal increase in risk against the -ability to offer a smoother migration path to their users when deciding whether -or not it is appropriate for them to implement this per-application "opt out" -model. - - Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 19 15:17:17 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 19 May 2015 13:17:17 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_fix_typo?= Message-ID: <20150519131717.10808.10559@psf.io> https://hg.python.org/peps/rev/a6078f39c50c changeset: 5863:a6078f39c50c user: Nick Coghlan date: Tue May 19 23:17:09 2015 +1000 summary: PEP 493: fix typo files: pep-0493.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -280,9 +280,9 @@ setting. This allows the setting to be changed for a given user, virtual environment or application, regardless of the system-wide default behaviour. -In this case, if ``PYTHONHTTPSVERIFY`` environment variable is defined, and set -to anything *other* than ``'0'``, then HTTPS certificate verification should be -enabled. +In this case, if the ``PYTHONHTTPSVERIFY`` environment variable is defined, and +set to anything *other* than ``'0'``, then HTTPS certificate verification +should be enabled. Example implementation ---------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 19 15:30:18 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 19 May 2015 13:30:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_493=3A_default_to_platfor?= =?utf-8?q?m_default_in_examples?= Message-ID: <20150519133016.32287.54660@psf.io> https://hg.python.org/peps/rev/19c17ec83bcd changeset: 5864:19c17ec83bcd user: Nick Coghlan date: Tue May 19 23:30:08 2015 +1000 summary: PEP 493: default to platform default in examples files: pep-0493.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0493.txt b/pep-0493.txt --- a/pep-0493.txt +++ b/pep-0493.txt @@ -232,7 +232,7 @@ try: verify_mode = config.get('https', 'verify') except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): - verify_mode = 'enable' + verify_mode = 'platform_default' default_factory = context_factories.get('platform_default') return context_factories.get(verify_mode, default_factory) @@ -310,7 +310,7 @@ try: verify_mode = config.get('https', 'verify') except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): - verify_mode = 'enable' + verify_mode = 'platform_default' default_factory = context_factories.get('platform_default') return context_factories.get(verify_mode, default_factory) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 19 20:55:49 2015 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 19 May 2015 18:55:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTg1?= =?utf-8?q?=3A_Fix_a_possible_buffer_overrun_when_deleting_a_slice_from_th?= =?utf-8?q?e?= Message-ID: <20150519185548.4229.26566@psf.io> https://hg.python.org/cpython/rev/98c1201d8eea changeset: 96159:98c1201d8eea branch: 3.4 parent: 96157:cf52756f19b6 user: Antoine Pitrou date: Tue May 19 20:52:27 2015 +0200 summary: Issue #23985: Fix a possible buffer overrun when deleting a slice from the front of a bytearray and then appending some other bytes data. Patch by Martin Panter. files: Lib/test/test_bytes.py | 16 ++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 8 ++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -947,6 +947,22 @@ b.extend(range(100, 110)) self.assertEqual(list(b), list(range(10, 110))) + def test_fifo_overrun(self): + # Test for issue #23985, a buffer overrun when implementing a FIFO + # Build Python in pydebug mode for best results. + b = bytearray(10) + b.pop() # Defeat expanding buffer off-by-one quirk + del b[:1] # Advance start pointer without reallocating + b += bytes(2) # Append exactly the number of deleted bytes + del b # Free memory buffer, allowing pydebug verification + + def test_del_expand(self): + # Reducing the size should not expand the buffer (issue #23985) + b = bytearray(10) + size = sys.getsizeof(b) + del b[:1] + self.assertLessEqual(sys.getsizeof(b), size) + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23985: Fix a possible buffer overrun when deleting a slice from + the front of a bytearray and then appending some other bytes data. + - Issue #24102: Fixed exception type checking in standard error handlers. - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -179,7 +179,7 @@ return -1; } - if (size + logical_offset + 1 < alloc) { + if (size + logical_offset + 1 <= alloc) { /* Current buffer is large enough to host the requested size, decide on a strategy. */ if (size < alloc / 2) { @@ -298,11 +298,7 @@ PyBuffer_Release(&vo); return PyErr_NoMemory(); } - if (size < self->ob_alloc) { - Py_SIZE(self) = size; - PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0'; /* Trailing null byte */ - } - else if (PyByteArray_Resize((PyObject *)self, size) < 0) { + if (PyByteArray_Resize((PyObject *)self, size) < 0) { PyBuffer_Release(&vo); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 20:55:48 2015 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 19 May 2015 18:55:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323985=3A_Fix_a_possible_buffer_overrun_when_del?= =?utf-8?q?eting_a_slice_from_the?= Message-ID: <20150519185548.44685.42974@psf.io> https://hg.python.org/cpython/rev/06fab9093973 changeset: 96160:06fab9093973 parent: 96158:abca9f81f408 parent: 96159:98c1201d8eea user: Antoine Pitrou date: Tue May 19 20:55:42 2015 +0200 summary: Issue #23985: Fix a possible buffer overrun when deleting a slice from the front of a bytearray and then appending some other bytes data. Patch by Martin Panter. files: Lib/test/test_bytes.py | 16 ++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 8 ++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -993,6 +993,22 @@ b.extend(range(100, 110)) self.assertEqual(list(b), list(range(10, 110))) + def test_fifo_overrun(self): + # Test for issue #23985, a buffer overrun when implementing a FIFO + # Build Python in pydebug mode for best results. + b = bytearray(10) + b.pop() # Defeat expanding buffer off-by-one quirk + del b[:1] # Advance start pointer without reallocating + b += bytes(2) # Append exactly the number of deleted bytes + del b # Free memory buffer, allowing pydebug verification + + def test_del_expand(self): + # Reducing the size should not expand the buffer (issue #23985) + b = bytearray(10) + size = sys.getsizeof(b) + del b[:1] + self.assertLessEqual(sys.getsizeof(b), size) + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23985: Fix a possible buffer overrun when deleting a slice from + the front of a bytearray and then appending some other bytes data. + - Issue #24102: Fixed exception type checking in standard error handlers. - Issue #15027: The UTF-32 encoder is now 3x to 7x faster. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -187,7 +187,7 @@ return -1; } - if (size + logical_offset + 1 < alloc) { + if (size + logical_offset + 1 <= alloc) { /* Current buffer is large enough to host the requested size, decide on a strategy. */ if (size < alloc / 2) { @@ -331,11 +331,7 @@ PyBuffer_Release(&vo); return PyErr_NoMemory(); } - if (size < self->ob_alloc) { - Py_SIZE(self) = size; - PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0'; /* Trailing null byte */ - } - else if (PyByteArray_Resize((PyObject *)self, size) < 0) { + if (PyByteArray_Resize((PyObject *)self, size) < 0) { PyBuffer_Release(&vo); return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 21:07:34 2015 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 19 May 2015 19:07:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_some_compi?= =?utf-8?q?lation_warnings_when_using_gcc_=28-Wmaybe-uninitialized=29=2E?= Message-ID: <20150519190734.4241.43862@psf.io> https://hg.python.org/cpython/rev/f3d2cfc4f2ab changeset: 96161:f3d2cfc4f2ab branch: 3.4 parent: 96159:98c1201d8eea user: Antoine Pitrou date: Tue May 19 21:04:33 2015 +0200 summary: Fix some compilation warnings when using gcc (-Wmaybe-uninitialized). files: Objects/unicodeobject.c | 36 ++++++++++++++-------------- 1 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3566,6 +3566,7 @@ return unicode; decode_error: + reason = NULL; errmsg = strerror(errno); assert(errmsg != NULL); @@ -3576,10 +3577,9 @@ if (wstr != NULL) { reason = PyUnicode_FromWideChar(wstr, errlen); PyMem_RawFree(wstr); - } else - errmsg = NULL; - } - if (errmsg == NULL) + } + } + if (reason == NULL) reason = PyUnicode_FromString( "mbstowcs() encountered an invalid multibyte sequence"); if (reason == NULL) @@ -9474,7 +9474,7 @@ { Py_ssize_t j; int final_sigma; - Py_UCS4 c; + Py_UCS4 c = 0; /* U+03A3 is in the Final_Sigma context when, it is found like this: \p{cased}\p{case-ignorable}*U+03A3!(\p{case-ignorable}*\p{cased}) @@ -11144,7 +11144,7 @@ static PyObject * unicode_count(PyObject *self, PyObject *args) { - PyObject *substring; + PyObject *substring = NULL; Py_ssize_t start = 0; Py_ssize_t end = PY_SSIZE_T_MAX; PyObject *result; @@ -11332,9 +11332,9 @@ static PyObject * unicode_find(PyObject *self, PyObject *args) { - PyObject *substring; - Py_ssize_t start; - Py_ssize_t end; + PyObject *substring = NULL; + Py_ssize_t start = 0; + Py_ssize_t end = 0; Py_ssize_t result; if (!stringlib_parse_args_finds_unicode("find", args, &substring, @@ -11420,9 +11420,9 @@ unicode_index(PyObject *self, PyObject *args) { Py_ssize_t result; - PyObject *substring; - Py_ssize_t start; - Py_ssize_t end; + PyObject *substring = NULL; + Py_ssize_t start = 0; + Py_ssize_t end = 0; if (!stringlib_parse_args_finds_unicode("index", args, &substring, &start, &end)) @@ -12497,9 +12497,9 @@ static PyObject * unicode_rfind(PyObject *self, PyObject *args) { - PyObject *substring; - Py_ssize_t start; - Py_ssize_t end; + PyObject *substring = NULL; + Py_ssize_t start = 0; + Py_ssize_t end = 0; Py_ssize_t result; if (!stringlib_parse_args_finds_unicode("rfind", args, &substring, @@ -12533,9 +12533,9 @@ static PyObject * unicode_rindex(PyObject *self, PyObject *args) { - PyObject *substring; - Py_ssize_t start; - Py_ssize_t end; + PyObject *substring = NULL; + Py_ssize_t start = 0; + Py_ssize_t end = 0; Py_ssize_t result; if (!stringlib_parse_args_finds_unicode("rindex", args, &substring, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 21:07:36 2015 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 19 May 2015 19:07:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fix_some_compilation_warnings_when_using_gcc_=28-Wmaybe-?= =?utf-8?q?uninitialized=29=2E?= Message-ID: <20150519190734.39269.97546@psf.io> https://hg.python.org/cpython/rev/f3dbeca1e30d changeset: 96162:f3dbeca1e30d parent: 96160:06fab9093973 parent: 96161:f3d2cfc4f2ab user: Antoine Pitrou date: Tue May 19 21:06:04 2015 +0200 summary: Fix some compilation warnings when using gcc (-Wmaybe-uninitialized). files: Objects/unicodeobject.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3530,6 +3530,7 @@ return unicode; decode_error: + reason = NULL; errmsg = strerror(errno); assert(errmsg != NULL); @@ -3540,10 +3541,9 @@ if (wstr != NULL) { reason = PyUnicode_FromWideChar(wstr, errlen); PyMem_RawFree(wstr); - } else - errmsg = NULL; - } - if (errmsg == NULL) + } + } + if (reason == NULL) reason = PyUnicode_FromString( "mbstowcs() encountered an invalid multibyte sequence"); if (reason == NULL) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 23:14:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 21:14:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMTA3?= =?utf-8?q?=3A_tempfile=2Egettempdir=28=29_and_tempfile=2Emkdtemp=28=29_no?= =?utf-8?q?w_try_again?= Message-ID: <20150519211443.125532.26850@psf.io> https://hg.python.org/cpython/rev/63f0ae6e218a changeset: 96163:63f0ae6e218a branch: 2.7 parent: 96151:6969bac411fa user: Serhiy Storchaka date: Wed May 20 00:10:56 2015 +0300 summary: Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not valid (not exists or is a file) on Windows. files: Lib/tempfile.py | 19 ++++++++-- Lib/test/test_tempfile.py | 50 +++++++++++++++++++++++--- Misc/NEWS | 5 ++ 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -205,9 +205,14 @@ _os.unlink(filename) return dir except (OSError, IOError) as e: - if e.args[0] != _errno.EEXIST: - break # no point trying more names in this directory - pass + if e.args[0] == _errno.EEXIST: + continue + if (_os.name == 'nt' and e.args[0] == _errno.EACCES and + _os.path.isdir(dir) and _os.access(dir, _os.W_OK)): + # On windows, when a directory with the chosen name already + # exists, EACCES error code is returned instead of EEXIST. + continue + break # no point trying more names in this directory raise IOError, (_errno.ENOENT, ("No usable temporary directory found in %s" % dirlist)) @@ -242,7 +247,8 @@ except OSError, e: if e.errno == _errno.EEXIST: continue # try again - if _os.name == 'nt' and e.errno == _errno.EACCES: + if (_os.name == 'nt' and e.errno == _errno.EACCES and + _os.path.isdir(dir) and _os.access(dir, _os.W_OK)): # On windows, when a directory with the chosen name already # exists, EACCES error code is returned instead of EEXIST. continue @@ -335,6 +341,11 @@ except OSError, e: if e.errno == _errno.EEXIST: continue # try again + if (_os.name == 'nt' and e.errno == _errno.EACCES and + _os.path.isdir(dir) and _os.access(dir, _os.W_OK)): + # On windows, when a directory with the chosen name already + # exists, EACCES error code is returned instead of EEXIST. + continue raise raise IOError, (_errno.EEXIST, "No usable temporary directory name found") diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -287,7 +287,42 @@ lambda: iter(names)) -class test__mkstemp_inner(TC): +class TestBadTempdir: + + def test_read_only_directory(self): + with _inside_empty_temp_dir(): + oldmode = mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + os.chmod(tempfile.tempdir, mode) + try: + if os.access(tempfile.tempdir, os.W_OK): + self.skipTest("can't set the directory read-only") + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertIn(cm.exception.errno, (errno.EPERM, errno.EACCES)) + self.assertEqual(os.listdir(tempfile.tempdir), []) + finally: + os.chmod(tempfile.tempdir, oldmode) + + def test_nonexisting_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'nonexistent') + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertEqual(cm.exception.errno, errno.ENOENT) + + def test_non_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'file') + open(tempdir, 'wb').close() + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertIn(cm.exception.errno, (errno.ENOTDIR, errno.ENOENT)) + + +class test__mkstemp_inner(TestBadTempdir, TC): """Test the internal function _mkstemp_inner.""" class mkstemped: @@ -400,7 +435,7 @@ self.do_create(bin=0).write("blat\n") # XXX should test that the file really is a text file - def default_mkstemp_inner(self): + def make_temp(self): return tempfile._mkstemp_inner(tempfile.gettempdir(), tempfile.template, '', @@ -411,11 +446,11 @@ # the chosen name already exists with _inside_empty_temp_dir(), \ _mock_candidate_names('aaa', 'aaa', 'bbb'): - (fd1, name1) = self.default_mkstemp_inner() + (fd1, name1) = self.make_temp() os.close(fd1) self.assertTrue(name1.endswith('aaa')) - (fd2, name2) = self.default_mkstemp_inner() + (fd2, name2) = self.make_temp() os.close(fd2) self.assertTrue(name2.endswith('bbb')) @@ -427,7 +462,7 @@ dir = tempfile.mkdtemp() self.assertTrue(dir.endswith('aaa')) - (fd, name) = self.default_mkstemp_inner() + (fd, name) = self.make_temp() os.close(fd) self.assertTrue(name.endswith('bbb')) @@ -542,9 +577,12 @@ test_classes.append(test_mkstemp) -class test_mkdtemp(TC): +class test_mkdtemp(TestBadTempdir, TC): """Test mkdtemp().""" + def make_temp(self): + return tempfile.mkdtemp() + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,11 @@ Library ------- +- Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again + when a directory with the chosen name already exists on Windows as well as + on Unix. tempfile.mkstemp() now fails early if parent directory is not + valid (not exists or is a file) on Windows. + - Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 23:14:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 21:14:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTA3?= =?utf-8?q?=3A_tempfile=2Egettempdir=28=29_and_tempfile=2Emkdtemp=28=29_no?= =?utf-8?q?w_try_again?= Message-ID: <20150519211443.26828.70548@psf.io> https://hg.python.org/cpython/rev/3a387854d106 changeset: 96164:3a387854d106 branch: 3.4 parent: 96161:f3d2cfc4f2ab user: Serhiy Storchaka date: Wed May 20 00:11:48 2015 +0300 summary: Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not valid (not exists or is a file) on Windows. files: Lib/tempfile.py | 18 +++++++++- Lib/test/test_tempfile.py | 47 +++++++++++++++++++++++--- Misc/NEWS | 5 ++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -166,6 +166,13 @@ return dir except FileExistsError: pass + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + break # no point trying more names in this directory except OSError: break # no point trying more names in this directory raise FileNotFoundError(_errno.ENOENT, @@ -204,7 +211,8 @@ except PermissionError: # This exception is thrown when a directory with the chosen name # already exists on windows. - if _os.name == 'nt': + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): continue else: raise @@ -296,6 +304,14 @@ return file except FileExistsError: continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + else: + raise raise FileExistsError(_errno.EEXIST, "No usable temporary directory name found") diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -274,7 +274,39 @@ lambda: iter(names)) -class TestMkstempInner(BaseTestCase): +class TestBadTempdir: + + def test_read_only_directory(self): + with _inside_empty_temp_dir(): + oldmode = mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + os.chmod(tempfile.tempdir, mode) + try: + if os.access(tempfile.tempdir, os.W_OK): + self.skipTest("can't set the directory read-only") + with self.assertRaises(PermissionError): + self.make_temp() + self.assertEqual(os.listdir(tempfile.tempdir), []) + finally: + os.chmod(tempfile.tempdir, oldmode) + + def test_nonexisting_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'nonexistent') + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(FileNotFoundError): + self.make_temp() + + def test_non_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'file') + open(tempdir, 'wb').close() + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises((NotADirectoryError, FileNotFoundError)): + self.make_temp() + + +class TestMkstempInner(TestBadTempdir, BaseTestCase): """Test the internal function _mkstemp_inner.""" class mkstemped: @@ -389,7 +421,7 @@ os.lseek(f.fd, 0, os.SEEK_SET) self.assertEqual(os.read(f.fd, 20), b"blat") - def default_mkstemp_inner(self): + def make_temp(self): return tempfile._mkstemp_inner(tempfile.gettempdir(), tempfile.template, '', @@ -400,11 +432,11 @@ # the chosen name already exists with _inside_empty_temp_dir(), \ _mock_candidate_names('aaa', 'aaa', 'bbb'): - (fd1, name1) = self.default_mkstemp_inner() + (fd1, name1) = self.make_temp() os.close(fd1) self.assertTrue(name1.endswith('aaa')) - (fd2, name2) = self.default_mkstemp_inner() + (fd2, name2) = self.make_temp() os.close(fd2) self.assertTrue(name2.endswith('bbb')) @@ -416,7 +448,7 @@ dir = tempfile.mkdtemp() self.assertTrue(dir.endswith('aaa')) - (fd, name) = self.default_mkstemp_inner() + (fd, name) = self.make_temp() os.close(fd) self.assertTrue(name.endswith('bbb')) @@ -528,9 +560,12 @@ os.rmdir(dir) -class TestMkdtemp(BaseTestCase): +class TestMkdtemp(TestBadTempdir, BaseTestCase): """Test mkdtemp().""" + def make_temp(self): + return tempfile.mkdtemp() + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -53,6 +53,11 @@ Library ------- +- Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again + when a directory with the chosen name already exists on Windows as well as + on Unix. tempfile.mkstemp() now fails early if parent directory is not + valid (not exists or is a file) on Windows. + - Issue #6598: Increased time precision and random number range in email.utils.make_msgid() to strengthen the uniqueness of the message ID. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 19 23:14:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 19 May 2015 21:14:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322107=3A_tempfile=2Egettempdir=28=29_and_tempfi?= =?utf-8?q?le=2Emkdtemp=28=29_now_try_again?= Message-ID: <20150519211443.21146.21875@psf.io> https://hg.python.org/cpython/rev/1134198e23bd changeset: 96165:1134198e23bd parent: 96162:f3dbeca1e30d parent: 96164:3a387854d106 user: Serhiy Storchaka date: Wed May 20 00:14:00 2015 +0300 summary: Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not valid (not exists or is a file) on Windows. files: Lib/tempfile.py | 18 +++++++++- Lib/test/test_tempfile.py | 47 +++++++++++++++++++++++--- Misc/NEWS | 5 ++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -166,6 +166,13 @@ return dir except FileExistsError: pass + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + break # no point trying more names in this directory except OSError: break # no point trying more names in this directory raise FileNotFoundError(_errno.ENOENT, @@ -204,7 +211,8 @@ except PermissionError: # This exception is thrown when a directory with the chosen name # already exists on windows. - if _os.name == 'nt': + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): continue else: raise @@ -296,6 +304,14 @@ return file except FileExistsError: continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + else: + raise raise FileExistsError(_errno.EEXIST, "No usable temporary directory name found") diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -275,7 +275,39 @@ lambda: iter(names)) -class TestMkstempInner(BaseTestCase): +class TestBadTempdir: + + def test_read_only_directory(self): + with _inside_empty_temp_dir(): + oldmode = mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + os.chmod(tempfile.tempdir, mode) + try: + if os.access(tempfile.tempdir, os.W_OK): + self.skipTest("can't set the directory read-only") + with self.assertRaises(PermissionError): + self.make_temp() + self.assertEqual(os.listdir(tempfile.tempdir), []) + finally: + os.chmod(tempfile.tempdir, oldmode) + + def test_nonexisting_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'nonexistent') + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(FileNotFoundError): + self.make_temp() + + def test_non_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'file') + open(tempdir, 'wb').close() + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises((NotADirectoryError, FileNotFoundError)): + self.make_temp() + + +class TestMkstempInner(TestBadTempdir, BaseTestCase): """Test the internal function _mkstemp_inner.""" class mkstemped: @@ -390,7 +422,7 @@ os.lseek(f.fd, 0, os.SEEK_SET) self.assertEqual(os.read(f.fd, 20), b"blat") - def default_mkstemp_inner(self): + def make_temp(self): return tempfile._mkstemp_inner(tempfile.gettempdir(), tempfile.template, '', @@ -401,11 +433,11 @@ # the chosen name already exists with _inside_empty_temp_dir(), \ _mock_candidate_names('aaa', 'aaa', 'bbb'): - (fd1, name1) = self.default_mkstemp_inner() + (fd1, name1) = self.make_temp() os.close(fd1) self.assertTrue(name1.endswith('aaa')) - (fd2, name2) = self.default_mkstemp_inner() + (fd2, name2) = self.make_temp() os.close(fd2) self.assertTrue(name2.endswith('bbb')) @@ -417,7 +449,7 @@ dir = tempfile.mkdtemp() self.assertTrue(dir.endswith('aaa')) - (fd, name) = self.default_mkstemp_inner() + (fd, name) = self.make_temp() os.close(fd) self.assertTrue(name.endswith('bbb')) @@ -529,9 +561,12 @@ os.rmdir(dir) -class TestMkdtemp(BaseTestCase): +class TestMkdtemp(TestBadTempdir, BaseTestCase): """Test mkdtemp().""" + def make_temp(self): + return tempfile.mkdtemp() + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,11 @@ Library ------- +- Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again + when a directory with the chosen name already exists on Windows as well as + on Unix. tempfile.mkstemp() now fails early if parent directory is not + valid (not exists or is a file) on Windows. + - Issue #23780: Improved error message in os.path.join() with single argument. - Issue #6598: Increased time precision and random number range in -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 06:30:07 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 20 May 2015 04:30:07 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_move_historic_schedule_to_the?= =?utf-8?q?_bottom?= Message-ID: <20150520043007.26848.9626@psf.io> https://hg.python.org/peps/rev/bb653d8de2da changeset: 5865:bb653d8de2da user: Benjamin Peterson date: Tue May 19 23:29:57 2015 -0500 summary: move historic schedule to the bottom files: pep-0373.txt | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pep-0373.txt b/pep-0373.txt --- a/pep-0373.txt +++ b/pep-0373.txt @@ -46,21 +46,6 @@ ============================ ================== -Release Schedule -================ - -The release schedule for 2.7.0 was: - -- 2.7 alpha 1 2009-12-05 -- 2.7 alpha 2 2010-01-09 -- 2.7 alpha 3 2010-02-06 -- 2.7 alpha 4 2010-03-06 -- 2.7 beta 1 2010-04-03 -- 2.7 beta 2 2010-05-08 -- 2.7 rc1 2010-06-05 -- 2.7 rc2 2010-06-19 -- 2.7 final 2010-07-03 - Maintenance releases ==================== @@ -94,6 +79,21 @@ - 2.7.9rc1 2014-11-26 - 2.7.9 2014-12-10 +2.7.0 Release Schedule +====================== + +The release schedule for 2.7.0 was: + +- 2.7 alpha 1 2009-12-05 +- 2.7 alpha 2 2010-01-09 +- 2.7 alpha 3 2010-02-06 +- 2.7 alpha 4 2010-03-06 +- 2.7 beta 1 2010-04-03 +- 2.7 beta 2 2010-05-08 +- 2.7 rc1 2010-06-05 +- 2.7 rc2 2010-06-19 +- 2.7 final 2010-07-03 + Possible features for 2.7 ========================= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 20 09:34:05 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 07:34:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316261=3A_Converte?= =?utf-8?q?d_some_bare_except_statements_to_except_statements?= Message-ID: <20150520073405.26828.86950@psf.io> https://hg.python.org/cpython/rev/b3a7215b9ce4 changeset: 96166:b3a7215b9ce4 user: Serhiy Storchaka date: Wed May 20 10:33:40 2015 +0300 summary: Issue #16261: Converted some bare except statements to except statements with specified exception type. Original patch by Ramchandra Apte. files: Lib/functools.py | 2 +- Lib/ipaddress.py | 4 ++-- Lib/uuid.py | 4 ++-- Mac/BuildScript/build-installer.py | 4 ++-- Tools/demo/ss1.py | 8 ++++---- Tools/scripts/eptags.py | 2 +- Tools/unicode/gencodec.py | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -23,7 +23,7 @@ from weakref import WeakKeyDictionary try: from _thread import RLock -except: +except ImportError: class RLock: 'Dummy reentrant lock for builds without threads' def __enter__(self): pass diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -135,7 +135,7 @@ """ try: return address.to_bytes(4, 'big') - except: + except OverflowError: raise ValueError("Address negative or too large for IPv4") @@ -151,7 +151,7 @@ """ try: return address.to_bytes(16, 'big') - except: + except OverflowError: raise ValueError("Address negative or too large for IPv6") diff --git a/Lib/uuid.py b/Lib/uuid.py --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -465,7 +465,7 @@ for libname in ['uuid', 'c']: try: lib = ctypes.CDLL(ctypes.util.find_library(libname)) - except: + except Exception: continue if hasattr(lib, 'uuid_generate_random'): _uuid_generate_random = lib.uuid_generate_random @@ -607,7 +607,7 @@ try: import os return UUID(bytes=os.urandom(16), version=4) - except: + except Exception: import random return UUID(int=random.getrandbits(128), version=4) diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -572,7 +572,7 @@ """ try: f = open(configfile, "r") - except: + except OSError: fatal("Framework configuration file not found: %s" % configfile) for l in f: @@ -814,7 +814,7 @@ except: try: os.unlink(fname) - except: + except OSError: pass def verifyThirdPartyFile(url, checksum, fname): diff --git a/Tools/demo/ss1.py b/Tools/demo/ss1.py --- a/Tools/demo/ss1.py +++ b/Tools/demo/ss1.py @@ -261,7 +261,7 @@ def end_int(self, text): try: self.value = int(text) - except: + except (TypeError, ValueError): self.value = None end_long = end_int @@ -269,13 +269,13 @@ def end_double(self, text): try: self.value = float(text) - except: + except (TypeError, ValueError): self.value = None def end_complex(self, text): try: self.value = complex(text) - except: + except (TypeError, ValueError): self.value = None def end_string(self, text): @@ -763,7 +763,7 @@ for cls in int, float, complex: try: value = cls(text) - except: + except (TypeError, ValueError): continue else: cell = NumericCell(value) diff --git a/Tools/scripts/eptags.py b/Tools/scripts/eptags.py --- a/Tools/scripts/eptags.py +++ b/Tools/scripts/eptags.py @@ -25,7 +25,7 @@ """Append tags found in file named 'filename' to the open file 'outfp'""" try: fp = open(filename, 'r') - except: + except OSError: sys.stderr.write('Cannot open %s\n'%filename) return charno = 0 diff --git a/Tools/unicode/gencodec.py b/Tools/unicode/gencodec.py --- a/Tools/unicode/gencodec.py +++ b/Tools/unicode/gencodec.py @@ -127,7 +127,7 @@ return 'None' try: len(t) - except: + except TypeError: return '0x%0*X' % (precision, t) try: return '(' + ', '.join(['0x%0*X' % (precision, item) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed May 20 11:03:28 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 20 May 2015 09:03:28 +0000 Subject: [Python-checkins] Daily reference leaks (1134198e23bd): sum=2 Message-ID: <20150520090328.26832.81840@psf.io> results for 1134198e23bd on branch "default" -------------------------------------------- test_collections leaked [-2, 0, 0] references, sum=-2 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog1SgArc', '--timeout', '7200'] From python-checkins at python.org Wed May 20 13:28:32 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 20 May 2015 11:28:32 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489_updates_from_Petr_Vik?= =?utf-8?q?torin=2E?= Message-ID: <20150520112826.21170.78342@psf.io> https://hg.python.org/peps/rev/aad7a39a695b changeset: 5866:aad7a39a695b user: Berker Peksag date: Wed May 20 14:27:55 2015 +0300 summary: PEP 489 updates from Petr Viktorin. - Clarify that not all problems with PEP 3121 are solved - Add a pseudo-code overview - Clarify that PyModuleDef_Init does very little - Say that the execution phase isn't done for non-module objects - Link to docs on support for multiple interpreters - Reword text about lack of finder for multi-module extensions - Mention changes in imp and _imp modules - Remove stale footnote files: pep-0489.txt | 207 +++++++++++++++++++++++++++++++++++--- 1 files changed, 187 insertions(+), 20 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -20,10 +20,10 @@ This PEP proposes a redesign of the way in which built-in and extension modules interact with the import machinery. This was last revised for Python 3.0 in PEP -3121, but did not solve all problems at the time. The goal is to solve them -by bringing extension modules closer to the way Python modules behave; -specifically to hook into the ModuleSpec-based loading mechanism -introduced in PEP 451. +3121, but did not solve all problems at the time. The goal is to solve +import-related problems by bringing extension modules closer to the way Python +modules behave; specifically to hook into the ModuleSpec-based loading +mechanism introduced in PEP 451. This proposal draws inspiration from PyType_Spec of PEP 384 to allow extension authors to only define features they need, and to allow future additions @@ -40,6 +40,10 @@ The proposal also allows extension modules with non-ASCII names. +Not all problems tackled in PEP 3121 are solved in this proposal. +In particular, problems with run-time module lookup (PyState_FindModule) +are left to a future PEP. + Motivation ========== @@ -161,7 +165,9 @@ To prevent crashes when the module is loaded in older versions of Python, the PyModuleDef object must be initialized using the newly added -PyModuleDef_Init function. +PyModuleDef_Init function. This sets the object type (which cannot be done +statically on certain compilers), refcount, and internal bookkeeping data +(m_index). For example, an extension module "example" would be exported as:: static PyModuleDef example_def = {...} @@ -175,6 +181,149 @@ The PyModuleDef object must be available for the lifetime of the module created from it ? usually, it will be declared statically. +Pseudo-code Overview +-------------------- + +Here is an overview of how the modified importers will operate. +Details such as logging or handling of errors and invalid states +are left out, and C code is presented with a concise Python-like syntax. + +The framework that calls the importers is explained in PEP 451 +[#pep-0451-loading]_. + +:: + + importlib/_bootstrap.py: + + class BuiltinImporter: + def create_module(self, spec): + module = _imp.create_builtin(spec) + + def exec_module(self, module): + _imp.exec_dynamic(module) + + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) + + importlib/_bootstrap_external.py: + + class ExtensionFileLoader: + def create_module(self, spec): + module = _imp.create_dynamic(spec) + + def exec_module(self, module): + _imp.exec_dynamic(module) + + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) + + Python/import.c (the _imp module): + + def create_dynamic(spec): + name = spec.name + path = spec.origin + + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod + + return _PyImport_LoadDynamicModuleWithSpec(spec) + + def exec_dynamic(module): + if not isinstance(module, types.ModuleType): + # non-modules are skipped -- PyModule_GetDef fails on them + return + + def = PyModule_GetDef(module) + state = PyModule_GetState(module) + if state is NULL: + PyModule_ExecDef(module, def) + + def create_builtin(spec): + name = spec.name + + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod + + for initname, initfunc in PyImport_Inittab: + if name == initname: + m = initfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) + else: + # fall back to single-phase initialization + module = m + _PyImport_FixupExtensionObject(module, name, name) + return module + + Python/importdl.c: + + def _PyImport_LoadDynamicModuleWithSpec(spec): + path = spec.origin + package, dot, name = spec.name.rpartition('.') + + # see the "Non-ASCII module names" section for export_hook_name + hook_name = export_hook_name(name) + + # call platform-specific function for loading exported function + # from shared library + exportfunc = _find_shared_funcptr(hook_name, path) + + m = exportfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) + + module = m + + # fall back to single-phase initialization + .... + + Objects/moduleobject.c: + + def PyModule_FromDefAndSpec(def, spec): + name = spec.name + create = None + for slot, value in def.m_slots: + if slot == Py_mod_create: + create = value + if create: + m = create(spec, def) + else: + m = PyModule_New(name) + + if isinstance(m, types.ModuleType): + m.md_state = None + m.md_def = def + + if def.m_methods: + PyModule_AddFunctions(m, def.m_methods) + if def.m_doc: + PyModule_SetDocString(m, def.m_doc) + + def PyModule_ExecDef(module, def): + if isinstance(module, types.module_type): + if module.md_state is NULL: + # allocate a block of zeroed-out memory + module.md_state = _alloc(module.md_size) + + if def.m_slots is NULL: + return + + for slot, value in def.m_slots: + if slot == Py_mod_exec: + value(module) + Module Creation Phase --------------------- @@ -223,8 +372,10 @@ If the Py_mod_create function returns an instance of types.ModuleType or a subclass (or if a Py_mod_create slot is not present), the import -machinery will associate the PyModuleDef with the module, making it accessible -to PyModule_GetDef, and enabling the m_traverse, m_clear and m_free hooks. +machinery will associate the PyModuleDef with the module. +This also makes the PyModuleDef accessible to execution phase, the +PyModule_GetDef function, and garbage collection routines (traverse, +clear, free). If the Py_mod_create function does not return a module subclass, then m_size must be 0, and m_traverse, m_clear and m_free must all be NULL. @@ -244,6 +395,10 @@ ExecutionLoader.exec_module -- is governed by "execution slots". This PEP only adds one, Py_mod_exec, but others may be added in the future. +The execution phase is done on the PyModuleDef associated with the module +object. For objects that are not a subclass of PyModule_Type (for which +PyModule_GetDef whoud fail), the execution phase is skipped. + Execution slots may be specified multiple times, and are processed in the order they appear in the slots array. When using the default import machinery, they are processed after @@ -289,12 +444,13 @@ In this case, the PyInit hook implements the creation phase, and the execution phase is a no-op. -Modules that need to work unchanged on older versions of Python should not -use multi-phase initialization, because the benefits it brings can't be +Modules that need to work unchanged on older versions of Python should stick to +single-phase initialization, because the benefits it brings can't be back-ported. -Nevertheless, here is an example of a module that supports multi-phase -initialization, and falls back to single-phase when compiled for an older -version of CPython:: +Here is an example of a module that supports multi-phase initialization, +and falls back to single-phase when compiled for an older version of CPython. +It is included mainly as an illustration of the changes needed to enable +multi-phase init:: #include @@ -359,7 +515,8 @@ ----------------------------------------- Extensions using the new initialization scheme are expected to support -subinterpreters and multiple Py_Initialize/Py_Finalize cycles correctly. +subinterpreters and multiple Py_Initialize/Py_Finalize cycles correctly, +avoiding the issues mentioned in Python documentation [#subinterpreter-docs]_. The mechanism is designed to make this easy, but care is still required on the part of the extension author. No user-defined functions, methods, or instances may leak to different @@ -503,10 +660,10 @@ to the library's filename. Note that this mechanism can currently only be used to *load* extra modules, -but not to *find* them. - -Given the filesystem location of a shared library and a module name, -a module may be loaded with:: +but not to *find* them. (This is a limitation of the loader mechanism, +which this PEP does not try to modify.) +To work around the lack of a suitable finder, code like the following +can be used:: import importlib.machinery import importlib.util @@ -562,6 +719,13 @@ PyModuleDef.m_reload changes to PyModuleDef.m_slots. +The internal ``_imp`` module will have backwards incompatible changes: +``create_builtin``, ``create_dynamic``, and ``exec_dynamic`` will be added; +``init_builtin``, ``load_dynamic`` will be removed. + +The undocumented functions ``imp.load_dynamic`` and ``imp.init_builtin`` will +be replaced by backwards-compatible shims. + Possible Future Extensions ========================== @@ -632,9 +796,6 @@ References ========== -.. [#lazy_import_concerns] - https://mail.python.org/pipermail/python-dev/2013-August/128129.html - .. [#pep-0451-attributes] https://www.python.org/dev/peps/pep-0451/#attributes @@ -656,6 +817,12 @@ .. [#findmodule-discussion] https://mail.python.org/pipermail/import-sig/2015-April/000959.html +.. [#pep-0451-loading] + https://www.python.org/dev/peps/pep-0451/#how-loading-will-work] + +.. [#subinterpreter-docs] + https://docs.python.org/3/c-api/init.html#sub-interpreter-support + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 20 15:15:50 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 13:15:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324245=3A_Eliminated_senseless_expect_clauses_th?= =?utf-8?q?at_have_no_any_effect_in?= Message-ID: <20150520131550.32285.92146@psf.io> https://hg.python.org/cpython/rev/5deb169ebb22 changeset: 96170:5deb169ebb22 parent: 96167:004c689d259c parent: 96169:f10ba5313fbb user: Serhiy Storchaka date: Wed May 20 16:15:20 2015 +0300 summary: Issue #24245: Eliminated senseless expect clauses that have no any effect in IDLE. Patch by Martin Panter. files: Lib/idlelib/idle.pyw | 26 +++++++++++--------------- Lib/idlelib/rpc.py | 5 +---- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Lib/idlelib/idle.pyw b/Lib/idlelib/idle.pyw --- a/Lib/idlelib/idle.pyw +++ b/Lib/idlelib/idle.pyw @@ -2,20 +2,16 @@ import idlelib.PyShell except ImportError: # IDLE is not installed, but maybe PyShell is on sys.path: - try: - from . import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() + from . import PyShell + import os + idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) + if idledir != os.getcwd(): + # We're not in the IDLE directory, help the subprocess find run.py + pypath = os.environ.get('PYTHONPATH', '') + if pypath: + os.environ['PYTHONPATH'] = pypath + ':' + idledir + else: + os.environ['PYTHONPATH'] = idledir + PyShell.main() else: idlelib.PyShell.main() diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -340,10 +340,7 @@ n = self.sock.send(s[:BUFSIZE]) except (AttributeError, TypeError): raise OSError("socket no longer exists") - except OSError: - raise - else: - s = s[n:] + s = s[n:] buff = b'' bufneed = 4 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 15:15:49 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 13:15:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjQ1?= =?utf-8?q?=3A_Eliminated_senseless_expect_clauses_that_have_no_any_effect?= =?utf-8?q?_in?= Message-ID: <20150520131549.4231.70518@psf.io> https://hg.python.org/cpython/rev/f10ba5313fbb changeset: 96169:f10ba5313fbb branch: 3.4 parent: 96164:3a387854d106 user: Serhiy Storchaka date: Wed May 20 16:15:02 2015 +0300 summary: Issue #24245: Eliminated senseless expect clauses that have no any effect in IDLE. Patch by Martin Panter. files: Lib/idlelib/idle.pyw | 26 +++++++++++--------------- Lib/idlelib/rpc.py | 5 +---- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Lib/idlelib/idle.pyw b/Lib/idlelib/idle.pyw --- a/Lib/idlelib/idle.pyw +++ b/Lib/idlelib/idle.pyw @@ -2,20 +2,16 @@ import idlelib.PyShell except ImportError: # IDLE is not installed, but maybe PyShell is on sys.path: - try: - from . import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() + from . import PyShell + import os + idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) + if idledir != os.getcwd(): + # We're not in the IDLE directory, help the subprocess find run.py + pypath = os.environ.get('PYTHONPATH', '') + if pypath: + os.environ['PYTHONPATH'] = pypath + ':' + idledir + else: + os.environ['PYTHONPATH'] = idledir + PyShell.main() else: idlelib.PyShell.main() diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -340,10 +340,7 @@ n = self.sock.send(s[:BUFSIZE]) except (AttributeError, TypeError): raise OSError("socket no longer exists") - except OSError: - raise - else: - s = s[n:] + s = s[n:] buff = b'' bufneed = 4 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 15:15:49 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 13:15:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324245=3A_Eliminat?= =?utf-8?q?ed_senseless_expect_clauses_that_have_no_any_effect=2E?= Message-ID: <20150520131549.32305.14241@psf.io> https://hg.python.org/cpython/rev/004c689d259c changeset: 96167:004c689d259c user: Serhiy Storchaka date: Wed May 20 16:10:04 2015 +0300 summary: Issue #24245: Eliminated senseless expect clauses that have no any effect. Patch by Martin Panter. files: Lib/distutils/core.py | 2 -- Lib/test/regrtest.py | 4 ---- Lib/test/test_urllib2net.py | 2 -- Lib/tkinter/font.py | 2 -- Lib/unittest/test/support.py | 4 ---- 5 files changed, 0 insertions(+), 14 deletions(-) diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py --- a/Lib/distutils/core.py +++ b/Lib/distutils/core.py @@ -221,8 +221,6 @@ # Hmm, should we do something if exiting with a non-zero code # (ie. error)? pass - except: - raise if _setup_distribution is None: raise RuntimeError(("'distutils.core.setup()' was never called -- " diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -765,8 +765,6 @@ except KeyboardInterrupt: interrupted = True break - except: - raise if ns.findleaks: gc.collect() if gc.garbage: @@ -823,8 +821,6 @@ # print a newline separate from the ^C print() break - except: - raise if ns.single: if next_single_test: diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -20,8 +20,6 @@ except exc as e: last_exc = e continue - except: - raise raise last_exc def _wrap_with_retry_thrice(func, exc): diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -112,8 +112,6 @@ try: if self.delete_font: self._call("font", "delete", self.name) - except (KeyboardInterrupt, SystemExit): - raise except Exception: pass diff --git a/Lib/unittest/test/support.py b/Lib/unittest/test/support.py --- a/Lib/unittest/test/support.py +++ b/Lib/unittest/test/support.py @@ -25,8 +25,6 @@ try: if not hash(obj_1) == hash(obj_2): self.fail("%r and %r do not hash equal" % (obj_1, obj_2)) - except KeyboardInterrupt: - raise except Exception as e: self.fail("Problem hashing %r and %r: %s" % (obj_1, obj_2, e)) @@ -35,8 +33,6 @@ if hash(obj_1) == hash(obj_2): self.fail("%s and %s hash equal, but shouldn't" % (obj_1, obj_2)) - except KeyboardInterrupt: - raise except Exception as e: self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 15:15:49 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 13:15:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MjQ1?= =?utf-8?q?=3A_Eliminated_senseless_expect_clauses_that_have_no_any_effect?= =?utf-8?q?_in?= Message-ID: <20150520131549.125544.43918@psf.io> https://hg.python.org/cpython/rev/56e1d24806b3 changeset: 96168:56e1d24806b3 branch: 2.7 parent: 96163:63f0ae6e218a user: Serhiy Storchaka date: Wed May 20 16:14:54 2015 +0300 summary: Issue #24245: Eliminated senseless expect clauses that have no any effect in IDLE. Patch by Martin Panter. files: Lib/idlelib/idle.pyw | 26 +++++++++++--------------- Lib/idlelib/rpc.py | 5 +---- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Lib/idlelib/idle.pyw b/Lib/idlelib/idle.pyw --- a/Lib/idlelib/idle.pyw +++ b/Lib/idlelib/idle.pyw @@ -2,20 +2,16 @@ import idlelib.PyShell except ImportError: # IDLE is not installed, but maybe PyShell is on sys.path: - try: - import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() + import PyShell + import os + idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) + if idledir != os.getcwd(): + # We're not in the IDLE directory, help the subprocess find run.py + pypath = os.environ.get('PYTHONPATH', '') + if pypath: + os.environ['PYTHONPATH'] = pypath + ':' + idledir + else: + os.environ['PYTHONPATH'] = idledir + PyShell.main() else: idlelib.PyShell.main() diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -332,10 +332,7 @@ n = self.sock.send(s[:BUFSIZE]) except (AttributeError, TypeError): raise IOError, "socket no longer exists" - except socket.error: - raise - else: - s = s[n:] + s = s[n:] buffer = "" bufneed = 4 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 17:29:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 15:29:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322955=3A_attrgett?= =?utf-8?q?er=2C_itemgetter_and_methodcaller_objects_in_the_operator?= Message-ID: <20150520152944.26826.38949@psf.io> https://hg.python.org/cpython/rev/435bc22f39e3 changeset: 96171:435bc22f39e3 user: Serhiy Storchaka date: Wed May 20 18:29:18 2015 +0300 summary: Issue #22955: attrgetter, itemgetter and methodcaller objects in the operator module now support pickling. Added readable and evaluable repr for these objects. Based on patch by Josh Rosenberg. files: Lib/operator.py | 46 ++++- Lib/test/test_operator.py | 109 ++++++++++ Misc/NEWS | 4 + Modules/_operator.c | 277 +++++++++++++++++++++++++- 4 files changed, 427 insertions(+), 9 deletions(-) diff --git a/Lib/operator.py b/Lib/operator.py --- a/Lib/operator.py +++ b/Lib/operator.py @@ -231,10 +231,13 @@ After h = attrgetter('name.first', 'name.last'), the call h(r) returns (r.name.first, r.name.last). """ + __slots__ = ('_attrs', '_call') + def __init__(self, attr, *attrs): if not attrs: if not isinstance(attr, str): raise TypeError('attribute name must be a string') + self._attrs = (attr,) names = attr.split('.') def func(obj): for name in names: @@ -242,7 +245,8 @@ return obj self._call = func else: - getters = tuple(map(attrgetter, (attr,) + attrs)) + self._attrs = (attr,) + attrs + getters = tuple(map(attrgetter, self._attrs)) def func(obj): return tuple(getter(obj) for getter in getters) self._call = func @@ -250,19 +254,30 @@ def __call__(self, obj): return self._call(obj) + def __repr__(self): + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__qualname__, + ', '.join(map(repr, self._attrs))) + + def __reduce__(self): + return self.__class__, self._attrs + class itemgetter: """ Return a callable object that fetches the given item(s) from its operand. After f = itemgetter(2), the call f(r) returns r[2]. After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) """ + __slots__ = ('_items', '_call') + def __init__(self, item, *items): if not items: + self._items = (item,) def func(obj): return obj[item] self._call = func else: - items = (item,) + items + self._items = items = (item,) + items def func(obj): return tuple(obj[i] for i in items) self._call = func @@ -270,6 +285,14 @@ def __call__(self, obj): return self._call(obj) + def __repr__(self): + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__name__, + ', '.join(map(repr, self._items))) + + def __reduce__(self): + return self.__class__, self._items + class methodcaller: """ Return a callable object that calls the given method on its operand. @@ -277,6 +300,7 @@ After g = methodcaller('name', 'date', foo=1), the call g(r) returns r.name('date', foo=1). """ + __slots__ = ('_name', '_args', '_kwargs') def __init__(*args, **kwargs): if len(args) < 2: @@ -284,12 +308,30 @@ raise TypeError(msg) self = args[0] self._name = args[1] + if not isinstance(self._name, str): + raise TypeError('method name must be a string') self._args = args[2:] self._kwargs = kwargs def __call__(self, obj): return getattr(obj, self._name)(*self._args, **self._kwargs) + def __repr__(self): + args = [repr(self._name)] + args.extend(map(repr, self._args)) + args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items()) + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__name__, + ', '.join(args)) + + def __reduce__(self): + if not self._kwargs: + return self.__class__, (self._name,) + self._args + else: + from functools import partial + return partial(self.__class__, self._name, **self._kwargs), self._args + + # In-place Operations *********************************************************# def iadd(a, b): diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -1,4 +1,6 @@ import unittest +import pickle +import sys from test import support @@ -35,6 +37,9 @@ class OperatorTestCase: + def setUp(self): + sys.modules['operator'] = self.module + def test_lt(self): operator = self.module self.assertRaises(TypeError, operator.lt) @@ -396,6 +401,7 @@ def test_methodcaller(self): operator = self.module self.assertRaises(TypeError, operator.methodcaller) + self.assertRaises(TypeError, operator.methodcaller, 12) class A: def foo(self, *args, **kwds): return args[0] + args[1] @@ -491,5 +497,108 @@ class COperatorTestCase(OperatorTestCase, unittest.TestCase): module = c_operator + +class OperatorPickleTestCase: + def copy(self, obj, proto): + with support.swap_item(sys.modules, 'operator', self.module): + pickled = pickle.dumps(obj, proto) + with support.swap_item(sys.modules, 'operator', self.module2): + return pickle.loads(pickled) + + def test_attrgetter(self): + attrgetter = self.module.attrgetter + attrgetter = self.module.attrgetter + class A: + pass + a = A() + a.x = 'X' + a.y = 'Y' + a.z = 'Z' + a.t = A() + a.t.u = A() + a.t.u.v = 'V' + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + f = attrgetter('x') + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + # multiple gets + f = attrgetter('x', 'y', 'z') + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + # recursive gets + f = attrgetter('t.u.v') + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + + def test_itemgetter(self): + itemgetter = self.module.itemgetter + a = 'ABCDE' + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + f = itemgetter(2) + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + # multiple gets + f = itemgetter(2, 0, 4) + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + + def test_methodcaller(self): + methodcaller = self.module.methodcaller + class A: + def foo(self, *args, **kwds): + return args[0] + args[1] + def bar(self, f=42): + return f + def baz(*args, **kwds): + return kwds['name'], kwds['self'] + a = A() + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + f = methodcaller('bar') + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + # positional args + f = methodcaller('foo', 1, 2) + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + # keyword args + f = methodcaller('bar', f=5) + f2 = self.copy(f, proto) + self.assertEqual(repr(f2), repr(f)) + self.assertEqual(f2(a), f(a)) + f = methodcaller('baz', self='eggs', name='spam') + f2 = self.copy(f, proto) + # Can't test repr consistently with multiple keyword args + self.assertEqual(f2(a), f(a)) + +class PyPyOperatorPickleTestCase(OperatorPickleTestCase, unittest.TestCase): + module = py_operator + module2 = py_operator + + at unittest.skipUnless(c_operator, 'requires _operator') +class PyCOperatorPickleTestCase(OperatorPickleTestCase, unittest.TestCase): + module = py_operator + module2 = c_operator + + at unittest.skipUnless(c_operator, 'requires _operator') +class CPyOperatorPickleTestCase(OperatorPickleTestCase, unittest.TestCase): + module = c_operator + module2 = py_operator + + at unittest.skipUnless(c_operator, 'requires _operator') +class CCOperatorPickleTestCase(OperatorPickleTestCase, unittest.TestCase): + module = c_operator + module2 = c_operator + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,10 @@ Library ------- +- Issue #22955: attrgetter, itemgetter and methodcaller objects in the operator + module now support pickling. Added readable and evaluable repr for these + objects. Based on patch by Josh Rosenberg. + - Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not diff --git a/Modules/_operator.c b/Modules/_operator.c --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -485,6 +485,41 @@ return result; } +static PyObject * +itemgetter_repr(itemgetterobject *ig) +{ + PyObject *repr; + const char *reprfmt; + + int status = Py_ReprEnter((PyObject *)ig); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(ig)->tp_name); + } + + reprfmt = ig->nitems == 1 ? "%s(%R)" : "%s%R"; + repr = PyUnicode_FromFormat(reprfmt, Py_TYPE(ig)->tp_name, ig->item); + Py_ReprLeave((PyObject *)ig); + return repr; +} + +static PyObject * +itemgetter_reduce(itemgetterobject *ig) +{ + if (ig->nitems == 1) + return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item); + return PyTuple_Pack(2, Py_TYPE(ig), ig->item); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling"); + +static PyMethodDef itemgetter_methods[] = { + {"__reduce__", (PyCFunction)itemgetter_reduce, METH_NOARGS, + reduce_doc}, + {NULL} +}; + PyDoc_STRVAR(itemgetter_doc, "itemgetter(item, ...) --> itemgetter object\n\ \n\ @@ -503,7 +538,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)itemgetter_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -521,7 +556,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + itemgetter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -737,6 +772,91 @@ return result; } +static PyObject * +dotjoinattr(PyObject *attr, PyObject **attrsep) +{ + if (PyTuple_CheckExact(attr)) { + if (*attrsep == NULL) { + *attrsep = PyUnicode_FromString("."); + if (*attrsep == NULL) + return NULL; + } + return PyUnicode_Join(*attrsep, attr); + } else { + Py_INCREF(attr); + return attr; + } +} + +static PyObject * +attrgetter_args(attrgetterobject *ag) +{ + Py_ssize_t i; + PyObject *attrsep = NULL; + PyObject *attrstrings = PyTuple_New(ag->nattrs); + if (attrstrings == NULL) + return NULL; + + for (i = 0; i < ag->nattrs; ++i) { + PyObject *attr = PyTuple_GET_ITEM(ag->attr, i); + PyObject *attrstr = dotjoinattr(attr, &attrsep); + if (attrstr == NULL) { + Py_XDECREF(attrsep); + Py_DECREF(attrstrings); + return NULL; + } + PyTuple_SET_ITEM(attrstrings, i, attrstr); + } + Py_XDECREF(attrsep); + return attrstrings; +} + +static PyObject * +attrgetter_repr(attrgetterobject *ag) +{ + PyObject *repr = NULL; + int status = Py_ReprEnter((PyObject *)ag); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(ag)->tp_name); + } + + if (ag->nattrs == 1) { + PyObject *attrsep = NULL; + PyObject *attr = dotjoinattr(PyTuple_GET_ITEM(ag->attr, 0), &attrsep); + if (attr != NULL) + repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(ag)->tp_name, attr); + Py_XDECREF(attrsep); + } + else { + PyObject *attrstrings = attrgetter_args(ag); + if (attrstrings != NULL) { + repr = PyUnicode_FromFormat("%s%R", + Py_TYPE(ag)->tp_name, attrstrings); + Py_DECREF(attrstrings); + } + } + Py_ReprLeave((PyObject *)ag); + return repr; +} + +static PyObject * +attrgetter_reduce(attrgetterobject *ag) +{ + PyObject *attrstrings = attrgetter_args(ag); + if (attrstrings == NULL) + return NULL; + + return Py_BuildValue("ON", Py_TYPE(ag), attrstrings); +} + +static PyMethodDef attrgetter_methods[] = { + {"__reduce__", (PyCFunction)attrgetter_reduce, METH_NOARGS, + reduce_doc}, + {NULL} +}; + PyDoc_STRVAR(attrgetter_doc, "attrgetter(attr, ...) --> attrgetter object\n\ \n\ @@ -757,7 +877,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)attrgetter_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -775,7 +895,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + attrgetter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -813,6 +933,13 @@ return NULL; } + name = PyTuple_GET_ITEM(args, 0); + if (!PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, + "method name must be a string"); + return NULL; + } + /* create methodcallerobject structure */ mc = PyObject_GC_New(methodcallerobject, &methodcaller_type); if (mc == NULL) @@ -825,8 +952,8 @@ } mc->args = newargs; - name = PyTuple_GET_ITEM(args, 0); Py_INCREF(name); + PyUnicode_InternInPlace(&name); mc->name = name; Py_XINCREF(kwds); @@ -869,6 +996,142 @@ return result; } +static PyObject * +methodcaller_repr(methodcallerobject *mc) +{ + PyObject *argreprs, *repr = NULL, *sep, *joinedargreprs; + Py_ssize_t numtotalargs, numposargs, numkwdargs, i; + int status = Py_ReprEnter((PyObject *)mc); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(mc)->tp_name); + } + + if (mc->kwds != NULL) { + numkwdargs = PyDict_Size(mc->kwds); + if (numkwdargs < 0) { + Py_ReprLeave((PyObject *)mc); + return NULL; + } + } else { + numkwdargs = 0; + } + + numposargs = PyTuple_GET_SIZE(mc->args); + numtotalargs = numposargs + numkwdargs; + + if (numtotalargs == 0) { + repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(mc)->tp_name, mc->name); + Py_ReprLeave((PyObject *)mc); + return repr; + } + + argreprs = PyTuple_New(numtotalargs); + if (argreprs == NULL) { + Py_ReprLeave((PyObject *)mc); + return NULL; + } + + for (i = 0; i < numposargs; ++i) { + PyObject *onerepr = PyObject_Repr(PyTuple_GET_ITEM(mc->args, i)); + if (onerepr == NULL) + goto done; + PyTuple_SET_ITEM(argreprs, i, onerepr); + } + + if (numkwdargs != 0) { + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(mc->kwds, &pos, &key, &value)) { + PyObject *onerepr = PyUnicode_FromFormat("%U=%R", key, value); + if (onerepr == NULL) + goto done; + if (i >= numtotalargs) { + i = -1; + break; + } + PyTuple_SET_ITEM(argreprs, i, onerepr); + ++i; + } + if (i != numtotalargs) { + PyErr_SetString(PyExc_RuntimeError, + "keywords dict changed size during iteration"); + goto done; + } + } + + sep = PyUnicode_FromString(", "); + if (sep == NULL) + goto done; + + joinedargreprs = PyUnicode_Join(sep, argreprs); + Py_DECREF(sep); + if (joinedargreprs == NULL) + goto done; + + repr = PyUnicode_FromFormat("%s(%R, %U)", Py_TYPE(mc)->tp_name, + mc->name, joinedargreprs); + Py_DECREF(joinedargreprs); + +done: + Py_DECREF(argreprs); + Py_ReprLeave((PyObject *)mc); + return repr; +} + +static PyObject * +methodcaller_reduce(methodcallerobject *mc) +{ + PyObject *newargs; + if (!mc->kwds || PyDict_Size(mc->kwds) == 0) { + Py_ssize_t i; + Py_ssize_t callargcount = PyTuple_GET_SIZE(mc->args); + newargs = PyTuple_New(1 + callargcount); + if (newargs == NULL) + return NULL; + Py_INCREF(mc->name); + PyTuple_SET_ITEM(newargs, 0, mc->name); + for (i = 0; i < callargcount; ++i) { + PyObject *arg = PyTuple_GET_ITEM(mc->args, i); + Py_INCREF(arg); + PyTuple_SET_ITEM(newargs, i + 1, arg); + } + return Py_BuildValue("ON", Py_TYPE(mc), newargs); + } + else { + PyObject *functools; + PyObject *partial; + PyObject *constructor; + _Py_IDENTIFIER(partial); + functools = PyImport_ImportModule("functools"); + if (!functools) + return NULL; + partial = _PyObject_GetAttrId(functools, &PyId_partial); + Py_DECREF(functools); + if (!partial) + return NULL; + newargs = PyTuple_New(2); + if (newargs == NULL) { + Py_DECREF(partial); + return NULL; + } + Py_INCREF(Py_TYPE(mc)); + PyTuple_SET_ITEM(newargs, 0, (PyObject *)Py_TYPE(mc)); + Py_INCREF(mc->name); + PyTuple_SET_ITEM(newargs, 1, mc->name); + constructor = PyObject_Call(partial, newargs, mc->kwds); + Py_DECREF(newargs); + Py_DECREF(partial); + return Py_BuildValue("NO", constructor, mc->args); + } +} + +static PyMethodDef methodcaller_methods[] = { + {"__reduce__", (PyCFunction)methodcaller_reduce, METH_NOARGS, + reduce_doc}, + {NULL} +}; PyDoc_STRVAR(methodcaller_doc, "methodcaller(name, ...) --> methodcaller object\n\ \n\ @@ -888,7 +1151,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)methodcaller_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -906,7 +1169,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + methodcaller_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 17:39:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 15:39:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324134=3A_Use_assertRaises=28=29_in_context_mana?= =?utf-8?q?ger_form_in_test=5Fslice_to?= Message-ID: <20150520153905.4227.9409@psf.io> https://hg.python.org/cpython/rev/36c4f8af99da changeset: 96174:36c4f8af99da parent: 96171:435bc22f39e3 parent: 96173:3a1ee0b5a096 user: Serhiy Storchaka date: Wed May 20 18:38:39 2015 +0300 summary: Issue #24134: Use assertRaises() in context manager form in test_slice to avoid passing the test accidently because slice.__hash__ is None. files: Lib/test/test_slice.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py --- a/Lib/test/test_slice.py +++ b/Lib/test/test_slice.py @@ -79,7 +79,8 @@ def test_hash(self): # Verify clearing of SF bug #800796 self.assertRaises(TypeError, hash, slice(5)) - self.assertRaises(TypeError, slice(5).__hash__) + with self.assertRaises(TypeError): + slice(5).__hash__() def test_cmp(self): s1 = slice(1, 2, 3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 17:39:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 15:39:10 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTM0?= =?utf-8?q?=3A_Use_assertRaises=28=29_in_context_manager_form_in_test=5Fsl?= =?utf-8?q?ice_to?= Message-ID: <20150520153905.125548.82046@psf.io> https://hg.python.org/cpython/rev/3a1ee0b5a096 changeset: 96173:3a1ee0b5a096 branch: 3.4 parent: 96169:f10ba5313fbb user: Serhiy Storchaka date: Wed May 20 18:37:37 2015 +0300 summary: Issue #24134: Use assertRaises() in context manager form in test_slice to avoid passing the test accidently because slice.__hash__ is None. files: Lib/test/test_slice.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py --- a/Lib/test/test_slice.py +++ b/Lib/test/test_slice.py @@ -80,7 +80,8 @@ def test_hash(self): # Verify clearing of SF bug #800796 self.assertRaises(TypeError, hash, slice(5)) - self.assertRaises(TypeError, slice(5).__hash__) + with self.assertRaises(TypeError): + slice(5).__hash__() def test_cmp(self): s1 = slice(1, 2, 3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 17:39:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 15:39:10 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTM0?= =?utf-8?q?=3A_Use_assertRaises=28=29_in_context_manager_form_in_test=5Fsl?= =?utf-8?q?ice_to?= Message-ID: <20150520153905.125530.28276@psf.io> https://hg.python.org/cpython/rev/cbe28273fd8d changeset: 96172:cbe28273fd8d branch: 2.7 parent: 96168:56e1d24806b3 user: Serhiy Storchaka date: Wed May 20 18:37:37 2015 +0300 summary: Issue #24134: Use assertRaises() in context manager form in test_slice to avoid passing the test accidently because slice.__hash__ is None. files: Lib/test/test_slice.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py --- a/Lib/test/test_slice.py +++ b/Lib/test/test_slice.py @@ -18,7 +18,8 @@ def test_hash(self): # Verify clearing of SF bug #800796 self.assertRaises(TypeError, hash, slice(5)) - self.assertRaises(TypeError, slice(5).__hash__) + with self.assertRaises(TypeError): + slice(5).__hash__() def test_cmp(self): s1 = slice(1, 2, 3) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 18:31:09 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 20 May 2015 16:31:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_PCBuild=2Esln_to_o?= =?utf-8?q?pen_with_VS_2015_by_default=2E?= Message-ID: <20150520163102.44671.88008@psf.io> https://hg.python.org/cpython/rev/b9f436efe48c changeset: 96175:b9f436efe48c user: Steve Dower date: Wed May 20 09:30:42 2015 -0700 summary: Updates PCBuild.sln to open with VS 2015 by default. files: PCbuild/pcbuild.sln | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.22823.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}" ProjectSection(SolutionItems) = preProject -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 18:38:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 16:38:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQyMTU6?= =?utf-8?q?_Added_tests_for_more_builtin_types_in_test=5Fpprint=2E?= Message-ID: <20150520163828.10812.27299@psf.io> https://hg.python.org/cpython/rev/2c074a8dd084 changeset: 96176:2c074a8dd084 branch: 3.4 parent: 96173:3a1ee0b5a096 user: Serhiy Storchaka date: Wed May 20 19:37:10 2015 +0300 summary: Issue 24215: Added tests for more builtin types in test_pprint. Made test_pprint and test_trace discoverable. files: Lib/test/test_pprint.py | 17 ++++++++--------- Lib/test/test_trace.py | 12 ++++-------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -58,7 +58,8 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", + bytearray(b"ghi"), True, False, None, ..., self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -128,21 +129,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", + for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ..., ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -597,9 +600,5 @@ self, object, context, maxlevels, level) -def test_main(): - test.support.run_unittest(QueryTestCase) - - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -1,8 +1,7 @@ import os import io import sys -from test.support import (run_unittest, TESTFN, rmtree, unlink, - captured_stdout) +from test.support import TESTFN, rmtree, unlink, captured_stdout import unittest import trace @@ -297,7 +296,8 @@ unlink(TESTFN) def _coverage(self, tracer, - cmd='from test import test_pprint; test_pprint.test_main()'): + cmd='import test.support, test.test_pprint;' + 'test.support.run_unittest(test.test_pprint.QueryTestCase)'): tracer.run(cmd) r = tracer.results() r.write_results(show_missing=True, summary=True, coverdir=TESTFN) @@ -407,9 +407,5 @@ trace.find_executable_linenos(fd.name) -def test_main(): - run_unittest(__name__) - - if __name__ == '__main__': - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 18:38:29 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 16:38:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_24215=3A_Added_tests_for_more_builtin_types_in_tes?= =?utf-8?b?dF9wcHJpbnQu?= Message-ID: <20150520163829.26830.9834@psf.io> https://hg.python.org/cpython/rev/da711bdcc1bf changeset: 96177:da711bdcc1bf parent: 96175:b9f436efe48c parent: 96176:2c074a8dd084 user: Serhiy Storchaka date: Wed May 20 19:38:05 2015 +0300 summary: Issue 24215: Added tests for more builtin types in test_pprint. Made test_pprint and test_trace discoverable. files: Lib/test/test_pprint.py | 17 ++++++++--------- Lib/test/test_trace.py | 12 ++++-------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -91,7 +91,8 @@ def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() - for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, "yaddayadda", + for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, b"def", + bytearray(b"ghi"), True, False, None, ..., self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -161,21 +162,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0, 0+0j, 0.0, "", b"", + for simple in (0, 0, 0+0j, 0.0, "", b"", bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6, -6-6j, -1.5, "x", b"x", (3,), [3], {3: 6}, + -6, -6, -6-6j, -1.5, "x", b"x", bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ..., ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) @@ -1005,9 +1008,5 @@ self, object, context, maxlevels, level) -def test_main(): - test.support.run_unittest(QueryTestCase) - - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -1,8 +1,7 @@ import os import io import sys -from test.support import (run_unittest, TESTFN, rmtree, unlink, - captured_stdout) +from test.support import TESTFN, rmtree, unlink, captured_stdout import unittest import trace @@ -301,7 +300,8 @@ unlink(TESTFN) def _coverage(self, tracer, - cmd='from test import test_pprint; test_pprint.test_main()'): + cmd='import test.support, test.test_pprint;' + 'test.support.run_unittest(test.test_pprint.QueryTestCase)'): tracer.run(cmd) r = tracer.results() r.write_results(show_missing=True, summary=True, coverdir=TESTFN) @@ -411,9 +411,5 @@ trace.find_executable_linenos(fd.name) -def test_main(): - run_unittest(__name__) - - if __name__ == '__main__': - test_main() + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 20:30:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 20 May 2015 18:30:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_20691=3A_Add_follow?= =?utf-8?q?=5Fwrapped_arg_to_inspect=2Esignature/from=5Fcallable=2E?= Message-ID: <20150520183040.39263.10365@psf.io> https://hg.python.org/cpython/rev/0c298f1ee3f6 changeset: 96178:0c298f1ee3f6 user: Yury Selivanov date: Wed May 20 14:30:08 2015 -0400 summary: Issue 20691: Add follow_wrapped arg to inspect.signature/from_callable. files: Doc/library/inspect.rst | 14 ++++++++++---- Doc/whatsnew/3.5.rst | 3 +++ Lib/inspect.py | 9 +++++---- Lib/test/test_inspect.py | 16 ++++++++++++++-- Misc/NEWS | 4 ++++ 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -431,7 +431,7 @@ return annotation. To retrieve a Signature object, use the :func:`signature` function. -.. function:: signature(callable) +.. function:: signature(callable, \*, follow_wrapped=True) Return a :class:`Signature` object for the given ``callable``:: @@ -456,6 +456,11 @@ Raises :exc:`ValueError` if no signature can be provided, and :exc:`TypeError` if that type of object is not supported. + .. versionadded:: 3.5 + ``follow_wrapped`` parameter. Pass ``False`` to get a signature of + ``callable`` specifically (``callable.__wrapped__`` will not be used to + unwrap decorated callables.) + .. note:: Some callables may not be introspectable in certain implementations of @@ -528,12 +533,13 @@ >>> str(new_sig) "(a, b) -> 'new return anno'" - .. classmethod:: Signature.from_callable(obj) + .. classmethod:: Signature.from_callable(obj, \*, follow_wrapped=True) Return a :class:`Signature` (or its subclass) object for a given callable - ``obj``. This method simplifies subclassing of :class:`Signature`: + ``obj``. Pass ``follow_wrapped=False`` to get a signature of ``obj`` + without unwrapping its ``__wrapped__`` chain. - :: + This method simplifies subclassing of :class:`Signature`:: class MySignature(Signature): pass diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -430,6 +430,9 @@ subclassing of :class:`~inspect.Signature` easier. (Contributed by Yury Selivanov and Eric Snow in :issue:`17373`.) +* New argument ``follow_wrapped`` for :func:`inspect.signature`. + (Contributed by Yury Selivanov in :issue:`20691`.) + ipaddress --------- diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2664,9 +2664,10 @@ return _signature_from_builtin(cls, func) @classmethod - def from_callable(cls, obj): + def from_callable(cls, obj, *, follow_wrapped=True): """Constructs Signature for the given callable object.""" - return _signature_from_callable(obj, sigcls=cls) + return _signature_from_callable(obj, sigcls=cls, + follow_wrapper_chains=follow_wrapped) @property def parameters(self): @@ -2915,9 +2916,9 @@ return rendered -def signature(obj): +def signature(obj, *, follow_wrapped=True): """Get a signature object for the passed callable.""" - return Signature.from_callable(obj) + return Signature.from_callable(obj, follow_wrapped=follow_wrapped) def _main(): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1735,8 +1735,8 @@ class TestSignatureObject(unittest.TestCase): @staticmethod - def signature(func): - sig = inspect.signature(func) + def signature(func, **kw): + sig = inspect.signature(func, **kw) return (tuple((param.name, (... if param.default is param.empty else param.default), (... if param.annotation is param.empty @@ -1956,6 +1956,11 @@ self.assertEqual(inspect.signature(func), inspect.signature(decorated_func)) + def wrapper_like(*args, **kwargs) -> int: pass + self.assertEqual(inspect.signature(decorated_func, + follow_wrapped=False), + inspect.signature(wrapper_like)) + @cpython_only def test_signature_on_builtins_no_signature(self): import _testcapi @@ -2384,6 +2389,13 @@ ('b', ..., ..., "positional_or_keyword")), ...)) + self.assertEqual(self.signature(Foo.bar, follow_wrapped=False), + ((('args', ..., ..., "var_positional"), + ('kwargs', ..., ..., "var_keyword")), + ...)) # functools.wraps will copy __annotations__ + # from "func" to "wrapper", hence no + # return_annotation + # Test that we handle method wrappers correctly def decorator(func): @functools.wraps(func) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -176,6 +176,10 @@ - Issue 24190: Implement inspect.BoundArgument.apply_defaults() method. Contributed by Yury Selivanov. +- Issue 20691: Add 'follow_wrapped' argument to + inspect.Signature.from_callable() and inspect.signature(). + Contributed by Yury Selivanov. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 20:44:17 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 20 May 2015 18:44:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=2ESignature=3A_Fac?= =?utf-8?q?tor_out_Signature=2Efrom=5Ffunction_to_a_private_helper?= Message-ID: <20150520184417.10810.89375@psf.io> https://hg.python.org/cpython/rev/52b05cedb7c3 changeset: 96179:52b05cedb7c3 user: Yury Selivanov date: Wed May 20 14:38:50 2015 -0400 summary: inspect.Signature: Factor out Signature.from_function to a private helper files: Lib/inspect.py | 161 +++++++++++++++++++----------------- 1 files changed, 83 insertions(+), 78 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2017,6 +2017,87 @@ return _signature_fromstr(cls, func, s, skip_bound_arg) +def _signature_from_function(cls, func): + """Private helper: constructs Signature for the given python function.""" + + is_duck_function = False + if not isfunction(func): + if _signature_is_functionlike(func): + is_duck_function = True + else: + # If it's not a pure Python function, and not a duck type + # of pure function: + raise TypeError('{!r} is not a Python function'.format(func)) + + Parameter = cls._parameter_cls + + # Parameter information. + func_code = func.__code__ + pos_count = func_code.co_argcount + arg_names = func_code.co_varnames + positional = tuple(arg_names[:pos_count]) + keyword_only_count = func_code.co_kwonlyargcount + keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)] + annotations = func.__annotations__ + defaults = func.__defaults__ + kwdefaults = func.__kwdefaults__ + + if defaults: + pos_default_count = len(defaults) + else: + pos_default_count = 0 + + parameters = [] + + # Non-keyword-only parameters w/o defaults. + non_default_count = pos_count - pos_default_count + for name in positional[:non_default_count]: + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_POSITIONAL_OR_KEYWORD)) + + # ... w/ defaults. + for offset, name in enumerate(positional[non_default_count:]): + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_POSITIONAL_OR_KEYWORD, + default=defaults[offset])) + + # *args + if func_code.co_flags & CO_VARARGS: + name = arg_names[pos_count + keyword_only_count] + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_VAR_POSITIONAL)) + + # Keyword-only parameters. + for name in keyword_only: + default = _empty + if kwdefaults is not None: + default = kwdefaults.get(name, _empty) + + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_KEYWORD_ONLY, + default=default)) + # **kwargs + if func_code.co_flags & CO_VARKEYWORDS: + index = pos_count + keyword_only_count + if func_code.co_flags & CO_VARARGS: + index += 1 + + name = arg_names[index] + annotation = annotations.get(name, _empty) + parameters.append(Parameter(name, annotation=annotation, + kind=_VAR_KEYWORD)) + + # Is 'func' is a pure Python function - don't validate the + # parameters list (for correct order and defaults), it should be OK. + return cls(parameters, + return_annotation=annotations.get('return', _empty), + __validate_parameters__=is_duck_function) + + def _signature_from_callable(obj, *, follow_wrapper_chains=True, skip_bound_arg=True, @@ -2088,7 +2169,7 @@ if isfunction(obj) or _signature_is_functionlike(obj): # If it's a pure Python function, or an object that is duck type # of a Python function (Cython functions, for instance), then: - return sigcls.from_function(obj) + return _signature_from_function(sigcls, obj) if _signature_is_builtin(obj): return _signature_from_builtin(sigcls, obj, @@ -2580,83 +2661,7 @@ @classmethod def from_function(cls, func): """Constructs Signature for the given python function.""" - - is_duck_function = False - if not isfunction(func): - if _signature_is_functionlike(func): - is_duck_function = True - else: - # If it's not a pure Python function, and not a duck type - # of pure function: - raise TypeError('{!r} is not a Python function'.format(func)) - - Parameter = cls._parameter_cls - - # Parameter information. - func_code = func.__code__ - pos_count = func_code.co_argcount - arg_names = func_code.co_varnames - positional = tuple(arg_names[:pos_count]) - keyword_only_count = func_code.co_kwonlyargcount - keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)] - annotations = func.__annotations__ - defaults = func.__defaults__ - kwdefaults = func.__kwdefaults__ - - if defaults: - pos_default_count = len(defaults) - else: - pos_default_count = 0 - - parameters = [] - - # Non-keyword-only parameters w/o defaults. - non_default_count = pos_count - pos_default_count - for name in positional[:non_default_count]: - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_POSITIONAL_OR_KEYWORD)) - - # ... w/ defaults. - for offset, name in enumerate(positional[non_default_count:]): - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_POSITIONAL_OR_KEYWORD, - default=defaults[offset])) - - # *args - if func_code.co_flags & CO_VARARGS: - name = arg_names[pos_count + keyword_only_count] - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_VAR_POSITIONAL)) - - # Keyword-only parameters. - for name in keyword_only: - default = _empty - if kwdefaults is not None: - default = kwdefaults.get(name, _empty) - - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_KEYWORD_ONLY, - default=default)) - # **kwargs - if func_code.co_flags & CO_VARKEYWORDS: - index = pos_count + keyword_only_count - if func_code.co_flags & CO_VARARGS: - index += 1 - - name = arg_names[index] - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_VAR_KEYWORD)) - - # Is 'func' is a pure Python function - don't validate the - # parameters list (for correct order and defaults), it should be OK. - return cls(parameters, - return_annotation=annotations.get('return', _empty), - __validate_parameters__=is_duck_function) + return _signature_from_function(cls, func) @classmethod def from_builtin(cls, func): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 21:03:17 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 20 May 2015 19:03:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322955=3A_Fixed_te?= =?utf-8?q?st=5Foperator=2E_It_left_Python_implementation_in?= Message-ID: <20150520190307.44693.99900@psf.io> https://hg.python.org/cpython/rev/c93e5ba1cc20 changeset: 96180:c93e5ba1cc20 user: Serhiy Storchaka date: Wed May 20 22:02:43 2015 +0300 summary: Issue #22955: Fixed test_operator. It left Python implementation in sys.modules and broke test_ipaddress. files: Lib/test/test_operator.py | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -37,9 +37,6 @@ class OperatorTestCase: - def setUp(self): - sys.modules['operator'] = self.module - def test_lt(self): operator = self.module self.assertRaises(TypeError, operator.lt) @@ -507,7 +504,6 @@ def test_attrgetter(self): attrgetter = self.module.attrgetter - attrgetter = self.module.attrgetter class A: pass a = A() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 21:52:20 2015 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 20 May 2015 19:52:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=239858=3A_Add_missi?= =?utf-8?q?ng_method_stubs_to_=5Fio=2ERawIOBase=2E__Patch_by_Laura?= Message-ID: <20150520195220.26828.93704@psf.io> https://hg.python.org/cpython/rev/962b42d67b9e changeset: 96181:962b42d67b9e user: Antoine Pitrou date: Wed May 20 21:50:59 2015 +0200 summary: Issue #9858: Add missing method stubs to _io.RawIOBase. Patch by Laura Rupprecht. files: Lib/test/test_io.py | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_io/iobase.c | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -722,10 +722,10 @@ @support.cpython_only class APIMismatchTest(unittest.TestCase): - @unittest.expectedFailure # Test to be fixed by issue9858. def test_RawIOBase_io_in_pyio_match(self): """Test that pyio RawIOBase class has all c RawIOBase methods""" - mismatch = support.detect_api_mismatch(pyio.RawIOBase, io.RawIOBase) + mismatch = support.detect_api_mismatch(pyio.RawIOBase, io.RawIOBase, + ignore=('__weakref__',)) self.assertEqual(mismatch, set(), msg='Python RawIOBase does not have all C RawIOBase methods') def test_RawIOBase_pyio_in_io_match(self): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1212,6 +1212,7 @@ Audun S. Runde Eran Rundstein Rauli Ruohonen +Laura Rupprecht Jeff Rush Sam Rushing Mark Russell diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,9 @@ Library ------- +- Issue #9858: Add missing method stubs to _io.RawIOBase. Patch by Laura + Rupprecht. + - Issue #22955: attrgetter, itemgetter and methodcaller objects in the operator module now support pickling. Added readable and evaluable repr for these objects. Based on patch by Josh Rosenberg. diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -952,9 +952,25 @@ return result; } +static PyObject * +rawiobase_readinto(PyObject *self, PyObject *args) +{ + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; +} + +static PyObject * +rawiobase_write(PyObject *self, PyObject *args) +{ + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; +} + static PyMethodDef rawiobase_methods[] = { _IO__RAWIOBASE_READ_METHODDEF _IO__RAWIOBASE_READALL_METHODDEF + {"readinto", rawiobase_readinto, METH_VARARGS}, + {"write", rawiobase_write, METH_VARARGS}, {NULL, NULL} }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 20 23:29:46 2015 From: python-checkins at python.org (eric.snow) Date: Wed, 20 May 2015 21:29:46 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Set_the_BDFL-Delegate=2E?= Message-ID: <20150520212944.125544.99371@psf.io> https://hg.python.org/peps/rev/ed3d2450194e changeset: 5867:ed3d2450194e user: Eric Snow date: Wed May 20 15:27:54 2015 -0600 summary: Set the BDFL-Delegate. files: pep-0489.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -5,6 +5,7 @@ Author: Petr Viktorin , Stefan Behnel , Nick Coghlan +BDFL-Delegate: Eric Snow Discussions-To: import-sig at python.org Status: Draft Type: Standards Track -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 21 05:08:11 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 03:08:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24248=3A_Deprecate_i?= =?utf-8?q?nspect=2ESignature=2Efrom=5Ffunction_and_=2Efrom=5Fbuiltin?= Message-ID: <20150521030811.44687.76821@psf.io> https://hg.python.org/cpython/rev/64fba4ea031b changeset: 96182:64fba4ea031b user: Yury Selivanov date: Wed May 20 23:07:02 2015 -0400 summary: Issue 24248: Deprecate inspect.Signature.from_function and .from_builtin files: Doc/whatsnew/3.5.rst | 5 +++++ Lib/inspect.py | 6 ++++++ Lib/test/test_inspect.py | 16 +++------------- Misc/NEWS | 3 +++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -751,6 +751,11 @@ left to a package. (Contributed by Vajrasky Kok and Berker Peksag in :issue:`1322`.) +* Previously undocumented ``from_function`` and ``from_builtin`` methods + of :class:`inspect.Signature` are deprecated. Use new + :meth:`inspect.Signature.from_callable` instead. (Contributed by Yury + Selivanov in :issue:`24248`.) + Deprecated functions and types of the C API ------------------------------------------- diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2661,11 +2661,17 @@ @classmethod def from_function(cls, func): """Constructs Signature for the given python function.""" + + warnings.warn("inspect.Signature.from_function() is deprecated, " + "use Signature.from_callable()", DeprecationWarning) return _signature_from_function(cls, func) @classmethod def from_builtin(cls, func): """Constructs Signature for the given builtin function.""" + + warnings.warn("inspect.Signature.from_builtin() is deprecated, " + "use Signature.from_callable()", DeprecationWarning) return _signature_from_builtin(cls, func) @classmethod diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1971,13 +1971,6 @@ with self.assertRaisesRegex(TypeError, 'is not a callable object'): inspect.signature(42) - with self.assertRaisesRegex(TypeError, 'is not a Python function'): - inspect.Signature.from_function(42) - - def test_signature_from_builtin_errors(self): - with self.assertRaisesRegex(TypeError, 'is not a Python builtin'): - inspect.Signature.from_builtin(42) - def test_signature_from_functionlike_object(self): def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): pass @@ -1998,9 +1991,9 @@ def __call__(self, *args, **kwargs): return self.func(*args, **kwargs) - sig_func = inspect.Signature.from_function(func) - - sig_funclike = inspect.Signature.from_function(funclike(func)) + sig_func = inspect.Signature.from_callable(func) + + sig_funclike = inspect.Signature.from_callable(funclike(func)) self.assertEqual(sig_funclike, sig_func) sig_funclike = inspect.signature(funclike(func)) @@ -2048,9 +2041,6 @@ __defaults__ = func.__defaults__ __kwdefaults__ = func.__kwdefaults__ - with self.assertRaisesRegex(TypeError, 'is not a Python function'): - inspect.Signature.from_function(funclike) - self.assertEqual(str(inspect.signature(funclike)), '(marker)') def test_signature_on_method(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -183,6 +183,9 @@ inspect.Signature.from_callable() and inspect.signature(). Contributed by Yury Selivanov. +- Issue 24248: Deprecate inspect.Signature.from_function() and + inspect.Signature.from_builtin(). + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 05:09:49 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 21 May 2015 03:09:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_improve_wording?= Message-ID: <20150521030949.32307.74365@psf.io> https://hg.python.org/cpython/rev/04cc39ac03b5 changeset: 96183:04cc39ac03b5 user: Benjamin Peterson date: Wed May 20 22:09:43 2015 -0500 summary: improve wording files: Doc/whatsnew/3.5.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -751,8 +751,8 @@ left to a package. (Contributed by Vajrasky Kok and Berker Peksag in :issue:`1322`.) -* Previously undocumented ``from_function`` and ``from_builtin`` methods - of :class:`inspect.Signature` are deprecated. Use new +* The previously undocumented ``from_function`` and ``from_builtin`` methods of + :class:`inspect.Signature` are deprecated. Use new :meth:`inspect.Signature.from_callable` instead. (Contributed by Yury Selivanov in :issue:`24248`.) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu May 21 11:04:26 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 21 May 2015 09:04:26 +0000 Subject: [Python-checkins] Daily reference leaks (04cc39ac03b5): sum=208 Message-ID: <20150521090425.32295.69334@psf.io> results for 04cc39ac03b5 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_operator leaked [45, 45, 45] references, sum=135 test_operator leaked [23, 23, 23] memory blocks, sum=69 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogYJ3ZzW', '--timeout', '7200'] From python-checkins at python.org Thu May 21 13:19:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 11:19:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322955=3A_Fixed_re?= =?utf-8?q?ference_leak_in_attrgetter=2Erepr=28=29=2E?= Message-ID: <20150521111959.26838.92623@psf.io> https://hg.python.org/cpython/rev/2688655e431a changeset: 96184:2688655e431a user: Serhiy Storchaka date: Thu May 21 14:19:20 2015 +0300 summary: Issue #22955: Fixed reference leak in attrgetter.repr(). files: Modules/_operator.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Modules/_operator.c b/Modules/_operator.c --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -825,8 +825,10 @@ if (ag->nattrs == 1) { PyObject *attrsep = NULL; PyObject *attr = dotjoinattr(PyTuple_GET_ITEM(ag->attr, 0), &attrsep); - if (attr != NULL) + if (attr != NULL) { repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(ag)->tp_name, attr); + Py_DECREF(attr); + } Py_XDECREF(attrsep); } else { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 14:48:37 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 21 May 2015 12:48:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489_updates_from_Petr_Vik?= =?utf-8?q?torin=2E?= Message-ID: <20150521124837.4251.38940@psf.io> https://hg.python.org/peps/rev/342a331682e5 changeset: 5868:342a331682e5 user: Berker Peksag date: Thu May 21 15:48:38 2015 +0300 summary: PEP 489 updates from Petr Viktorin. - Don't allow execution slots for non-module subclasses - Remove misleading reason for PyModuleDef_Init - Clarify that sys.modules is not checked between execution steps - Add a Backwards Compatibility summary - Heading level fix, Typo fix files: pep-0489.txt | 52 +++++++++++++++++++++++++++++---------- 1 files changed, 38 insertions(+), 14 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -164,11 +164,10 @@ When using multi-phase initialization, the *m_name* field of PyModuleDef will not be used during importing; the module name will be taken from the ModuleSpec. -To prevent crashes when the module is loaded in older versions of Python, -the PyModuleDef object must be initialized using the newly added -PyModuleDef_Init function. This sets the object type (which cannot be done -statically on certain compilers), refcount, and internal bookkeeping data -(m_index). +Before it is returned from PyInit_*, the PyModuleDef object must be initialized +using the newly added PyModuleDef_Init function. This sets the object type +(which cannot be done statically on certain compilers), refcount, and internal +bookkeeping data (m_index). For example, an extension module "example" would be exported as:: static PyModuleDef example_def = {...} @@ -353,7 +352,9 @@ types.ModuleType. Any type can be used, as long as it supports setting and getting attributes, including at least the import-related attributes. However, only ModuleType instances support module-specific functionality -such as per-module state. +such as per-module state and processing of execution slots. +If something other than a ModuleType subclass is returned, no execution slots +may be defined; if any are, a SystemError is raised. Note that when this function is called, the module's entry in sys.modules is not populated yet. Attempting to import the same module again @@ -398,7 +399,7 @@ The execution phase is done on the PyModuleDef associated with the module object. For objects that are not a subclass of PyModule_Type (for which -PyModule_GetDef whoud fail), the execution phase is skipped. +PyModule_GetDef would fail), the execution phase is skipped. Execution slots may be specified multiple times, and are processed in the order they appear in the slots array. @@ -409,7 +410,7 @@ Pre-Execution steps -------------------- +................... Before processing the execution slots, per-module state is allocated for the module. From this point on, per-module state is accessible through @@ -427,14 +428,17 @@ setting the module's initial attributes. The "module" argument receives the module object to initialize. -If PyModuleExec replaces the module's entry in sys.modules, -the new object will be used and returned by importlib machinery. -(This mirrors the behavior of Python modules. Note that implementing -Py_mod_create is usually a better solution for the use cases this serves.) - The function must return ``0`` on success, or, on error, set an exception and return ``-1``. +If PyModuleExec replaces the module's entry in sys.modules, the new object +will be used and returned by importlib machinery after all execution slots +are processed. This is a feature of the import machinery itself. +The slots themselves are all processed using the module returned from the +creation phase; sys.modules is not consulted during the execution phase. +(Note that for extension modules, implementing Py_mod_create is usually +a better solution for using custom module objects.) + Legacy Init ----------- @@ -694,7 +698,7 @@ Summary of API Changes and Additions ------------------------------------- +==================================== New functions: @@ -728,6 +732,26 @@ be replaced by backwards-compatible shims. +Backwards Compatibility +----------------------- + +Existing modules will continue to be source- and binary-compatible with new +versions of Python. +Modules that use multi-phase initialization will not be compatible with +versions of Python that do not implement this PEP. + +The functions ``init_builtin`` and ``load_dynamic`` will be removed from +the ``_imp`` module (but not from the ``imp`` module). + +All changed loaders (``BuiltinImporter`` and ``ExtensionFileLoader``) will +remain backwards-compatible; the ``load_module`` method will be replaced by +a shim. + +Internal functions of Python/import.c and Python/importdl.c will be removed. +(Specifically, these are ``_PyImport_GetDynLoadFunc``, +``_PyImport_GetDynLoadWindows``, and ``_PyImport_LoadDynamicModule``.) + + Possible Future Extensions ========================== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 21 14:58:28 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 21 May 2015 12:58:28 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_Improve_markup=2E?= Message-ID: <20150521125828.26846.5801@psf.io> https://hg.python.org/peps/rev/6b6570f097ee changeset: 5869:6b6570f097ee user: Berker Peksag date: Thu May 21 15:58:29 2015 +0300 summary: PEP 489: Improve markup. files: pep-0489.txt | 202 +++++++++++++++++++------------------- 1 files changed, 100 insertions(+), 102 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -191,138 +191,136 @@ The framework that calls the importers is explained in PEP 451 [#pep-0451-loading]_. -:: +importlib/_bootstrap.py:: - importlib/_bootstrap.py: +class BuiltinImporter: + def create_module(self, spec): + module = _imp.create_builtin(spec) - class BuiltinImporter: - def create_module(self, spec): - module = _imp.create_builtin(spec) + def exec_module(self, module): + _imp.exec_dynamic(module) - def exec_module(self, module): - _imp.exec_dynamic(module) + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) - def load_module(self, name): - # use a backwards compatibility shim - _load_module_shim(self, name) +importlib/_bootstrap_external.py:: - importlib/_bootstrap_external.py: + class ExtensionFileLoader: + def create_module(self, spec): + module = _imp.create_dynamic(spec) - class ExtensionFileLoader: - def create_module(self, spec): - module = _imp.create_dynamic(spec) + def exec_module(self, module): + _imp.exec_dynamic(module) - def exec_module(self, module): - _imp.exec_dynamic(module) + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) - def load_module(self, name): - # use a backwards compatibility shim - _load_module_shim(self, name) +Python/import.c (the _imp module):: - Python/import.c (the _imp module): + def create_dynamic(spec): + name = spec.name + path = spec.origin - def create_dynamic(spec): - name = spec.name - path = spec.origin + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod - # Find an already loaded module that used single-phase init. - # For multi-phase initialization, mod is NULL, so a new module - # is always created. - mod = _PyImport_FindExtensionObject(name, name) - if mod: - return mod + return _PyImport_LoadDynamicModuleWithSpec(spec) - return _PyImport_LoadDynamicModuleWithSpec(spec) + def exec_dynamic(module): + if not isinstance(module, types.ModuleType): + # non-modules are skipped -- PyModule_GetDef fails on them + return - def exec_dynamic(module): - if not isinstance(module, types.ModuleType): - # non-modules are skipped -- PyModule_GetDef fails on them - return + def = PyModule_GetDef(module) + state = PyModule_GetState(module) + if state is NULL: + PyModule_ExecDef(module, def) - def = PyModule_GetDef(module) - state = PyModule_GetState(module) - if state is NULL: - PyModule_ExecDef(module, def) + def create_builtin(spec): + name = spec.name - def create_builtin(spec): - name = spec.name + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod - # Find an already loaded module that used single-phase init. - # For multi-phase initialization, mod is NULL, so a new module - # is always created. - mod = _PyImport_FindExtensionObject(name, name) - if mod: - return mod + for initname, initfunc in PyImport_Inittab: + if name == initname: + m = initfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) + else: + # fall back to single-phase initialization + module = m + _PyImport_FixupExtensionObject(module, name, name) + return module - for initname, initfunc in PyImport_Inittab: - if name == initname: - m = initfunc() - if isinstance(m, PyModuleDef): - def = m - return PyModule_FromDefAndSpec(def, spec) - else: - # fall back to single-phase initialization - module = m - _PyImport_FixupExtensionObject(module, name, name) - return module +Python/importdl.c:: - Python/importdl.c: +def _PyImport_LoadDynamicModuleWithSpec(spec): + path = spec.origin + package, dot, name = spec.name.rpartition('.') - def _PyImport_LoadDynamicModuleWithSpec(spec): - path = spec.origin - package, dot, name = spec.name.rpartition('.') + # see the "Non-ASCII module names" section for export_hook_name + hook_name = export_hook_name(name) - # see the "Non-ASCII module names" section for export_hook_name - hook_name = export_hook_name(name) + # call platform-specific function for loading exported function + # from shared library + exportfunc = _find_shared_funcptr(hook_name, path) - # call platform-specific function for loading exported function - # from shared library - exportfunc = _find_shared_funcptr(hook_name, path) + m = exportfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) - m = exportfunc() - if isinstance(m, PyModuleDef): - def = m - return PyModule_FromDefAndSpec(def, spec) + module = m - module = m + # fall back to single-phase initialization + .... - # fall back to single-phase initialization - .... +Objects/moduleobject.c:: - Objects/moduleobject.c: +def PyModule_FromDefAndSpec(def, spec): + name = spec.name + create = None + for slot, value in def.m_slots: + if slot == Py_mod_create: + create = value + if create: + m = create(spec, def) + else: + m = PyModule_New(name) - def PyModule_FromDefAndSpec(def, spec): - name = spec.name - create = None - for slot, value in def.m_slots: - if slot == Py_mod_create: - create = value - if create: - m = create(spec, def) - else: - m = PyModule_New(name) + if isinstance(m, types.ModuleType): + m.md_state = None + m.md_def = def - if isinstance(m, types.ModuleType): - m.md_state = None - m.md_def = def + if def.m_methods: + PyModule_AddFunctions(m, def.m_methods) + if def.m_doc: + PyModule_SetDocString(m, def.m_doc) - if def.m_methods: - PyModule_AddFunctions(m, def.m_methods) - if def.m_doc: - PyModule_SetDocString(m, def.m_doc) +def PyModule_ExecDef(module, def): + if isinstance(module, types.module_type): + if module.md_state is NULL: + # allocate a block of zeroed-out memory + module.md_state = _alloc(module.md_size) - def PyModule_ExecDef(module, def): - if isinstance(module, types.module_type): - if module.md_state is NULL: - # allocate a block of zeroed-out memory - module.md_state = _alloc(module.md_size) + if def.m_slots is NULL: + return - if def.m_slots is NULL: - return - - for slot, value in def.m_slots: - if slot == Py_mod_exec: - value(module) + for slot, value in def.m_slots: + if slot == Py_mod_exec: + value(module) Module Creation Phase -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 21 16:10:13 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 21 May 2015 14:10:13 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_Tweak_code_formatt?= =?utf-8?q?ing=2E?= Message-ID: <20150521141013.16310.65329@psf.io> https://hg.python.org/peps/rev/646e34576f7c changeset: 5870:646e34576f7c user: Berker Peksag date: Thu May 21 17:10:14 2015 +0300 summary: PEP 489: Tweak code formatting. files: pep-0489.txt | 210 ++++++++++++++++++++------------------ 1 files changed, 110 insertions(+), 100 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -191,136 +191,146 @@ The framework that calls the importers is explained in PEP 451 [#pep-0451-loading]_. -importlib/_bootstrap.py:: +importlib/_bootstrap.py: -class BuiltinImporter: - def create_module(self, spec): - module = _imp.create_builtin(spec) + :: - def exec_module(self, module): - _imp.exec_dynamic(module) + class BuiltinImporter: + def create_module(self, spec): + module = _imp.create_builtin(spec) - def load_module(self, name): - # use a backwards compatibility shim - _load_module_shim(self, name) + def exec_module(self, module): + _imp.exec_dynamic(module) -importlib/_bootstrap_external.py:: + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) - class ExtensionFileLoader: - def create_module(self, spec): - module = _imp.create_dynamic(spec) +importlib/_bootstrap_external.py: - def exec_module(self, module): - _imp.exec_dynamic(module) + :: - def load_module(self, name): - # use a backwards compatibility shim - _load_module_shim(self, name) + class ExtensionFileLoader: + def create_module(self, spec): + module = _imp.create_dynamic(spec) -Python/import.c (the _imp module):: + def exec_module(self, module): + _imp.exec_dynamic(module) - def create_dynamic(spec): - name = spec.name - path = spec.origin + def load_module(self, name): + # use a backwards compatibility shim + _load_module_shim(self, name) - # Find an already loaded module that used single-phase init. - # For multi-phase initialization, mod is NULL, so a new module - # is always created. - mod = _PyImport_FindExtensionObject(name, name) - if mod: - return mod +Python/import.c (the _imp module): - return _PyImport_LoadDynamicModuleWithSpec(spec) + :: - def exec_dynamic(module): - if not isinstance(module, types.ModuleType): - # non-modules are skipped -- PyModule_GetDef fails on them - return + def create_dynamic(spec): + name = spec.name + path = spec.origin - def = PyModule_GetDef(module) - state = PyModule_GetState(module) - if state is NULL: - PyModule_ExecDef(module, def) + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod - def create_builtin(spec): - name = spec.name + return _PyImport_LoadDynamicModuleWithSpec(spec) - # Find an already loaded module that used single-phase init. - # For multi-phase initialization, mod is NULL, so a new module - # is always created. - mod = _PyImport_FindExtensionObject(name, name) - if mod: - return mod + def exec_dynamic(module): + if not isinstance(module, types.ModuleType): + # non-modules are skipped -- PyModule_GetDef fails on them + return - for initname, initfunc in PyImport_Inittab: - if name == initname: - m = initfunc() - if isinstance(m, PyModuleDef): - def = m - return PyModule_FromDefAndSpec(def, spec) - else: - # fall back to single-phase initialization - module = m - _PyImport_FixupExtensionObject(module, name, name) - return module + def = PyModule_GetDef(module) + state = PyModule_GetState(module) + if state is NULL: + PyModule_ExecDef(module, def) -Python/importdl.c:: + def create_builtin(spec): + name = spec.name -def _PyImport_LoadDynamicModuleWithSpec(spec): - path = spec.origin - package, dot, name = spec.name.rpartition('.') + # Find an already loaded module that used single-phase init. + # For multi-phase initialization, mod is NULL, so a new module + # is always created. + mod = _PyImport_FindExtensionObject(name, name) + if mod: + return mod - # see the "Non-ASCII module names" section for export_hook_name - hook_name = export_hook_name(name) + for initname, initfunc in PyImport_Inittab: + if name == initname: + m = initfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) + else: + # fall back to single-phase initialization + module = m + _PyImport_FixupExtensionObject(module, name, name) + return module - # call platform-specific function for loading exported function - # from shared library - exportfunc = _find_shared_funcptr(hook_name, path) +Python/importdl.c: - m = exportfunc() - if isinstance(m, PyModuleDef): - def = m - return PyModule_FromDefAndSpec(def, spec) + :: - module = m + def _PyImport_LoadDynamicModuleWithSpec(spec): + path = spec.origin + package, dot, name = spec.name.rpartition('.') - # fall back to single-phase initialization - .... + # see the "Non-ASCII module names" section for export_hook_name + hook_name = export_hook_name(name) -Objects/moduleobject.c:: + # call platform-specific function for loading exported function + # from shared library + exportfunc = _find_shared_funcptr(hook_name, path) -def PyModule_FromDefAndSpec(def, spec): - name = spec.name - create = None - for slot, value in def.m_slots: - if slot == Py_mod_create: - create = value - if create: - m = create(spec, def) - else: - m = PyModule_New(name) + m = exportfunc() + if isinstance(m, PyModuleDef): + def = m + return PyModule_FromDefAndSpec(def, spec) - if isinstance(m, types.ModuleType): - m.md_state = None - m.md_def = def + module = m - if def.m_methods: - PyModule_AddFunctions(m, def.m_methods) - if def.m_doc: - PyModule_SetDocString(m, def.m_doc) + # fall back to single-phase initialization + .... -def PyModule_ExecDef(module, def): - if isinstance(module, types.module_type): - if module.md_state is NULL: - # allocate a block of zeroed-out memory - module.md_state = _alloc(module.md_size) +Objects/moduleobject.c: - if def.m_slots is NULL: - return + :: - for slot, value in def.m_slots: - if slot == Py_mod_exec: - value(module) + def PyModule_FromDefAndSpec(def, spec): + name = spec.name + create = None + for slot, value in def.m_slots: + if slot == Py_mod_create: + create = value + if create: + m = create(spec, def) + else: + m = PyModule_New(name) + + if isinstance(m, types.ModuleType): + m.md_state = None + m.md_def = def + + if def.m_methods: + PyModule_AddFunctions(m, def.m_methods) + if def.m_doc: + PyModule_SetDocString(m, def.m_doc) + + def PyModule_ExecDef(module, def): + if isinstance(module, types.module_type): + if module.md_state is NULL: + # allocate a block of zeroed-out memory + module.md_state = _alloc(module.md_size) + + if def.m_slots is NULL: + return + + for slot, value in def.m_slots: + if slot == Py_mod_exec: + value(module) Module Creation Phase -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 21 17:50:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 15:50:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24180=3A_Documentati?= =?utf-8?q?on_for_PEP_492_changes=2E?= Message-ID: <20150521155036.26580.40725@psf.io> https://hg.python.org/cpython/rev/548d5704fcb3 changeset: 96185:548d5704fcb3 user: Yury Selivanov date: Thu May 21 11:50:30 2015 -0400 summary: Issue 24180: Documentation for PEP 492 changes. files: Doc/c-api/typeobj.rst | 65 ++++++++++- Doc/extending/newtypes.rst | 2 +- Doc/glossary.rst | 48 ++++++++ Doc/library/collections.abc.rst | 45 +++++++- Doc/library/exceptions.rst | 8 + Doc/library/inspect.rst | 41 +++++++ Doc/library/types.rst | 14 ++ Doc/reference/compound_stmts.rst | 109 +++++++++++++++++++ Doc/reference/datamodel.rst | 108 ++++++++++++++++++ Doc/reference/expressions.rst | 18 ++- Doc/whatsnew/3.5.rst | 33 +++++- 11 files changed, 483 insertions(+), 8 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -220,9 +220,16 @@ the subtype's :c:member:`~PyTypeObject.tp_setattr` and :c:member:`~PyTypeObject.tp_setattro` are both *NULL*. -.. c:member:: void* PyTypeObject.tp_reserved +.. c:member:: void* PyTypeObject.tp_as_async - Reserved slot, formerly known as tp_compare. + Pointer to an additional structure that contains fields relevant only to + objects which implement :term:`awaitable` and :term:`asynchronous iterator` + protocols at the C-level. See :ref:`async-structs` for details. + + .. versionadded:: 3.5 + + .. note:: + Formerly known as tp_compare and tp_reserved. .. c:member:: reprfunc PyTypeObject.tp_repr @@ -1332,3 +1339,57 @@ :c:func:`PyBuffer_Release` is the interface for the consumer that wraps this function. + + +.. _async-structs: + + +Async Object Structures +======================= + +.. sectionauthor:: Yury Selivanov + + +.. c:type:: PyAsyncMethods + + This structure holds pointers to the functions required to implement + :term:`awaitable` and :term:`asynchronous iterator` objects. + + Here is the structure definition:: + + typedef struct { + getawaitablefunc am_await; + getaiterfunc am_aiter; + aiternextfunc am_anext; + } PyAsyncMethods; + +.. c:member:: getawaitablefunc PyAsyncMethods.am_await + + The signature of this function is:: + + PyObject *am_await(PyObject *self) + + The returned object must be an iterator, i.e. :c:func:`PyIter_Check` must + return ``1`` for it. + + This slot may be set to *NULL* if an object is not an :term:`awaitable`. + +.. c:member:: getaiterfunc PyAsyncMethods.am_aiter + + The signature of this function is:: + + PyObject *am_aiter(PyObject *self) + + Must return an :term:`awaitable` object. See :meth:`__anext__` for details. + + This slot may be set to *NULL* if an object does not implement + asynchronous iteration protocol. + +.. c:member:: aiternextfunc PyAsyncMethods.am_anext + + The signature of this function is:: + + PyObject *am_anext(PyObject *self) + + Must return an :term:`awaitable` object. See :meth:`__anext__` for details. + This slot may be set to *NULL*. diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -80,7 +80,7 @@ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_reserved */ + 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -69,11 +69,42 @@ :ref:`the difference between arguments and parameters `, and :pep:`362`. + asynchronous context manager + An object which controls the environment seen in an + :keyword:`async with` statement by defining :meth:`__aenter__` and + :meth:`__aexit__` methods. Introduced by :pep:`492`. + + .. versionadded:: 3.5 + + asynchronous iterable + An object, that can be used in an :keyword:`async for` statement. + Must return an :term:`awaitable` from its :meth:`__aiter__` method, + which should in turn be resolved in an :term:`asynchronous iterator` + object. Introduced by :pep:`492`. + + .. versionadded:: 3.5 + + asynchronous iterator + An object that implements :meth:`__aiter__` and :meth:`__anext__` + methods, that must return :term:`awaitable` objects. + :keyword:`async for` resolves awaitable returned from asynchronous + iterator's :meth:`__anext__` method until it raises + :exc:`StopAsyncIteration` exception. Introduced by :pep:`492`. + + .. versionadded:: 3.5 + attribute A value associated with an object which is referenced by name using dotted expressions. For example, if an object *o* has an attribute *a* it would be referenced as *o.a*. + awaitable + An object that can be used in an :keyword:`await` expression. Can be + a :term:`coroutine` or an object with an :meth:`__await__` method. + See also :pep:`492`. + + .. versionadded:: 3.5 + BDFL Benevolent Dictator For Life, a.k.a. `Guido van Rossum `_, Python's creator. @@ -146,6 +177,23 @@ statement by defining :meth:`__enter__` and :meth:`__exit__` methods. See :pep:`343`. + coroutine function + A function which returns a :term:`coroutine` object. It is defined + with an :keyword:`async def` keyword, and may contain :keyword:`await`, + :keyword:`async for`, and :keyword:`async with` keywords. Introduced + by :pep:`492`. + + .. versionadded:: 3.5 + + coroutine + Coroutines is a more generalized form of subroutines. Subroutines are + entered at one point and exited at another point. Coroutines, can be + entered, exited, and resumed at many different points. See + :keyword:`await` expressions, and :keyword:`async for` and + :keyword:`async with` statements. See also :pep:`492`. + + .. versionadded:: 3.5 + CPython The canonical implementation of the Python programming language, as distributed on `python.org `_. The term "CPython" diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -33,9 +33,9 @@ .. tabularcolumns:: |l|L|L|L| -========================= ===================== ====================== ==================================================== +========================== ====================== ======================= ==================================================== ABC Inherits from Abstract Methods Mixin Methods -========================= ===================== ====================== ==================================================== +========================== ====================== ======================= ==================================================== :class:`Container` ``__contains__`` :class:`Hashable` ``__hash__`` :class:`Iterable` ``__iter__`` @@ -81,7 +81,11 @@ :class:`KeysView` :class:`MappingView`, ``__contains__``, :class:`Set` ``__iter__`` :class:`ValuesView` :class:`MappingView` ``__contains__``, ``__iter__`` -========================= ===================== ====================== ==================================================== +:class:`Awaitable` ``__await__`` +:class:`Coroutine` ``send``, ``throw`` ``close`` +:class:`AsyncIterable` ``__aiter__`` +:class:`AsyncIterator` :class:`AsyncIterable` ``__anext__`` ``__aiter__`` +========================== ====================== ======================= ==================================================== .. class:: Container @@ -134,6 +138,41 @@ ABCs for mapping, items, keys, and values :term:`views `. +.. class:: Awaitable + + ABC for classes that provide ``__await__`` method. Instances + of such classes can be used in ``await`` expression. + + :term:`coroutine` objects and instances of + :class:`~collections.abc.Coroutine` are too instances of this ABC. + + .. versionadded:: 3.5 + +.. class:: Coroutine + + ABC for coroutine compatible classes that implement a subset of + generator methods defined in :pep:`342`, namely: + :meth:`~generator.send`, :meth:`~generator.throw` and + :meth:`~generator.close` methods. All :class:`Coroutine` instances + are also instances of :class:`Awaitable`. See also the definition + of :term:`coroutine`. + + .. versionadded:: 3.5 + +.. class:: AsyncIterable + + ABC for classes that provide ``__aiter__`` method. See also the + definition of :term:`asynchronous iterable`. + + .. versionadded:: 3.5 + +.. class:: AsyncIterator + + ABC for classes that provide ``__aiter__`` and ``__anext__`` + methods. See also the definition of :term:`asynchronous iterator`. + + .. versionadded:: 3.5 + These ABCs allow us to ask classes or instances if they provide particular functionality, for example:: diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -322,6 +322,14 @@ .. versionchanged:: 3.5 Introduced the RuntimeError transformation. +.. exception:: StopAsyncIteration + + Must be raised by :meth:`__anext__` method of an + :term:`asynchronous iterator` object to stop the iteration. + + .. versionadded:: 3.5 + See also :pep:`492`. + .. exception:: SyntaxError Raised when the parser encounters a syntax error. This may occur in an diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -266,6 +266,47 @@ Return true if the object is a generator. +.. function:: iscoroutinefunction(object) + + Return true if the object is a coroutine function. + + Coroutine functions are defined with an ``async def`` syntax, + or are generators decorated with :func:`types.coroutine` + or :func:`asyncio.coroutine`. + + The function will return false for plain python generator + functions. + + See also :pep:`492`. + + .. versionadded:: 3.5 + + +.. function:: iscoroutine(object) + + Return true if the object is a coroutine. + + Coroutines are results of calls of coroutine functions or + generator functions decorated with :func:`types.coroutine` + or :func:`asyncio.coroutine`. + + The function will return false for plain python generators. + + See also :class:`collections.abc.Coroutine` and :pep:`492`. + + .. versionadded:: 3.5 + + +.. function:: isawaitable(object) + + Return true if the object can be used in :keyword:`await` + expression. + + See also :class:`collections.abc.Awaitable` and :pep:`492`. + + .. versionadded:: 3.5 + + .. function:: istraceback(object) Return true if the object is a traceback. diff --git a/Doc/library/types.rst b/Doc/library/types.rst --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -271,3 +271,17 @@ attributes on the class with the same name (see Enum for an example). .. versionadded:: 3.4 + + +Coroutines Utility Functions +---------------------------- + +.. function:: coroutine(gen_func) + + The function transforms a generator function to a :term:`coroutine function`, + so that it returns a :term:`coroutine` object. + + *gen_func* is modified in-place, hence the function can be used as a + decorator. + + .. versionadded:: 3.5 diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -51,6 +51,9 @@ : | `with_stmt` : | `funcdef` : | `classdef` + : | `async_with_stmt` + : | `async_for_stmt` + : | `async_funcdef` suite: `stmt_list` NEWLINE | NEWLINE INDENT `statement`+ DEDENT statement: `stmt_list` NEWLINE | `compound_stmt` stmt_list: `simple_stmt` (";" `simple_stmt`)* [";"] @@ -660,6 +663,112 @@ :pep:`3129` - Class Decorators +Coroutines +========== + +.. _`async def`: + +Coroutine function definition +----------------------------- + +.. productionlist:: + async_funcdef: "async" `funcdef` + +Execution of Python coroutines can be suspended and resumed at many points +(see :term:`coroutine`.) :keyword:`await` expressions, :keyword:`async for` +and :keyword:`async with` can only be used in their bodies. + +Functions defined with ``async def`` syntax are always coroutine functions, +even if they do not contain ``await`` or ``async`` keywords. + +It is a :exc:`SyntaxError` to use :keyword:`yield` expressions in coroutines. + +.. versionadded:: 3.5 + + +.. _`async for`: + +The :keyword:`async for` statement +---------------------------------- + +.. productionlist:: + async_for_stmt: "async" `for_stmt` + +An :term:`asynchronous iterable` is able to call asynchronous code in its +*iter* implementation, and :term:`asynchronous iterator` can call asynchronous +code in its *next* method. + +The ``async for`` statement allows convenient iteration over asynchronous +iterators. + +The following code:: + + async for TARGET in ITER: + BLOCK + else: + BLOCK2 + +Is semantically equivalent to:: + + iter = (ITER) + iter = await type(iter).__aiter__(iter) + running = True + while running: + try: + TARGET = await type(iter).__anext__(iter) + except StopAsyncIteration: + running = False + else: + BLOCK + else: + BLOCK2 + +See also :meth:`__aiter__` and :meth:`__anext__` for details. + +.. versionadded:: 3.5 + + +.. _`async with`: + +The :keyword:`async with` statement +----------------------------------- + +.. productionlist:: + async_with_stmt: "async" `with_stmt` + +An :term:`asynchronous context manager` is a :term:`context manager` that is +able to suspend execution in its *enter* and *exit* methods. + +The following code:: + + async with EXPR as VAR: + BLOCK + +Is semantically equivalent to:: + + mgr = (EXPR) + aexit = type(mgr).__aexit__ + aenter = type(mgr).__aenter__(mgr) + exc = True + + VAR = await aenter + try: + BLOCK + except: + if not await aexit(mgr, *sys.exc_info()): + raise + else: + await aexit(mgr, None, None, None) + +See also :meth:`__aenter__` and :meth:`__aexit__` for details. + +.. versionadded:: 3.5 + +.. seealso:: + + :pep:`492` - Coroutines with async and await syntax + + .. rubric:: Footnotes .. [#] The exception is propagated to the invocation stack unless diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -616,6 +616,16 @@ exception is raised and the iterator will have reached the end of the set of values to be returned. + Coroutine functions + .. index:: + single: coroutine; function + + A function or method which is defined using :keyword:`async def` is called + a :dfn:`coroutine function`. Such a function, when called, returns a + :term:`coroutine` object. It may contain :keyword:`await` expressions, + as well as :keyword:`async with` and :keyword:`async for` statements. See + also :ref:`coroutines` section. + Built-in functions .. index:: object: built-in function @@ -2254,6 +2264,104 @@ object itself in order to be consistently invoked by the interpreter). +.. _coroutines: + +Coroutines +========== + +.. index:: + single: coroutine + + +Awaitable Objects +----------------- + +An *awaitable* object can be one of the following: + +* A :term:`coroutine` object returned from a :term:`coroutine function`. + +* A :term:`generator` decorated with :func:`types.coroutine` + (or :func:`asyncio.coroutine`) decorator. + +* An object that implements an ``__await__`` method. + +.. method:: object.__await__(self) + + Must return an :term:`iterator`. Should be used to implement + :term:`awaitable` objects. For instance, :class:`asyncio.Future` implements + this method to be compatible with the :keyword:`await` expression. + +.. versionadded:: 3.5 + +.. seealso:: :pep:`492` for additional information about awaitable objects. + + +Asynchronous Iterators +---------------------- + +An *asynchronous iterable* is able to call asynchronous code in its +``__aiter__`` implementation, and an *asynchronous iterator* can call +asynchronous code in its ``__anext__`` method. + +Asynchronous iterators can be used in a :keyword:`async for` statement. + +.. method:: object.__aiter__(self) + + Must return an *awaitable* resulting in an *asynchronous iterator* object. + +.. method:: object.__anext__(self) + + Must return an *awaitable* resulting in a next value of the iterator. Should + raise a :exc:`StopAsyncIteration` error when the iteration is over. + +An example of an asynchronous iterable object:: + + class Reader: + async def readline(self): + ... + + async def __aiter__(self): + return self + + async def __anext__(self): + val = await self.readline() + if val == b'': + raise StopAsyncIteration + return val + +.. versionadded:: 3.5 + + +Asynchronous Context Managers +----------------------------- + +An *asynchronous context manager* is a *context manager* that is able to +suspend execution in its ``__aenter__`` and ``__aexit__`` methods. + +Asynchronous context managers can be used in a :keyword:`async with` statement. + +.. method:: object.__aenter__(self) + + This method is semantically similar to the :meth:`__enter__`, with only + difference that it must return an *awaitable*. + +.. method:: object.__aexit__(self, exc_type, exc_value, traceback) + + This method is semantically similar to the :meth:`__exit__`, with only + difference that it must return an *awaitable*. + +An example of an asynchronous context manager class:: + + class AsyncContextManager: + async def __aenter__(self): + await log('entering context') + + async def __aexit__(self, exc_type, exc, tb): + await log('exiting context') + +.. versionadded:: 3.5 + + .. rubric:: Footnotes .. [#] It *is* possible in some cases to change an object's type, under certain diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -811,6 +811,20 @@ if that method was called. +.. _await: + +Await expression +================ + +Suspend the execution of :term:`coroutine` on an :term:`awaitable` object. +Can only be used inside a :term:`coroutine function`. + +.. productionlist:: + await: ["await"] `primary` + +.. versionadded:: 3.5 + + .. _power: The power operator @@ -820,7 +834,7 @@ less tightly than unary operators on its right. The syntax is: .. productionlist:: - power: `primary` ["**" `u_expr`] + power: `await` ["**" `u_expr`] Thus, in an unparenthesized sequence of power and unary operators, the operators are evaluated from right to left (this does not constrain the evaluation order @@ -1362,6 +1376,8 @@ +-----------------------------------------------+-------------------------------------+ | ``**`` | Exponentiation [#]_ | +-----------------------------------------------+-------------------------------------+ +| ``await`` ``x`` | Await expression | ++-----------------------------------------------+-------------------------------------+ | ``x[index]``, ``x[index:index]``, | Subscription, slicing, | | ``x(arguments...)``, ``x.attribute`` | call, attribute reference | +-----------------------------------------------+-------------------------------------+ diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -121,6 +121,26 @@ PEP written by Carl Meyer +PEP 492 - Coroutines with async and await syntax +------------------------------------------------ + +The PEP added dedicated syntax for declaring :term:`coroutines `, +:keyword:`await` expressions, new asynchronous :keyword:`async for` +and :keyword:`async with` statements. + +Example:: + + async def read_data(db): + async with db.transaction(): + data = await db.fetch('SELECT ...') + +PEP written and implemented by Yury Selivanov. + +.. seealso:: + + :pep:`492` -- Coroutines with async and await syntax + + PEP 461 - Adding formatting to bytes and bytearray -------------------------------------------------- @@ -433,6 +453,10 @@ * New argument ``follow_wrapped`` for :func:`inspect.signature`. (Contributed by Yury Selivanov in :issue:`20691`.) +* New :func:`~inspect.iscoroutine`, :func:`~inspect.iscoroutinefunction`, + and :func:`~inspect.isawaitable` functions. (Contributed by Yury Selivanov + in :issue:`24017`.) + ipaddress --------- @@ -614,6 +638,12 @@ * The :func:`time.monotonic` function is now always available. (Contributed by Victor Stinner in :issue:`22043`.) +types +----- + +* New :func:`~types.coroutine` function. (Contributed by Yury Selivanov + in :issue:`24017`.) + urllib ------ @@ -961,4 +991,5 @@ (:issue:`20204`) * As part of PEP 492 implementation, ``tp_reserved`` slot of - ``PyTypeObject`` was replaced with ``tp_as_async`` slot. + :c:type:`PyTypeObject` was replaced with a + :c:member:`PyTypeObject.tp_as_async` slot. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 18:03:45 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 16:03:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24017=3A_Use_abc=2EC?= =?utf-8?q?oroutine_in_inspect=2Eiscoroutine=28=29_function?= Message-ID: <20150521160345.4241.44863@psf.io> https://hg.python.org/cpython/rev/ff983ee10b3e changeset: 96186:ff983ee10b3e user: Yury Selivanov date: Thu May 21 12:03:21 2015 -0400 summary: Issue 24017: Use abc.Coroutine in inspect.iscoroutine() function files: Lib/inspect.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -212,8 +212,7 @@ def iscoroutine(object): """Return true if the object is a coroutine.""" - return (isinstance(object, types.GeneratorType) and - object.gi_code.co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) + return isinstance(object, collections.abc.Coroutine) def istraceback(object): """Return true if the object is a traceback. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 18:25:48 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 16:25:48 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0478=3A_Mention_PEP_488?= Message-ID: <20150521162541.39257.29258@psf.io> https://hg.python.org/peps/rev/d99e2cdd1a80 changeset: 5871:d99e2cdd1a80 user: Yury Selivanov date: Thu May 21 12:25:38 2015 -0400 summary: pep-0478: Mention PEP 488 files: pep-0478.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -66,6 +66,7 @@ * PEP 486, make the Python Launcher aware of virtual environments * PEP 475, retrying system calls that fail with EINTR * PEP 492, coroutines with async and await syntax +* PEP 488, elimination of PYO files Accepted PEPs: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu May 21 19:16:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:16:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315836=3A_assertRa?= =?utf-8?q?ises=28=29=2C_assertRaisesRegex=28=29=2C_assertWarns=28=29_and?= Message-ID: <20150521171615.44671.69761@psf.io> https://hg.python.org/cpython/rev/84d7ec21cc43 changeset: 96187:84d7ec21cc43 user: Serhiy Storchaka date: Thu May 21 20:15:40 2015 +0300 summary: Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() assertments now check the type of the first argument to prevent possible user error. Based on patch by Daniel Wagner-Hall. files: Lib/test/test_importlib/builtin/test_loader.py | 1 - Lib/unittest/case.py | 13 ++ Lib/unittest/test/test_case.py | 56 ++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 + 5 files changed, 74 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/builtin/test_loader.py b/Lib/test/test_importlib/builtin/test_loader.py --- a/Lib/test/test_importlib/builtin/test_loader.py +++ b/Lib/test/test_importlib/builtin/test_loader.py @@ -97,7 +97,6 @@ method = getattr(self.machinery.BuiltinImporter, meth_name) with self.assertRaises(ImportError) as cm: method(util.BUILTINS.bad_name) - self.assertRaises(util.BUILTINS.bad_name) (Frozen_InspectLoaderTests, diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -119,6 +119,10 @@ test_item.__unittest_expecting_failure__ = True return test_item +def _is_subtype(expected, basetype): + if isinstance(expected, tuple): + return all(_is_subtype(e, basetype) for e in expected) + return isinstance(expected, type) and issubclass(expected, basetype) class _BaseTestCaseContext: @@ -148,6 +152,9 @@ If args is not empty, call a callable passing positional and keyword arguments. """ + if not _is_subtype(self.expected, self._base_type): + raise TypeError('%s() arg 1 must be %s' % + (name, self._base_type_str)) if args and args[0] is None: warnings.warn("callable is None", DeprecationWarning, 3) @@ -172,6 +179,9 @@ class _AssertRaisesContext(_AssertRaisesBaseContext): """A context manager used to implement TestCase.assertRaises* methods.""" + _base_type = BaseException + _base_type_str = 'an exception type or tuple of exception types' + def __enter__(self): return self @@ -206,6 +216,9 @@ class _AssertWarnsContext(_AssertRaisesBaseContext): """A context manager used to implement TestCase.assertWarns* methods.""" + _base_type = Warning + _base_type_str = 'a warning type or tuple of warning types' + def __enter__(self): # The __warningregistry__'s need to be in a pristine state for tests # to work properly. diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -1185,6 +1185,18 @@ with self.assertRaises(ExceptionMock): self.assertRaises(ValueError, Stub) + def testAssertRaisesNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertRaises() + with self.assertRaises(TypeError): + self.assertRaises(1) + with self.assertRaises(TypeError): + self.assertRaises(object) + with self.assertRaises(TypeError): + self.assertRaises((ValueError, 1)) + with self.assertRaises(TypeError): + self.assertRaises((ValueError, object)) + def testAssertRaisesRegex(self): class ExceptionMock(Exception): pass @@ -1258,6 +1270,20 @@ self.assertIsInstance(e, ExceptionMock) self.assertEqual(e.args[0], v) + def testAssertRaisesRegexNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertRaisesRegex() + with self.assertRaises(TypeError): + self.assertRaisesRegex(ValueError) + with self.assertRaises(TypeError): + self.assertRaisesRegex(1, 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex(object, 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex((ValueError, 1), 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex((ValueError, object), 'expect') + def testAssertWarnsCallable(self): def _runtime_warn(): warnings.warn("foo", RuntimeWarning) @@ -1336,6 +1362,20 @@ with self.assertWarns(DeprecationWarning): _runtime_warn() + def testAssertWarnsNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertWarns() + with self.assertRaises(TypeError): + self.assertWarns(1) + with self.assertRaises(TypeError): + self.assertWarns(object) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, 1)) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, object)) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, Exception)) + def testAssertWarnsRegexCallable(self): def _runtime_warn(msg): warnings.warn(msg, RuntimeWarning) @@ -1414,6 +1454,22 @@ with self.assertWarnsRegex(RuntimeWarning, "o+"): _runtime_warn("barz") + def testAssertWarnsRegexNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertWarnsRegex() + with self.assertRaises(TypeError): + self.assertWarnsRegex(UserWarning) + with self.assertRaises(TypeError): + self.assertWarnsRegex(1, 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex(object, 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, 1), 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, object), 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, Exception), 'expect') + @contextlib.contextmanager def assertNoStderr(self): with captured_stderr() as buf: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1472,6 +1472,7 @@ Martijn Vries Sjoerd de Vries Guido Vranken +Daniel Wagner-Hall Niki W. Waibel Wojtek Walczak Charles Waldman diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,10 @@ Library ------- +- Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() assertments now check the type of the first argument + to prevent possible user error. Based on patch by Daniel Wagner-Hall. + - Issue #9858: Add missing method stubs to _io.RawIOBase. Patch by Laura Rupprecht. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:52:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:52:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323985=3A_Fixed_integer_overflow_in_iterator_obj?= =?utf-8?q?ect=2E__Patch_by?= Message-ID: <20150521175225.16312.13315@psf.io> https://hg.python.org/cpython/rev/9f2a1d9d7164 changeset: 96190:9f2a1d9d7164 parent: 96187:84d7ec21cc43 parent: 96189:5b86a1abc8c3 user: Serhiy Storchaka date: Thu May 21 20:51:53 2015 +0300 summary: Issue #23985: Fixed integer overflow in iterator object. Patch by Clement Rouault. files: Lib/test/test_iter.py | 25 +++++++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/iterobject.c | 5 +++++ 3 files changed, 33 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -1,5 +1,6 @@ # Test iterators. +import sys import unittest from test.support import run_unittest, TESTFN, unlink, cpython_only import pickle @@ -48,6 +49,10 @@ else: raise IndexError +class UnlimitedSequenceClass: + def __getitem__(self, i): + return i + # Main test suite class TestCase(unittest.TestCase): @@ -919,6 +924,26 @@ lst.extend(gen()) self.assertEqual(len(lst), 760) + @cpython_only + def test_iter_overflow(self): + # Test for the issue 22939 + it = iter(UnlimitedSequenceClass()) + # Manually set `it_index` to PY_SSIZE_T_MAX-2 without a loop + it.__setstate__(sys.maxsize - 2) + self.assertEqual(next(it), sys.maxsize - 2) + self.assertEqual(next(it), sys.maxsize - 1) + with self.assertRaises(OverflowError): + next(it) + # Check that Overflow error is always raised + with self.assertRaises(OverflowError): + next(it) + + def test_iter_neg_setstate(self): + it = iter(UnlimitedSequenceClass()) + it.__setstate__(-42) + self.assertEqual(next(it), 0) + self.assertEqual(next(it), 1) + def test_main(): run_unittest(TestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23985: Fixed integer overflow in iterator object. Patch by + Clement Rouault. + - Issue #23985: Fix a possible buffer overrun when deleting a slice from the front of a bytearray and then appending some other bytes data. diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -54,6 +54,11 @@ seq = it->it_seq; if (seq == NULL) return NULL; + if (it->it_index == PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, + "iter index too large"); + return NULL; + } result = PySequence_GetItem(seq, it->it_index); if (result != NULL) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:52:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:52:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzOTg1?= =?utf-8?q?=3A_Fixed_integer_overflow_in_iterator_object=2E__Original_patc?= =?utf-8?q?h_by?= Message-ID: <20150521175225.21156.28824@psf.io> https://hg.python.org/cpython/rev/274c1b0a2494 changeset: 96188:274c1b0a2494 branch: 2.7 parent: 96172:cbe28273fd8d user: Serhiy Storchaka date: Thu May 21 20:49:34 2015 +0300 summary: Issue #23985: Fixed integer overflow in iterator object. Original patch by Clement Rouault. files: Misc/ACKS | 1 + Misc/NEWS | 3 +++ Objects/iterobject.c | 5 +++++ 3 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1159,6 +1159,7 @@ Just van Rossum Hugo van Rossum Saskia van Rossum +Clement Rouault Donald Wallace Rouse II Liam Routt Todd Rovito diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23985: Fixed integer overflow in iterator object. Original patch by + Clement Rouault. + - Issue #24102: Fixed exception type checking in standard error handlers. Library diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -54,6 +54,11 @@ seq = it->it_seq; if (seq == NULL) return NULL; + if (it->it_index == LONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "iter index too large"); + return NULL; + } result = PySequence_GetItem(seq, it->it_index); if (result != NULL) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:52:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:52:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTg1?= =?utf-8?q?=3A_Fixed_integer_overflow_in_iterator_object=2E__Patch_by?= Message-ID: <20150521175225.21164.36048@psf.io> https://hg.python.org/cpython/rev/5b86a1abc8c3 changeset: 96189:5b86a1abc8c3 branch: 3.4 parent: 96176:2c074a8dd084 user: Serhiy Storchaka date: Thu May 21 20:50:25 2015 +0300 summary: Issue #23985: Fixed integer overflow in iterator object. Patch by Clement Rouault. files: Lib/test/test_iter.py | 25 +++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Objects/iterobject.c | 5 +++++ 4 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -1,5 +1,6 @@ # Test iterators. +import sys import unittest from test.support import run_unittest, TESTFN, unlink, cpython_only import pickle @@ -48,6 +49,10 @@ else: raise IndexError +class UnlimitedSequenceClass: + def __getitem__(self, i): + return i + # Main test suite class TestCase(unittest.TestCase): @@ -919,6 +924,26 @@ lst.extend(gen()) self.assertEqual(len(lst), 760) + @cpython_only + def test_iter_overflow(self): + # Test for the issue 22939 + it = iter(UnlimitedSequenceClass()) + # Manually set `it_index` to PY_SSIZE_T_MAX-2 without a loop + it.__setstate__(sys.maxsize - 2) + self.assertEqual(next(it), sys.maxsize - 2) + self.assertEqual(next(it), sys.maxsize - 1) + with self.assertRaises(OverflowError): + next(it) + # Check that Overflow error is always raised + with self.assertRaises(OverflowError): + next(it) + + def test_iter_neg_setstate(self): + it = iter(UnlimitedSequenceClass()) + it.__setstate__(-42) + self.assertEqual(next(it), 0) + self.assertEqual(next(it), 1) + def test_main(): run_unittest(TestCase) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1168,6 +1168,7 @@ Just van Rossum Hugo van Rossum Saskia van Rossum +Clement Rouault Donald Wallace Rouse II Liam Routt Todd Rovito diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23985: Fixed integer overflow in iterator object. Patch by + Clement Rouault. + - Issue #23985: Fix a possible buffer overrun when deleting a slice from the front of a bytearray and then appending some other bytes data. diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -54,6 +54,11 @@ seq = it->it_seq; if (seq == NULL) return NULL; + if (it->it_index == PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, + "iter index too large"); + return NULL; + } result = PySequence_GetItem(seq, it->it_index); if (result != NULL) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:55:19 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:55:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_issue_number_for_issue_=2322939=2E?= Message-ID: <20150521175519.16298.2803@psf.io> https://hg.python.org/cpython/rev/f23533fa6afa changeset: 96193:f23533fa6afa parent: 96190:9f2a1d9d7164 parent: 96192:7fa2f4afcf5a user: Serhiy Storchaka date: Thu May 21 20:54:48 2015 +0300 summary: Fixed issue number for issue #22939. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,7 @@ Core and Builtins ----------------- -- Issue #23985: Fixed integer overflow in iterator object. Patch by +- Issue #22939: Fixed integer overflow in iterator object. Patch by Clement Rouault. - Issue #23985: Fix a possible buffer overrun when deleting a slice from -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:55:19 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:55:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_issue_nu?= =?utf-8?q?mber_for_issue_=2322939=2E?= Message-ID: <20150521175519.26854.38490@psf.io> https://hg.python.org/cpython/rev/7fa2f4afcf5a changeset: 96192:7fa2f4afcf5a branch: 3.4 parent: 96189:5b86a1abc8c3 user: Serhiy Storchaka date: Thu May 21 20:54:36 2015 +0300 summary: Fixed issue number for issue #22939. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,7 @@ Core and Builtins ----------------- -- Issue #23985: Fixed integer overflow in iterator object. Patch by +- Issue #22939: Fixed integer overflow in iterator object. Patch by Clement Rouault. - Issue #23985: Fix a possible buffer overrun when deleting a slice from -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 19:55:21 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 21 May 2015 17:55:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_issue_nu?= =?utf-8?q?mber_for_issue_=2322939=2E?= Message-ID: <20150521175519.32297.34818@psf.io> https://hg.python.org/cpython/rev/d6179accca20 changeset: 96191:d6179accca20 branch: 2.7 parent: 96188:274c1b0a2494 user: Serhiy Storchaka date: Thu May 21 20:54:26 2015 +0300 summary: Fixed issue number for issue #22939. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,7 @@ Core and Builtins ----------------- -- Issue #23985: Fixed integer overflow in iterator object. Original patch by +- Issue #22939: Fixed integer overflow in iterator object. Original patch by Clement Rouault. - Issue #24102: Fixed exception type checking in standard error handlers. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 21:46:17 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 19:46:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjM4OTg6?= =?utf-8?q?_Fix_inspect=2Eclassify=5Fclass=5Fattrs=28=29_to_work_with_=5F?= =?utf-8?b?X2VxX18=?= Message-ID: <20150521194616.26848.28594@psf.io> https://hg.python.org/cpython/rev/fb9addfdfc35 changeset: 96194:fb9addfdfc35 branch: 3.4 parent: 96192:7fa2f4afcf5a user: Yury Selivanov date: Thu May 21 15:41:57 2015 -0400 summary: Issue 23898: Fix inspect.classify_class_attrs() to work with __eq__ files: Lib/inspect.py | 6 +++--- Lib/test/test_inspect.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -380,7 +380,7 @@ # first look in the classes for srch_cls in class_bases: srch_obj = getattr(srch_cls, name, None) - if srch_obj == get_obj: + if srch_obj is get_obj: last_cls = srch_cls # then check the metaclasses for srch_cls in metamro: @@ -388,7 +388,7 @@ srch_obj = srch_cls.__getattr__(cls, name) except AttributeError: continue - if srch_obj == get_obj: + if srch_obj is get_obj: last_cls = srch_cls if last_cls is not None: homecls = last_cls @@ -402,7 +402,7 @@ # unable to locate the attribute anywhere, most likely due to # buggy custom __dir__; discard and move on continue - obj = get_obj or dict_obj + obj = get_obj if get_obj is not None else dict_obj # Classify the object or its descriptor. if isinstance(dict_obj, staticmethod): kind = "static method" diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -782,6 +782,21 @@ should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam') self.assertIn(should_find_ga, inspect.classify_class_attrs(VA)) + def test_classify_overrides_bool(self): + class NoBool(object): + def __eq__(self, other): + return NoBool() + + def __bool__(self): + raise NotImplementedError( + "This object does not specify a boolean value") + + class HasNB(object): + dd = NoBool() + + should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd) + self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB)) + def test_classify_metaclass_class_attribute(self): class Meta(type): fish = 'slap' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -260,6 +260,9 @@ - asyncio: async() function is deprecated in favour of ensure_future(). +- Issue 23898: Fix inspect.classify_class_attrs() to support attributes + with overloaded __eq__ and __bool__. Patch by Mike Bayer. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 21:46:17 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 19:46:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_23898=3A_Fix_inspect=2Eclassify=5Fclass=5Fattrs=28?= =?utf-8?b?KSB0byB3b3JrIHdpdGggX19lcV9f?= Message-ID: <20150521194616.4231.50264@psf.io> https://hg.python.org/cpython/rev/d6a9d225413a changeset: 96195:d6a9d225413a parent: 96193:f23533fa6afa parent: 96194:fb9addfdfc35 user: Yury Selivanov date: Thu May 21 15:45:08 2015 -0400 summary: Issue 23898: Fix inspect.classify_class_attrs() to work with __eq__ Patch by Mike Bayer. files: Lib/inspect.py | 6 +++--- Lib/test/test_inspect.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -395,7 +395,7 @@ # first look in the classes for srch_cls in class_bases: srch_obj = getattr(srch_cls, name, None) - if srch_obj == get_obj: + if srch_obj is get_obj: last_cls = srch_cls # then check the metaclasses for srch_cls in metamro: @@ -403,7 +403,7 @@ srch_obj = srch_cls.__getattr__(cls, name) except AttributeError: continue - if srch_obj == get_obj: + if srch_obj is get_obj: last_cls = srch_cls if last_cls is not None: homecls = last_cls @@ -417,7 +417,7 @@ # unable to locate the attribute anywhere, most likely due to # buggy custom __dir__; discard and move on continue - obj = get_obj or dict_obj + obj = get_obj if get_obj is not None else dict_obj # Classify the object or its descriptor. if isinstance(dict_obj, staticmethod): kind = "static method" diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -888,6 +888,21 @@ should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam') self.assertIn(should_find_ga, inspect.classify_class_attrs(VA)) + def test_classify_overrides_bool(self): + class NoBool(object): + def __eq__(self, other): + return NoBool() + + def __bool__(self): + raise NotImplementedError( + "This object does not specify a boolean value") + + class HasNB(object): + dd = NoBool() + + should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd) + self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB)) + def test_classify_metaclass_class_attribute(self): class Meta(type): fish = 'slap' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,9 @@ - Issue #24017: PEP 492: Coroutines with async and await syntax. +- Issue #23898: Fix inspect.classify_class_attrs() to support attributes + with overloaded __eq__ and __bool__. Patch by Mike Bayer. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 21:49:04 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 19:49:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_a_misplaced_NEWS_entry?= =?utf-8?q?=2E?= Message-ID: <20150521194903.26856.75801@psf.io> https://hg.python.org/cpython/rev/1ace09ac33b0 changeset: 96196:1ace09ac33b0 user: Yury Selivanov date: Thu May 21 15:48:59 2015 -0400 summary: Fix a misplaced NEWS entry. files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,9 +52,6 @@ - Issue #24017: PEP 492: Coroutines with async and await syntax. -- Issue #23898: Fix inspect.classify_class_attrs() to support attributes - with overloaded __eq__ and __bool__. Patch by Mike Bayer. - Library ------- @@ -196,6 +193,9 @@ - Issue 24248: Deprecate inspect.Signature.from_function() and inspect.Signature.from_builtin(). +- Issue #23898: Fix inspect.classify_class_attrs() to support attributes + with overloaded __eq__ and __bool__. Patch by Mike Bayer. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 22:40:52 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 21 May 2015 20:40:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Set_stacklevel_to_2_to_get?= =?utf-8?q?_more_accurate_warning_messages_from_deprecated?= Message-ID: <20150521204052.39265.95651@psf.io> https://hg.python.org/cpython/rev/6362e9dc09de changeset: 96197:6362e9dc09de user: Berker Peksag date: Thu May 21 23:40:54 2015 +0300 summary: Set stacklevel to 2 to get more accurate warning messages from deprecated functions. files: Lib/inspect.py | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2662,7 +2662,8 @@ """Constructs Signature for the given python function.""" warnings.warn("inspect.Signature.from_function() is deprecated, " - "use Signature.from_callable()", DeprecationWarning) + "use Signature.from_callable()", + DeprecationWarning, stacklevel=2) return _signature_from_function(cls, func) @classmethod @@ -2670,7 +2671,8 @@ """Constructs Signature for the given builtin function.""" warnings.warn("inspect.Signature.from_builtin() is deprecated, " - "use Signature.from_callable()", DeprecationWarning) + "use Signature.from_callable()", + DeprecationWarning, stacklevel=2) return _signature_from_builtin(cls, func) @classmethod -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 21 23:02:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 21 May 2015 21:02:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24180=3A_Fixes_by_Be?= =?utf-8?q?rker_Peksag=2E?= Message-ID: <20150521210235.4237.95801@psf.io> https://hg.python.org/cpython/rev/5691d2d2d0a4 changeset: 96198:5691d2d2d0a4 user: Yury Selivanov date: Thu May 21 17:02:31 2015 -0400 summary: Issue 24180: Fixes by Berker Peksag. files: Doc/c-api/typeobj.rst | 5 ++--- Doc/glossary.rst | 12 ------------ Doc/library/exceptions.rst | 1 - Doc/library/inspect.rst | 12 +++++------- 4 files changed, 7 insertions(+), 23 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -227,9 +227,7 @@ protocols at the C-level. See :ref:`async-structs` for details. .. versionadded:: 3.5 - - .. note:: - Formerly known as tp_compare and tp_reserved. + Formerly known as ``tp_compare`` and ``tp_reserved``. .. c:member:: reprfunc PyTypeObject.tp_repr @@ -1349,6 +1347,7 @@ .. sectionauthor:: Yury Selivanov +.. versionadded:: 3.5 .. c:type:: PyAsyncMethods diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -74,16 +74,12 @@ :keyword:`async with` statement by defining :meth:`__aenter__` and :meth:`__aexit__` methods. Introduced by :pep:`492`. - .. versionadded:: 3.5 - asynchronous iterable An object, that can be used in an :keyword:`async for` statement. Must return an :term:`awaitable` from its :meth:`__aiter__` method, which should in turn be resolved in an :term:`asynchronous iterator` object. Introduced by :pep:`492`. - .. versionadded:: 3.5 - asynchronous iterator An object that implements :meth:`__aiter__` and :meth:`__anext__` methods, that must return :term:`awaitable` objects. @@ -91,8 +87,6 @@ iterator's :meth:`__anext__` method until it raises :exc:`StopAsyncIteration` exception. Introduced by :pep:`492`. - .. versionadded:: 3.5 - attribute A value associated with an object which is referenced by name using dotted expressions. For example, if an object *o* has an attribute @@ -103,8 +97,6 @@ a :term:`coroutine` or an object with an :meth:`__await__` method. See also :pep:`492`. - .. versionadded:: 3.5 - BDFL Benevolent Dictator For Life, a.k.a. `Guido van Rossum `_, Python's creator. @@ -183,8 +175,6 @@ :keyword:`async for`, and :keyword:`async with` keywords. Introduced by :pep:`492`. - .. versionadded:: 3.5 - coroutine Coroutines is a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines, can be @@ -192,8 +182,6 @@ :keyword:`await` expressions, and :keyword:`async for` and :keyword:`async with` statements. See also :pep:`492`. - .. versionadded:: 3.5 - CPython The canonical implementation of the Python programming language, as distributed on `python.org `_. The term "CPython" diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -328,7 +328,6 @@ :term:`asynchronous iterator` object to stop the iteration. .. versionadded:: 3.5 - See also :pep:`492`. .. exception:: SyntaxError diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -268,23 +268,21 @@ .. function:: iscoroutinefunction(object) - Return true if the object is a coroutine function. + Return true if the object is a :term:`coroutine function`. Coroutine functions are defined with an ``async def`` syntax, or are generators decorated with :func:`types.coroutine` or :func:`asyncio.coroutine`. - The function will return false for plain python generator + The function will return false for plain Python generator functions. - See also :pep:`492`. - .. versionadded:: 3.5 .. function:: iscoroutine(object) - Return true if the object is a coroutine. + Return true if the object is a :term:`coroutine`. Coroutines are results of calls of coroutine functions or generator functions decorated with :func:`types.coroutine` @@ -292,7 +290,7 @@ The function will return false for plain python generators. - See also :class:`collections.abc.Coroutine` and :pep:`492`. + See also :class:`collections.abc.Coroutine`. .. versionadded:: 3.5 @@ -302,7 +300,7 @@ Return true if the object can be used in :keyword:`await` expression. - See also :class:`collections.abc.Awaitable` and :pep:`492`. + See also :class:`collections.abc.Awaitable`. .. versionadded:: 3.5 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 06:39:27 2015 From: python-checkins at python.org (donald.stufft) Date: Fri, 22 May 2015 04:39:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Upgrade_pip_to?= =?utf-8?q?_7=2E0_and_setuptools_to_16=2E0?= Message-ID: <20150522043927.39239.63639@psf.io> https://hg.python.org/cpython/rev/16c42506fbdf changeset: 96199:16c42506fbdf branch: 3.4 parent: 96194:fb9addfdfc35 user: Donald Stufft date: Fri May 22 00:39:22 2015 -0400 summary: Upgrade pip to 7.0 and setuptools to 16.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.2" +_SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "6.1.1" +_PIP_VERSION = "7.0.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl deleted file mode 100644 index e59694a019051d58b9a378a1adfc9461b8cec9c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..926d2a79fa715a9f9a9825a6304bcbd96683612e GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl deleted file mode 100644 index f153ed376684275e08fcfebdb2de8352fb074171..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fa4e994929b5bd27f99a44c78e08f48d142ccfd9 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 06:40:02 2015 From: python-checkins at python.org (donald.stufft) Date: Fri, 22 May 2015 04:40:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge=3A_Upgrade_pip_to_7=2E0_and_setuptools_to_16=2E0?= Message-ID: <20150522044002.26568.24848@psf.io> https://hg.python.org/cpython/rev/1ca30423b0c9 changeset: 96200:1ca30423b0c9 parent: 96198:5691d2d2d0a4 parent: 96199:16c42506fbdf user: Donald Stufft date: Fri May 22 00:39:57 2015 -0400 summary: merge: Upgrade pip to 7.0 and setuptools to 16.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.2" +_SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "6.1.1" +_PIP_VERSION = "7.0.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl deleted file mode 100644 index e59694a019051d58b9a378a1adfc9461b8cec9c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..926d2a79fa715a9f9a9825a6304bcbd96683612e GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl deleted file mode 100644 index f153ed376684275e08fcfebdb2de8352fb074171..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fa4e994929b5bd27f99a44c78e08f48d142ccfd9 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 06:43:40 2015 From: python-checkins at python.org (donald.stufft) Date: Fri, 22 May 2015 04:43:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Upgrade_pip_to?= =?utf-8?q?_7=2E0_and_setuptools_to_16=2E0?= Message-ID: <20150522044340.26574.76455@psf.io> https://hg.python.org/cpython/rev/a4cb9c30cd91 changeset: 96201:a4cb9c30cd91 branch: 2.7 parent: 96191:d6179accca20 user: Donald Stufft date: Fri May 22 00:43:31 2015 -0400 summary: Upgrade pip to 7.0 and setuptools to 16.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.2" +_SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "6.1.1" +_PIP_VERSION = "7.0.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl deleted file mode 100644 index e59694a019051d58b9a378a1adfc9461b8cec9c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..926d2a79fa715a9f9a9825a6304bcbd96683612e GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl deleted file mode 100644 index f153ed376684275e08fcfebdb2de8352fb074171..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fa4e994929b5bd27f99a44c78e08f48d142ccfd9 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 09:42:09 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 22 May 2015 07:42:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324221=3A__Small_o?= =?utf-8?q?ptimizations_for_heapq=2E?= Message-ID: <20150522074209.4235.41611@psf.io> https://hg.python.org/cpython/rev/490720fc1525 changeset: 96202:490720fc1525 parent: 96200:1ca30423b0c9 user: Raymond Hettinger date: Fri May 22 00:41:57 2015 -0700 summary: Issue #24221: Small optimizations for heapq. Replaces the PyList_GET_ITEM and PyList_SET_ITEM macros with normal array accesses. Replace the siftup unpredicatable branch with arithmetic. Replace the rc == -1 tests with rc < 0. Gives nicer looking assembly with both Clang and GCC-4.9. Also gives a small performance both for both. files: Include/listobject.h | 1 + Modules/_heapqmodule.c | 80 ++++++++++++++++------------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/Include/listobject.h b/Include/listobject.h --- a/Include/listobject.h +++ b/Include/listobject.h @@ -72,6 +72,7 @@ #define PyList_GET_ITEM(op, i) (((PyListObject *)(op))->ob_item[i]) #define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v)) #define PyList_GET_SIZE(op) Py_SIZE(op) +#define _PyList_ITEMS(op) (((PyListObject *)(op))->ob_item) #endif #ifdef __cplusplus diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -11,7 +11,7 @@ static int siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, **arr; Py_ssize_t parentpos, size; int cmp; @@ -24,12 +24,13 @@ /* Follow the path to the root, moving parents down until finding a place newitem fits. */ - newitem = PyList_GET_ITEM(heap, pos); + arr = _PyList_ITEMS(heap); + newitem = arr[pos]; while (pos > startpos) { parentpos = (pos - 1) >> 1; - parent = PyList_GET_ITEM(heap, parentpos); + parent = arr[parentpos]; cmp = PyObject_RichCompareBool(newitem, parent, Py_LT); - if (cmp == -1) + if (cmp < 0) return -1; if (size != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, @@ -38,10 +39,11 @@ } if (cmp == 0) break; - parent = PyList_GET_ITEM(heap, parentpos); - newitem = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, parentpos, newitem); - PyList_SET_ITEM(heap, pos, parent); + arr = _PyList_ITEMS(heap); + parent = arr[parentpos]; + newitem = arr[pos]; + arr[parentpos] = newitem; + arr[pos] = parent; pos = parentpos; } return 0; @@ -51,7 +53,7 @@ siftup(PyListObject *heap, Py_ssize_t pos) { Py_ssize_t startpos, endpos, childpos, limit; - PyObject *tmp1, *tmp2; + PyObject *tmp1, *tmp2, **arr; int cmp; assert(PyList_Check(heap)); @@ -63,19 +65,19 @@ } /* Bubble up the smaller child until hitting a leaf. */ + arr = _PyList_ITEMS(heap); limit = endpos / 2; /* smallest pos that has no child */ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ if (childpos + 1 < endpos) { cmp = PyObject_RichCompareBool( - PyList_GET_ITEM(heap, childpos), - PyList_GET_ITEM(heap, childpos + 1), + arr[childpos], + arr[childpos + 1], Py_LT); - if (cmp == -1) + if (cmp < 0) return -1; - if (cmp == 0) - childpos++; /* rightmost child is smallest */ + childpos += ((unsigned)cmp ^ 1); /* increment when cmp==0 */ if (endpos != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); @@ -83,10 +85,11 @@ } } /* Move the smaller child up. */ - tmp1 = PyList_GET_ITEM(heap, childpos); - tmp2 = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, childpos, tmp2); - PyList_SET_ITEM(heap, pos, tmp1); + arr = _PyList_ITEMS(heap); + tmp1 = arr[childpos]; + tmp2 = arr[pos]; + arr[childpos] = tmp2; + arr[pos] = tmp1; pos = childpos; } /* Bubble it up to its final resting place (by sifting its parents down). */ @@ -227,7 +230,7 @@ } cmp = PyObject_RichCompareBool(PyList_GET_ITEM(heap, 0), item, Py_LT); - if (cmp == -1) + if (cmp < 0) return NULL; if (cmp == 0) { Py_INCREF(item); @@ -362,7 +365,7 @@ static int siftdown_max(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) { - PyObject *newitem, *parent; + PyObject *newitem, *parent, **arr; Py_ssize_t parentpos, size; int cmp; @@ -375,12 +378,13 @@ /* Follow the path to the root, moving parents down until finding a place newitem fits. */ - newitem = PyList_GET_ITEM(heap, pos); + arr = _PyList_ITEMS(heap); + newitem = arr[pos]; while (pos > startpos) { parentpos = (pos - 1) >> 1; - parent = PyList_GET_ITEM(heap, parentpos); + parent = arr[parentpos]; cmp = PyObject_RichCompareBool(parent, newitem, Py_LT); - if (cmp == -1) + if (cmp < 0) return -1; if (size != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, @@ -389,10 +393,11 @@ } if (cmp == 0) break; - parent = PyList_GET_ITEM(heap, parentpos); - newitem = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, parentpos, newitem); - PyList_SET_ITEM(heap, pos, parent); + arr = _PyList_ITEMS(heap); + parent = arr[parentpos]; + newitem = arr[pos]; + arr[parentpos] = newitem; + arr[pos] = parent; pos = parentpos; } return 0; @@ -402,7 +407,7 @@ siftup_max(PyListObject *heap, Py_ssize_t pos) { Py_ssize_t startpos, endpos, childpos, limit; - PyObject *tmp1, *tmp2; + PyObject *tmp1, *tmp2, **arr; int cmp; assert(PyList_Check(heap)); @@ -414,19 +419,19 @@ } /* Bubble up the smaller child until hitting a leaf. */ + arr = _PyList_ITEMS(heap); limit = endpos / 2; /* smallest pos that has no child */ while (pos < limit) { /* Set childpos to index of smaller child. */ childpos = 2*pos + 1; /* leftmost child position */ if (childpos + 1 < endpos) { cmp = PyObject_RichCompareBool( - PyList_GET_ITEM(heap, childpos + 1), - PyList_GET_ITEM(heap, childpos), + arr[childpos + 1], + arr[childpos], Py_LT); - if (cmp == -1) + if (cmp < 0) return -1; - if (cmp == 0) - childpos++; /* rightmost child is smallest */ + childpos += ((unsigned)cmp ^ 1); /* increment when cmp==0 */ if (endpos != PyList_GET_SIZE(heap)) { PyErr_SetString(PyExc_RuntimeError, "list changed size during iteration"); @@ -434,10 +439,11 @@ } } /* Move the smaller child up. */ - tmp1 = PyList_GET_ITEM(heap, childpos); - tmp2 = PyList_GET_ITEM(heap, pos); - PyList_SET_ITEM(heap, childpos, tmp2); - PyList_SET_ITEM(heap, pos, tmp1); + arr = _PyList_ITEMS(heap); + tmp1 = arr[childpos]; + tmp2 = arr[pos]; + arr[childpos] = tmp2; + arr[pos] = tmp1; pos = childpos; } /* Bubble it up to its final resting place (by sifting its parents down). */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 10:14:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 22 May 2015 08:14:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324257=3A_Fixed_incorrect_uses_of_PyObject=5FIsI?= =?utf-8?q?nstance=28=29=2E?= Message-ID: <20150522081403.10812.7922@psf.io> https://hg.python.org/cpython/rev/a5101529a8a9 changeset: 96205:a5101529a8a9 parent: 96202:490720fc1525 parent: 96204:c7b9645a6f35 user: Serhiy Storchaka date: Fri May 22 11:13:20 2015 +0300 summary: Issue #24257: Fixed incorrect uses of PyObject_IsInstance(). Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. Fixed system error in the comparison of faked types.SimpleNamespace. files: Lib/sqlite3/test/factory.py | 8 ++++++++ Lib/test/test_types.py | 16 ++++++++++++++++ Misc/NEWS | 6 ++++++ Modules/_sqlite/row.c | 2 +- Objects/genobject.c | 5 ++--- Objects/namespaceobject.c | 7 +++---- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -180,6 +180,14 @@ self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) + def CheckFakeCursorClass(self): + # Issue #24257: Incorrect use of PyObject_IsInstance() caused + # segmentation fault. + class FakeCursor(str): + __class__ = sqlite.Cursor + cur = self.con.cursor(factory=FakeCursor) + self.assertRaises(TypeError, sqlite.Row, cur, ()) + def tearDown(self): self.con.close() diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1172,6 +1172,22 @@ self.assertEqual(ns, ns_roundtrip, pname) + def test_fake_namespace_compare(self): + # Issue #24257: Incorrect use of PyObject_IsInstance() caused + # SystemError. + class FakeSimpleNamespace(str): + __class__ = types.SimpleNamespace + self.assertFalse(types.SimpleNamespace() == FakeSimpleNamespace()) + self.assertTrue(types.SimpleNamespace() != FakeSimpleNamespace()) + with self.assertRaises(TypeError): + types.SimpleNamespace() < FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() <= FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() > FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() >= FakeSimpleNamespace() + class CoroutineTests(unittest.TestCase): def test_wrong_args(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24257: Fixed system error in the comparison of faked + types.SimpleNamespace. + - Issue #22939: Fixed integer overflow in iterator object. Patch by Clement Rouault. @@ -55,6 +58,9 @@ Library ------- +- Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked + cursor type. + - Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() assertments now check the type of the first argument to prevent possible user error. Based on patch by Daniel Wagner-Hall. diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -46,7 +46,7 @@ if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) return NULL; - if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { + if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return NULL; } diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -442,8 +442,7 @@ PyErr_Fetch(&et, &ev, &tb); if (ev) { /* exception will usually be normalised already */ - if (Py_TYPE(ev) == (PyTypeObject *) et - || PyObject_IsInstance(ev, PyExc_StopIteration)) { + if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) { value = ((PyStopIterationObject *)ev)->value; Py_INCREF(value); Py_DECREF(ev); @@ -453,7 +452,7 @@ } else { /* normalisation required */ PyErr_NormalizeException(&et, &ev, &tb); - if (!PyObject_IsInstance(ev, PyExc_StopIteration)) { + if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) { PyErr_Restore(et, ev, tb); return -1; } diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -164,12 +164,11 @@ static PyObject * namespace_richcompare(PyObject *self, PyObject *other, int op) { - if (PyObject_IsInstance(self, (PyObject *)&_PyNamespace_Type) && - PyObject_IsInstance(other, (PyObject *)&_PyNamespace_Type)) + if (PyObject_TypeCheck(self, &_PyNamespace_Type) && + PyObject_TypeCheck(other, &_PyNamespace_Type)) return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict, ((_PyNamespaceObject *)other)->ns_dict, op); - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 10:14:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 22 May 2015 08:14:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjU3?= =?utf-8?q?=3A_Fixed_incorrect_uses_of_PyObject=5FIsInstance=28=29=2E?= Message-ID: <20150522081403.10808.23383@psf.io> https://hg.python.org/cpython/rev/c7b9645a6f35 changeset: 96204:c7b9645a6f35 branch: 3.4 parent: 96199:16c42506fbdf user: Serhiy Storchaka date: Fri May 22 11:02:49 2015 +0300 summary: Issue #24257: Fixed incorrect uses of PyObject_IsInstance(). Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. Fixed system error in the comparison of faked types.SimpleNamespace. files: Lib/sqlite3/test/factory.py | 8 ++++++++ Lib/test/test_types.py | 16 ++++++++++++++++ Misc/NEWS | 6 ++++++ Modules/_sqlite/row.c | 2 +- Objects/genobject.c | 5 ++--- Objects/namespaceobject.c | 7 +++---- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -162,6 +162,14 @@ self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) + def CheckFakeCursorClass(self): + # Issue #24257: Incorrect use of PyObject_IsInstance() caused + # segmentation fault. + class FakeCursor(str): + __class__ = sqlite.Cursor + cur = self.con.cursor(factory=FakeCursor) + self.assertRaises(TypeError, sqlite.Row, cur, ()) + def tearDown(self): self.con.close() diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1169,6 +1169,22 @@ self.assertEqual(ns, ns_roundtrip, pname) + def test_fake_namespace_compare(self): + # Issue #24257: Incorrect use of PyObject_IsInstance() caused + # SystemError. + class FakeSimpleNamespace(str): + __class__ = types.SimpleNamespace + self.assertFalse(types.SimpleNamespace() == FakeSimpleNamespace()) + self.assertTrue(types.SimpleNamespace() != FakeSimpleNamespace()) + with self.assertRaises(TypeError): + types.SimpleNamespace() < FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() <= FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() > FakeSimpleNamespace() + with self.assertRaises(TypeError): + types.SimpleNamespace() >= FakeSimpleNamespace() + def test_main(): run_unittest(TypesTests, MappingProxyTests, ClassCreationTests, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24257: Fixed system error in the comparison of faked + types.SimpleNamespace. + - Issue #22939: Fixed integer overflow in iterator object. Patch by Clement Rouault. @@ -56,6 +59,9 @@ Library ------- +- Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked + cursor type. + - Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -46,7 +46,7 @@ if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) return NULL; - if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { + if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return NULL; } diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -398,8 +398,7 @@ PyErr_Fetch(&et, &ev, &tb); if (ev) { /* exception will usually be normalised already */ - if (Py_TYPE(ev) == (PyTypeObject *) et - || PyObject_IsInstance(ev, PyExc_StopIteration)) { + if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) { value = ((PyStopIterationObject *)ev)->value; Py_INCREF(value); Py_DECREF(ev); @@ -409,7 +408,7 @@ } else { /* normalisation required */ PyErr_NormalizeException(&et, &ev, &tb); - if (!PyObject_IsInstance(ev, PyExc_StopIteration)) { + if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) { PyErr_Restore(et, ev, tb); return -1; } diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -164,12 +164,11 @@ static PyObject * namespace_richcompare(PyObject *self, PyObject *other, int op) { - if (PyObject_IsInstance(self, (PyObject *)&_PyNamespace_Type) && - PyObject_IsInstance(other, (PyObject *)&_PyNamespace_Type)) + if (PyObject_TypeCheck(self, &_PyNamespace_Type) && + PyObject_TypeCheck(other, &_PyNamespace_Type)) return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict, ((_PyNamespaceObject *)other)->ns_dict, op); - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 10:14:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 22 May 2015 08:14:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MjU3?= =?utf-8?q?=3A_Fixed_segmentation_fault_in_sqlite3=2ERow_constructor_with_?= =?utf-8?q?faked?= Message-ID: <20150522081403.27927.65699@psf.io> https://hg.python.org/cpython/rev/bccaba8a5482 changeset: 96203:bccaba8a5482 branch: 2.7 parent: 96201:a4cb9c30cd91 user: Serhiy Storchaka date: Fri May 22 11:00:40 2015 +0300 summary: Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. files: Lib/sqlite3/test/factory.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_sqlite/row.c | 2 +- 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -170,6 +170,14 @@ self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) + def CheckFakeCursorClass(self): + # Issue #24257: Incorrect use of PyObject_IsInstance() caused + # segmentation fault. + class FakeCursor(str): + __class__ = sqlite.Cursor + cur = self.con.cursor(factory=FakeCursor) + self.assertRaises(TypeError, sqlite.Row, cur, ()) + def tearDown(self): self.con.close() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,9 @@ Library ------- +- Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked + cursor type. + - Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -47,7 +47,7 @@ if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) return NULL; - if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { + if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return NULL; } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri May 22 10:45:37 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 22 May 2015 08:45:37 +0000 Subject: [Python-checkins] Daily reference leaks (1ca30423b0c9): sum=4 Message-ID: <20150522084536.45373.15564@psf.io> results for 1ca30423b0c9 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog0mmgzE', '--timeout', '7200'] From python-checkins at python.org Fri May 22 17:16:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 15:16:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24237=3A_Raise_Pendi?= =?utf-8?q?ngDeprecationWarning_per_PEP_479?= Message-ID: <20150522151653.70431.74238@psf.io> https://hg.python.org/cpython/rev/2771a0ac806b changeset: 96206:2771a0ac806b user: Yury Selivanov date: Fri May 22 11:16:47 2015 -0400 summary: Issue 24237: Raise PendingDeprecationWarning per PEP 479 Raise PendingDeprecationWarning when generator raises StopIteration and no __future__ import is used. Fix offenders in the stdlib and tests. See also issue 22906. Thanks to Nick Coghlan and Berker Peksag for reviews. files: Lib/difflib.py | 10 +++- Lib/test/test_contextlib.py | 6 +- Lib/test/test_generators.py | 62 ++++++++++++++++-------- Lib/test/test_with.py | 6 +- Objects/genobject.c | 23 ++++++++- 5 files changed, 78 insertions(+), 29 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1582,7 +1582,10 @@ while True: # Collecting lines of text until we have a from/to pair while (len(fromlines)==0 or len(tolines)==0): - from_line, to_line, found_diff = next(line_iterator) + try: + from_line, to_line, found_diff = next(line_iterator) + except StopIteration: + return if from_line is not None: fromlines.append((from_line,found_diff)) if to_line is not None: @@ -1609,7 +1612,10 @@ index, contextLines = 0, [None]*(context) found_diff = False while(found_diff is False): - from_line, to_line, found_diff = next(line_pair_iterator) + try: + from_line, to_line, found_diff = next(line_pair_iterator) + except StopIteration: + return i = index % context contextLines[i] = (from_line, to_line, found_diff) index += 1 diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -89,8 +89,10 @@ def woohoo(): yield try: - with woohoo(): - raise stop_exc + with self.assertWarnsRegex(PendingDeprecationWarning, + "StopIteration"): + with woohoo(): + raise stop_exc except Exception as ex: self.assertIs(ex, stop_exc) else: diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1,6 +1,7 @@ import gc import sys import unittest +import warnings import weakref from test import support @@ -217,6 +218,46 @@ self.assertEqual(next(g), "done") self.assertEqual(sys.exc_info(), (None, None, None)) + def test_stopiteration_warning(self): + # See also PEP 479. + + def gen(): + raise StopIteration + yield + + with self.assertRaises(StopIteration), \ + self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"): + + next(gen()) + + with self.assertRaisesRegex(PendingDeprecationWarning, + "generator .* raised StopIteration"), \ + warnings.catch_warnings(): + + warnings.simplefilter('error') + next(gen()) + + + def test_tutorial_stopiteration(self): + # Raise StopIteration" stops the generator too: + + def f(): + yield 1 + raise StopIteration + yield 2 # never reached + + g = f() + self.assertEqual(next(g), 1) + + with self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"): + with self.assertRaises(StopIteration): + next(g) + + with self.assertRaises(StopIteration): + # This time StopIteration isn't raised from the generator's body, + # hence no warning. + next(g) + tutorial_tests = """ Let's try a simple generator: @@ -263,26 +304,7 @@ File "", line 1, in ? StopIteration -"raise StopIteration" stops the generator too: - - >>> def f(): - ... yield 1 - ... raise StopIteration - ... yield 2 # never reached - ... - >>> g = f() - >>> next(g) - 1 - >>> next(g) - Traceback (most recent call last): - File "", line 1, in ? - StopIteration - >>> next(g) - Traceback (most recent call last): - File "", line 1, in ? - StopIteration - -However, they are not exactly equivalent: +However, "return" and StopIteration are not exactly equivalent: >>> def g1(): ... try: diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py --- a/Lib/test/test_with.py +++ b/Lib/test/test_with.py @@ -454,7 +454,8 @@ with cm(): raise StopIteration("from with") - self.assertRaises(StopIteration, shouldThrow) + with self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"): + self.assertRaises(StopIteration, shouldThrow) def testRaisedStopIteration2(self): # From bug 1462485 @@ -481,7 +482,8 @@ with cm(): raise next(iter([])) - self.assertRaises(StopIteration, shouldThrow) + with self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"): + self.assertRaises(StopIteration, shouldThrow) def testRaisedGeneratorExit1(self): # From bug 1462485 diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -143,13 +143,12 @@ } Py_CLEAR(result); } - else if (!result) { + else if (!result && PyErr_ExceptionMatches(PyExc_StopIteration)) { /* Check for __future__ generator_stop and conditionally turn * a leaking StopIteration into RuntimeError (with its cause * set appropriately). */ - if ((((PyCodeObject *)gen->gi_code)->co_flags & + if (((PyCodeObject *)gen->gi_code)->co_flags & (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE)) - && PyErr_ExceptionMatches(PyExc_StopIteration)) { PyObject *exc, *val, *val2, *tb; PyErr_Fetch(&exc, &val, &tb); @@ -167,6 +166,24 @@ PyException_SetContext(val2, val); PyErr_Restore(exc, val2, tb); } + else { + PyObject *exc, *val, *tb; + + /* Pop the exception before issuing a warning. */ + PyErr_Fetch(&exc, &val, &tb); + + if (PyErr_WarnFormat(PyExc_PendingDeprecationWarning, 1, + "generator '%.50S' raised StopIteration", + gen->gi_qualname)) { + /* Warning was converted to an error. */ + Py_XDECREF(exc); + Py_XDECREF(val); + Py_XDECREF(tb); + } + else { + PyErr_Restore(exc, val, tb); + } + } } if (!result || f->f_stacktop == NULL) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 17:24:03 2015 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 22 May 2015 15:24:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_484=2E_Mostly_clar?= =?utf-8?q?ifications_and_edits=3B_dropped_predefined_platform?= Message-ID: <20150522152403.16309.42733@psf.io> https://hg.python.org/peps/rev/40d5e05e77fd changeset: 5873:40d5e05e77fd user: Guido van Rossum date: Fri May 22 08:21:26 2015 -0700 summary: Update PEP 484. Mostly clarifications and edits; dropped predefined platform constants. files: pep-0484.txt | 186 ++++++++++++++++++++++++++------------- 1 files changed, 124 insertions(+), 62 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -9,7 +9,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 29-Sep-2014 -Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015 +Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015,22-May-2015 Resolution: @@ -109,8 +109,12 @@ function, the default annotation for arguments and for the return type is ``Any``. An exception is that the first argument of instance and class methods does not need to be annotated; it is assumed to have the -type of the containing class for instance methods, and ``type`` for -class methods. +type of the containing class for instance methods, and a type object +type corresponding to the containing class object for class methods. +For example, in class ``A`` the first argument of an instance method +has the implicit type ``A``. In a class method, the precise type of +the first argument cannot be represented using the available type +notation. (Note that the return type of ``__init__`` ought to be annotated with ``-> None``. The reason for this is subtle. If ``__init__`` assumed @@ -158,7 +162,7 @@ While annotations are normally the best format for type hints, there are times when it is more appropriate to represent them -by a special comment, or in a separately distributed interface +by a special comment, or in a separately distributed stub file. (See below for examples.) Annotations must be valid expressions that evaluate without raising @@ -284,6 +288,11 @@ In this case the contract is that the returned value is consistent with the elements held by the collection. +A ``TypeVar()`` expression must always directly be assigned to a +variable (it should not be used as part of a larger expression). The +argument to ``TypeVar()`` must be a string equal to the variable name +to which it is assigned. Type variables must not be redefined. + ``TypeVar`` supports constraining parametric types to a fixed set of possible types. For example, we can define a type variable that ranges over just ``str`` and ``bytes``. By default, a type variable ranges @@ -406,25 +415,57 @@ class MyIterable(Iterable): # Same as Iterable[Any] ... +Generic metaclasses are not supported. + Instantiating generic classes and type erasure ---------------------------------------------- Generic types like ``List`` or ``Sequence`` cannot be instantiated. However, user-defined classes derived from them can be instantiated. -Given a generic class ``Node[T]`` there are three forms of -instantiation: +Suppose we write a ``Node`` class inheriting from ``Generic[T]``:: -* ``x = Node()`` -- the type of x is ``Node[Any]``. + from typing import TypeVar, Generic -* ``x = Node[T]()`` -- the type of x is ``Node[T]``. + T = TypeVar('T') -* ``x = Node[int]()`` -- the type of x is ``Node[int]``. + class Node(Generic[T]): + ... -At runtime the type is not preserved, and the observable type of x is -just ``Node``. This is type erasure and common practice in languages -with generics (e.g. Java, Typescript). +Now there are two ways we can instantiate this class; the type +inferred by a type checker may be different depending on the form we +use. The first way is to give the value of the type parameter +explicitly -- this overrides whatever type inference the type +checker would otherwise perform: + x = Node[T]() # The type inferred for x is Node[T]. + + y = Node[int]() # The type inferred for y is Node[int]. + +If no explicit types are given, the type checker is given some +freedom. Consider this code: + + x = Node() + +The inferred type could be ``Node[Any]``, as there isn't enough +context to infer a more precise type. Alternatively, a type checker +may reject the line and require an explicit annotation, like this: + + x = Node() # type: Node[int] # Inferred type is Node[int]. + +A type checker with more powerful type inference could look at how +``x`` is used elsewhere in the file and try to infer a more precise +type such as ``Node[int]`` even without an explicit type annotation. +However, it is probably impossible to make such type inference work +well in all cases, since Python programs can be very dynamic. + +This PEP doesn't specify the details of how type inference should +work. We allow different tools to experiment with various approaches. +We may give more explicit rules in future revisions. + +At runtime the type is not preserved, and the class of ``x`` is just +``Node`` in all cases. This behavior is called "type erasure"; it is +common practice in languages with generics (e.g. Java, TypeScript). Arbitrary generic types as base classes @@ -565,28 +606,30 @@ is desirable, pass ``contravariant=True``. At most one of these may be passed. -A typical example involves defining an immutable container class:: +A typical example involves defining an immutable (or read-only) +container class:: - from typing import TypeVar + from typing import TypeVar, Generic, Iterable, Iterator T = TypeVar('T', covariant=True) class ImmutableList(Generic[T]): - def append(self, T): ... + def __init__(self, items: Iterable[T]) -> None: ... + def __iter__(self) -> Iterator[T]: ... ... class Employee: ... class Manager(Employee): ... - def dump_employees(emps: ImmutableList[Employee]) -> None: ... + def dump_employees(emps: ImmutableList[Employee]) -> None: + for emp in emps: + ... - mgrs = ... # type: ImmutableList[Mananger] - mgrs.append(Manager()) - + mgrs = ImmutableList([Manager()]) # type: ImmutableList[Manager] dump_employees(mgrs) # OK -The immutable collection classes in ``typing`` are all defined using a +The read-only collection classes in ``typing`` are all defined using a covariant type variable (e.g. ``Mapping`` and ``Sequence``). The mutable collection classes (e.g. ``MutableMapping`` and ``MutableSequence``) are defined using regular invariant type @@ -676,7 +719,7 @@ self.right = right The string literal should contain a valid Python expression (i.e., -``compile(lit, '', 'expr')`` should be a valid code object) and it +``compile(lit, '', 'eval')`` should be a valid code object) and it should evaluate without errors once the module has been fully loaded. The local and global namespace in which it is evaluated should be the same namespaces in which default arguments to the same function would @@ -711,8 +754,8 @@ def bar(self, a: A): ... # File main.py - from a import A - from b import B + from models.a import A + from models.b import B Assuming main is imported first, this will fail with an ImportError at the line ``from models.a import A`` in models/b.py, which is being @@ -731,8 +774,8 @@ def bar(self, a: 'a.A'): ... # File main.py - from a import A - from b import B + from models.a import A + from models.b import B Union types @@ -790,31 +833,26 @@ to a variable (or used as a return value) of a more constrained type. -Predefined constants --------------------- +Version and platform checking +----------------------------- -Some predefined Boolean constants are defined in the ``typing`` -module to enable platform-specific type definitions and such:: +Type checkers are expected to understand simple version and platform +checks, e.g.:: - from typing import PY2, PY3, WINDOWS, POSIX + import sys - if PY2: - text = unicode + if sys.version_info[0] >= 3: + # Python 3 specific definitions else: - text = str + # Python 2 specific definitions - def f() -> text: ... + if sys.platform == 'win32': + # Windows specific definitions + else: + # Posix specific definitions - if WINDOWS: - loop = ProactorEventLoop - else: - loop = UnixSelectorEventLoop - -It is up to the type checker implementation to define their values, as -long as ``PY2 == not PY3`` and ``WINDOWS == not POSIX``. When the -program is being executed these always reflect the current platform, -and this is also the suggested default when the program is being -type-checked. +Don't expect a checker to understand obfuscations like +``"".join(reversed(sys.platform)) == "xunil"``. Default argument values @@ -942,7 +980,7 @@ # We only get here if there's at least one string in a return cast(str, a[index]) -Some type checkers may not be able to infers that the type of +Some type checkers may not be able to infer that the type of ``a[index]`` is ``str`` and only infer ``object`` or ``Any``", but we know that (if the code gets to that point) it must be a string. The ``cast(t, x)`` call tells the type checker that we are confident that @@ -1010,20 +1048,21 @@ from typing import overload class bytes: - ... - @overload - def __getitem__(self, i: int) -> int: ... - @overload - def __getitem__(self, s: slice) -> bytes: ... + ... + @overload + def __getitem__(self, i: int) -> int: ... + @overload + def __getitem__(self, s: slice) -> bytes: ... This description is more precise than would be possible using unions (which cannot express the relationship between the argument and return types):: from typing import Union + class bytes: - ... - def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: ... + ... + def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: ... Another example where ``@overload`` comes in handy is the type of the builtin ``map()`` function, which takes a different number of @@ -1064,6 +1103,35 @@ stub files. In the meantime, using the ``@overload`` decorator or calling ``overload()`` directly raises ``RuntimeError``. +A constrained ``TypeVar`` type can often be used instead of using the +``@overload`` decorator. For example, the definitions of ``concat1`` +and ``concat2`` in this stub file are equivalent: + + from typing import TypeVar + + AnyStr = TypeVar('AnyStr', str, bytes) + + def concat1(x: AnyStr, y: AnyStr) -> AnyStr: ... + + @overload + def concat2(x: str, y: str) -> str: ... + @overload + def concat2(x: bytes, y: bytes) -> bytes: ... + +Some functions, such as ``map`` or ``bytes.__getitem__`` above, can't +be represented precisely using type variables. However, unlike +``@overload``, type variables can also be used outside stub files. We +recommend that ``@overload`` is only used in cases where a type +variable is not sufficient, due to its special stub-only status. + +Another important difference between type variables such as ``AnyStr`` +and using ``@overload`` is that the prior can also be used to define +constraints for generic class type parameters. For example, the type +parameter of the generic class ``typing.IO`` is constrained (only +``IO[str]``, ``IO[bytes]`` and ``IO[Any]`` are valid): + + class IO(Generic[AnyStr]): ... + Storing and distributing stub files ----------------------------------- @@ -1162,6 +1230,8 @@ * TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply ``Y = TypeVar('Y')`` (see above for more details) +* Generic, used to create user-defined generic classes + Generic variants of builtin collections: * Dict, used as ``Dict[key_type, value_type]`` @@ -1242,17 +1312,9 @@ * SupportsBytes, to test for ``__bytes__`` -Constants for platform-specific type hinting: +Convenience definitions: -* PY2 - -* PY3, equivalent to ``not PY2`` - -* WINDOWS - -* POSIX, equivalent to ``not WINDOWS`` - -Convenience definitions: +* Optional, defined by ``Optional[t] == Union[t, type(None)]`` * AnyStr, defined as ``TypeVar('AnyStr', str, bytes)`` -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 22 17:24:05 2015 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 22 May 2015 15:24:05 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Updated_version_of_PEP_484=2E?= Message-ID: <20150522152403.126958.70256@psf.io> https://hg.python.org/peps/rev/be41a3975777 changeset: 5872:be41a3975777 user: Guido van Rossum date: Wed May 20 08:26:09 2015 -0700 summary: Updated version of PEP 484. files: pep-0484.txt | 557 +++++++++++++++++++++++++++++--------- 1 files changed, 424 insertions(+), 133 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -9,17 +9,29 @@ Type: Standards Track Content-Type: text/x-rst Created: 29-Sep-2014 -Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015 +Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015 Resolution: Abstract ======== -This PEP introduces a standard syntax for type hints using annotations -(PEP 3107) on function definitions. For example, here is a simple -function whose argument and return type are declared in the -annotations:: +PEP 3107 introduced syntax for function annotations, but the semantics +were deliberately left undefined. There has now been enough 3rd party +usage for static type analysis that the community would benefit from +a standard vocabulary and baseline tools within the standard library. + +This PEP introduces a provisional module to provide these standard +definitions and tools, along with some conventions for situations +where annotations are not available. + +Note that this PEP still explicitly does NOT prevent other uses of +annotations, nor does it require (or forbid) any particular processing +of annotations, even when they conform to this specification. It +simply enables better coordination, as PEP 333 did for web frameworks. + +For example, here is a simple function whose argument and return type +are declared in the annotations:: def greeting(name: str) -> str: return 'Hello ' + name @@ -29,13 +41,17 @@ Instead, the proposal assumes the existence of a separate off-line type checker which users can run over their source code voluntarily. Essentially, such a type checker acts as a very powerful linter. +(While it would of course be possible for individual users to employ +a similar checker at run time for Design By Contract enforcement or +JIT optimization, those tools are not yet as mature.) The proposal is strongly inspired by mypy [mypy]_. For example, the type "sequence of integers" can be written as ``Sequence[int]``. The square brackets mean that no new syntax needs to be added to the -language. The example here uses a custom class ``Sequence``, imported -from a pure-Python module ``typing``. The ``Sequence[int]`` -notation works by implementing ``__getitem__()`` in the metaclass. +language. The example here uses a custom type ``Sequence``, imported +from a pure-Python module ``typing``. The ``Sequence[int]`` notation +works at runtime by implementing ``__getitem__()`` in the metaclass +(but its significance is primarily to an offline type checker). The type system supports unions, generic types, and a special type named ``Any`` which is consistent with (i.e. assignable to and from) all @@ -49,15 +65,16 @@ Rationale and Goals =================== -PEP 3107 added support for arbitrary annotations on parts of a function -definition. Although no meaning was assigned to annotations then, there -has always been an implicit goal to use them for type hinting, which is -listed as the first possible use case in said PEP. +PEP 3107 added support for arbitrary annotations on parts of a +function definition. Although no meaning was assigned to annotations +then, there has always been an implicit goal to use them for type +hinting [gvr-artima]_, which is listed as the first possible use case +in said PEP. -This PEP aims to provide a standard syntax for type annotations, opening -up Python code to easier static analysis and refactoring, potential -runtime type checking, and performance optimizations utilizing type -information. +This PEP aims to provide a standard syntax for type annotations, +opening up Python code to easier static analysis and refactoring, +potential runtime type checking, and (perhaps, in some contexts) +code generation utilizing type information. Of these goals, static analysis is the most important. This includes support for off-line type checkers such as mypy, as well as providing @@ -74,43 +91,43 @@ using decorators or metaclasses. Using type hints for performance optimizations is left as an exercise for the reader. -It should also be emphasized that Python will remain a dynamically +It should also be emphasized that **Python will remain a dynamically typed language, and the authors have no desire to ever make type hints -mandatory, even by convention. +mandatory, even by convention.** -What is checked? -================ +The meaning of annotations +========================== -Any function (or method -- for brevity we won't be repeating this) -with at least one argument or return annotation is checked, unless -type checking is disabled by the ``@no_type_check`` decorator or a -``# type: ignore`` comment (see below). +Any function without annotations should be treated as having the most +general type possible, or ignored, by any type checker. Functions +with the ``@no_type_check`` decorator or with a ``# type: ignore`` +comment should be treated as having no annotations. -A checked function should have annotations for all its arguments and -its return type, with the exception that the ``self`` argument of a -method should not be annotated; it is assumed to have the type of the -containing class. Notably, the return type of ``__init__`` should be -annotated with ``-> None``. +It is recommended but not required that checked functions have +annotations for all arguments and the return type. For a checked +function, the default annotation for arguments and for the return type +is ``Any``. An exception is that the first argument of instance and +class methods does not need to be annotated; it is assumed to have the +type of the containing class for instance methods, and ``type`` for +class methods. -The body of a checked function is checked for consistency with the -given annotations. The annotations are also used to check correctness -of calls appearing in other checked functions. +(Note that the return type of ``__init__`` ought to be annotated with +``-> None``. The reason for this is subtle. If ``__init__`` assumed +a return annotation of ``-> None``, would that mean that an +argument-less, un-annotated ``__init__`` method should still be +type-checked? Rather than leaving this ambiguous or introducing an +exception to the exception, we simply say that ``__init__`` ought to +have a return annotation; the default behavior is thus the same as for +other methods.) -Functions without any annotations (or whose checking is disabled) are -assumed to have type ``Any`` when they are referenced in checked -functions, and this should completely silence complaints from the -checker regarding those references (although a checker may still -request that a type be specified using a cast or a ``# type:`` comment -if a more specific type than ``Any`` is needed for analysis of -subsequent code). +A type checker is expected to check the body of a checked function for +consistency with the given annotations. The annotations may also used +to check correctness of calls appearing in other checked functions. -A type checker should understand decorators; this may require -annotations on decorator definitions. In particular, a type checker -should understand the built-in decorators ``@property``, -``@staticmethod`` and ``@classmethod``. The first argument of a class -method should not be annotated; it is assumed to be a subclass of the -defining class. +Type checkers are expected to attempt to infer as much information as +necessary. The minimum requirement is to handle the builtin +decorators ``@property``, ``@staticmethod`` and ``@classmethod``. Type Definition Syntax @@ -137,17 +154,20 @@ standard library or third-party extension modules), abstract base classes, types available in the ``types`` module, and user-defined classes (including those defined in the standard library or -third-party modules). Annotations for built-in classes (and other -classes at the discretion of the developer) may be placed in stub -files (see below). +third-party modules). + +While annotations are normally the best format for type hints, +there are times when it is more appropriate to represent them +by a special comment, or in a separately distributed interface +file. (See below for examples.) Annotations must be valid expressions that evaluate without raising exceptions at the time the function is defined (but see below for forward references). -The needs of static analysis require that annotations must be simple -enough to be interpreted by static analysis tools. In particular, -dynamically computed types are not acceptable. (This is an +Annotations should be kept simple or static analysis tools may not be +able to interpret the values. For example, dynamically computed types +are unlikely to be understood. (This is an intentionally somewhat vague requirement, specific inclusions and exclusions may be added to future versions of this PEP as warranted by the discussion.) @@ -158,7 +178,7 @@ from ``typing`` (e.g. ``Sequence`` and ``Dict``), type variables, and type aliases. -All newly introducedw names used to support features described in +All newly introduced names used to support features described in following sections (such as ``Any`` and ``Union``) are available in the ``typing`` module. @@ -280,7 +300,10 @@ or two ``bytes`` arguments, but not with a mix of ``str`` and ``bytes`` arguments. -Note that subtypes of types constrained by a type variable are treated +There should be at least two constraints, if any; specifying a single +constraint is disallowed. + +Subtypes of types constrained by a type variable should be treated as their respective explicitly listed base types in the context of the type variable. Consider this example:: @@ -374,6 +397,35 @@ class LinkedList(Sized, Generic[T]): ... +Subclassing a generic class without specifying type parameters assumes +``Any`` for each position. In the following example, ``MyIterable`` +is not generic but implicitly inherits from ``Iterable[Any]``: + + from typing import Iterable + + class MyIterable(Iterable): # Same as Iterable[Any] + ... + + +Instantiating generic classes and type erasure +---------------------------------------------- + +Generic types like ``List`` or ``Sequence`` cannot be instantiated. +However, user-defined classes derived from them can be instantiated. +Given a generic class ``Node[T]`` there are three forms of +instantiation: + +* ``x = Node()`` -- the type of x is ``Node[Any]``. + +* ``x = Node[T]()`` -- the type of x is ``Node[T]``. + +* ``x = Node[int]()`` -- the type of x is ``Node[int]``. + +At runtime the type is not preserved, and the observable type of x is +just ``Node``. This is type erasure and common practice in languages +with generics (e.g. Java, Typescript). + + Arbitrary generic types as base classes --------------------------------------- @@ -421,6 +473,17 @@ multiple times in the base class list, as long as we don't use the same type variable ``T`` multiple times within ``Generic[...]``. +Also consider the following example:: + + from typing import TypeVar, Mapping + + T = TypeVar('T') + + class MyDict(Mapping[str, T]): + ... + +In this case MyDict has a single parameter, T. + Abstract generic types ---------------------- @@ -431,6 +494,164 @@ classes without a metaclass conflict. +Type variables with an upper bound +---------------------------------- + +A type variable may specify an upper bound using ``bound=``. +This means that an actual type substituted (explicitly or implictly) +for the type variable must be a subclass of the boundary type. A +common example is the definition of a Comparable type that works well +enough to catch the most common errors:: + + from typing import TypeVar + + class Comparable(metaclass=ABCMeta): + @abstractmethod + def __lt__(self, other: Any) -> bool: ... + ... # __gt__ etc. as well + + CT = TypeVar('CT', bound=Comparable) + + def min(x: CT, y: CT) -> CT: + if x < y: + return x + else: + return y + + min(1, 2) # ok, return type int + min('x', 'y') # ok, return type str + +(Note that this is not ideal -- for example ``min('x', 1)`` is invalid +at runtime but a type checker would simply infer the return type +``Comparable``. Unfortunately, addressing this would require +introducing a much more powerful and also much more complicated +concept, F-bounded polymorphism. We may revisit this in the future.) + +An upper bound cannot be combined with type constraints (as in used +``AnyStr``, see the example earlier); type constraints cause the +inferred type to be _exactly_ one of the constraint types, while an +upper bound just requires that the actual type is a subclass of the +boundary type. + + +Covariance and contravariance +----------------------------- + +Consider a class ``Employee`` with a subclass ``Manager``. Now +suppose we have a function with an argument annotated with +``List[Employee]``. Should we be allowed to call this function with a +variable of type ``List[Manager]`` as its argument? Many people would +answer "yes, of course" without even considering the consequences. +But unless we know more about the function, a type checker should +reject such a call: the function might append an ``Employee`` instance +to the list, which would violate the variable's type in the caller. + +It turns out such an argument acts _contravariantly_, whereas the +intuitive answer (which is correct in case the function doesn't mutate +its argument!) requires the argument to act _covariantly_. A longer +introduction to these concepts can be found on Wikipedia +[wiki-variance]_; here we just show how to control a type checker's +behavior. + +By default type variables are considered _invariant_, which means that +arguments for arguments annotated with types like ``List[Employee]`` +must exactly match the type annotation -- no subclasses or +superclasses of the type parameter (in this example ``Employee``) are +allowed. + +To facilitate the declaration of container types where covariant type +checking is acceptable, a type variable can be declared using +``covariant=True``. For the (rare) case where contravariant behavior +is desirable, pass ``contravariant=True``. At most one of these may +be passed. + +A typical example involves defining an immutable container class:: + + from typing import TypeVar + + T = TypeVar('T', covariant=True) + + class ImmutableList(Generic[T]): + def append(self, T): ... + ... + + class Employee: ... + + class Manager(Employee): ... + + def dump_employees(emps: ImmutableList[Employee]) -> None: ... + + mgrs = ... # type: ImmutableList[Mananger] + mgrs.append(Manager()) + + dump_employees(mgrs) # OK + +The immutable collection classes in ``typing`` are all defined using a +covariant type variable (e.g. ``Mapping`` and ``Sequence``). The +mutable collection classes (e.g. ``MutableMapping`` and +``MutableSequence``) are defined using regular invariant type +variables. The one example of a contravariant type variable is the +``Generator`` type, which is contravariant in the ``send()`` argument +type (see below). + +Note: variance affects type parameters for generic types -- it does +not affect regular parameters. For example, the following example is +fine:: + + from typing import TypeVar + + class Employee: ... + + class Manager(Employee): ... + + E = TypeVar('E', bound=Employee) # Invariant + + def dump_employee(e: E) -> None: ... + + dump_employee(Manager()) # OK + + +The numeric tower +----------------- + +PEP 3141 defines Python's numeric tower, and the stdlib module +``numbers`` implements the corresponding ABCs (``Number``, +``Complex``, ``Real``, ``Rational`` and ``Integral``). There are some +issues with these ABCs, but the built-in concrete numeric classes +``complex``, ``float`` and ``int`` are ubiquitous (especially the +latter two :-). + +Rather than requiring that users write ``import numbers`` and then use +``numbers.Float`` etc., this PEP proposes a straightforward shortcut +that is almost as effective: when an argument is annotated as having +type ``float``, an argument of type ``int`` is acceptable; similar, +for an argument annotated as having type ``complex``, arguments of +type ``float`` or ``int`` are acceptable. This does not handle +classes implementing the corresponding ABCs or the +``fractions.Fraction`` class, but we believe those use cases are +exceedingly rare. + + +The bytes types +--------------- + +There are three different builtin classes used for arrays of bytes +(not counting the classes available in the ``array`` module): +``bytes``, ``bytearray`` and ``memoryview``. Of these, ``bytes`` and +``bytearray`` have many behaviors in common (though not all -- +``bytearray`` is mutable). + +While there is an ABC ``ByteString`` defined in ``collections.abc`` +and a corresponding type in ``typing``, functions accepting bytes (of +some form) are so common that it would be cumbersome to have to write +``typing.ByteString`` everywhere. So, as a shortcut similar to that +for the builtin numeric classes, when an argument is annotated as +having type ``bytes``, arguments of type ``bytearray`` or +``memoryview`` are acceptable. (Again, there are situations where +this isn't sound, but we believe those are exceedingly rare in +practice.) + + Forward references ------------------ @@ -529,8 +750,8 @@ ... A type factored by ``Union[T1, T2, ...]`` responds ``True`` to -``issubclass`` checks for ``T1`` and any of its subclasses, ``T2`` and -any of its subclasses, and so on. +``issubclass`` checks for ``T1`` and any of its subtypes, ``T2`` and +any of its subtypes, and so on. One common case of union types are *optional* types. By default, ``None`` is an invalid value for any type, unless a default value of @@ -557,8 +778,8 @@ The ``Any`` type ---------------- -A special kind of type is ``Any``. Every class is a subclass of -``Any``. This is also true for the builtin class ``object``. +A special kind of type is ``Any``. Every type is a subtype of +``Any``. This is also true for the builtin type ``object``. However, to the static type checker these are completely different. When the type of a value is ``object``, the type checker will reject @@ -596,6 +817,22 @@ type-checked. +Default argument values +----------------------- + +In stubs it may be useful to declare an argument as having a default +without specifying the actual default value. For example:: + + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... + +What should the default value look like? Any of the options ``""``, +``b""`` or ``None`` fails to satisfy the type constraint (actually, +``None`` will *modify* the type to become ``Optional[AnyStr]``). + +In such cases the default value may be specified as a literal +ellipsis, i.e. the above example is literally what you would write. + + Compatibility with other uses of function annotations ===================================================== @@ -655,6 +892,28 @@ # Here x and y are floats ... +In stubs it may be useful to declare the existence of a variable +without giving it an initial value. This can be done using a literal +ellipsis:: + + from typing import IO + + stream = ... # type: IO[str] + +In non-stub code, there is a similar special case: + + from typing import IO + + stream = None # type: IO[str] + +Type checkers should not complain about this (despite the value +``None`` not matching the given type), nor should they change the +inferred type to ``Optional[...]`` (despite the rule that does this +for annotated arguments with a default value of ``None``). The +assumption here is that other code will ensure that the variable is +given a value of the proper type, and all uses can assume that the +variable has the given type. + The ``# type: ignore`` comment should be put on the line that the error refers to:: @@ -674,7 +933,7 @@ Occasionally the type checker may need a different kind of hint: the programmer may know that an expression is of a more constrained type -than the type checker infers. For example:: +than a type checker may be able to infer. For example:: from typing import List, cast @@ -683,7 +942,8 @@ # We only get here if there's at least one string in a return cast(str, a[index]) -The type checker infers the type ``object`` for ``a[index]``, but we +Some type checkers may not be able to infers that the type of +``a[index]`` is ``str`` and only infer ``object`` or ``Any``", but we know that (if the code gets to that point) it must be a string. The ``cast(t, x)`` call tells the type checker that we are confident that the type of ``x`` is ``t``. At runtime a cast always returns the @@ -720,8 +980,8 @@ the ``@overload`` decorator described below. The type checker should only check function signatures in stub files; -function bodies in stub files should just be a single ``pass`` -statement. +It is recommended that function bodies in stub files just be a single +ellipsis (``...``). The type checker should have a configurable search path for stub files. If a stub file is found the type checker should not read the @@ -732,6 +992,12 @@ same directory as the corresponding real module. This also reinforces the notion that no runtime behavior should be expected of stub files. +Additional notes on stub files: + +* Modules and variables imported into the stub are not considered + exported from the stub unless the import uses the ``import ... as + ...`` form. + Function overloading -------------------- @@ -746,9 +1012,9 @@ class bytes: ... @overload - def __getitem__(self, i: int) -> int: pass + def __getitem__(self, i: int) -> int: ... @overload - def __getitem__(self, s: slice) -> bytes: pass + def __getitem__(self, s: slice) -> bytes: ... This description is more precise than would be possible using unions (which cannot express the relationship between the argument and return @@ -757,7 +1023,7 @@ from typing import Union class bytes: ... - def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: pass + def __getitem__(self, a: Union[int, slice]) -> Union[int, bytes]: ... Another example where ``@overload`` comes in handy is the type of the builtin ``map()`` function, which takes a different number of @@ -770,20 +1036,20 @@ S = TypeVar('S') @overload - def map(func: Callable[[T1], S], iter1: Iterable[T1]) -> Iterator[S]: pass + def map(func: Callable[[T1], S], iter1: Iterable[T1]) -> Iterator[S]: ... @overload def map(func: Callable[[T1, T2], S], - iter1: Iterable[T1], iter2: Iterable[T2]) -> Iterator[S]: pass + iter1: Iterable[T1], iter2: Iterable[T2]) -> Iterator[S]: ... # ... and we could add more items to support more than two iterables Note that we could also easily add items to support ``map(None, ...)``:: @overload - def map(func: None, iter1: Iterable[T1]) -> Iterable[T1]: pass + def map(func: None, iter1: Iterable[T1]) -> Iterable[T1]: ... @overload def map(func: None, iter1: Iterable[T1], - iter2: Iterable[T2]) -> Iterable[Tuple[T1, T2]]: pass + iter2: Iterable[T2]) -> Iterable[Tuple[T1, T2]]: ... The ``@overload`` decorator may only be used in stub files. While it would be possible to provide a multiple dispatch implementation using @@ -795,7 +1061,8 @@ "Alternative approaches".) In the future we may come up with a satisfactory multiple dispatch design, but we don't want such a design to be constrained by the overloading syntax defined for type hints in -stub files. +stub files. In the meantime, using the ``@overload`` decorator or +calling ``overload()`` directly raises ``RuntimeError``. Storing and distributing stub files ----------------------------------- @@ -827,8 +1094,8 @@ package, using the "latest" stub files should generally also work if they're updated often. -Third-party stub packages can use any location for stub storage. The -type checker will search for them using PYTHONPATH. A default fallback +Third-party stub packages can use any location for stub storage. Type +checkers should search for them using PYTHONPATH. A default fallback directory that is always checked is ``shared/typehints/python3.5/`` (or 3.6, etc.). Since there can only be one package installed for a given Python version per environment, no additional versioning is performed @@ -845,6 +1112,16 @@ ], ... +The Typeshed Repo +----------------- + +There is a shared repository where useful stubs are being collected +[typeshed]_. Note that stubs for a given package will not be included +here without the explicit consent of the package owner. Further +policies regarding the stubs collected here will be decided at a later +time, after discussion on python-dev, and reported in the typeshed +repo's README. + Exceptions ========== @@ -860,8 +1137,32 @@ To open the usage of static type checking to Python 3.5 as well as older versions, a uniform namespace is required. For this purpose, a new -module in the standard library is introduced called ``typing``. It -holds a set of classes representing builtin types with generics, namely: +module in the standard library is introduced called ``typing``. + +It defines the fundamental building blocks for constructing types +(e.g. ``Any``), types representing generic variants of builtin +collections (e.g. ``List``), types representing generic +collection ABCs (e.g. ``Sequence``), and a small collection of +convenience definitions. + +Fundamental building blocks: + +* Any, used as ``def get(key: str) -> Any: ...`` + +* Union, used as ``Union[Type1, Type2, Type3]`` + +* Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]`` + +* Tuple, used by listing the element types, for example + ``Tuple[int, int, str]``. + Arbitrary-length homogeneous tuples can be expressed + using one type and ellipsis, for example ``Tuple[int, ...]``. + (The ``...`` here are part of the syntax, a literal ellipsis.) + +* TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply + ``Y = TypeVar('Y')`` (see above for more details) + +Generic variants of builtin collections: * Dict, used as ``Dict[key_type, value_type]`` @@ -872,53 +1173,28 @@ * FrozenSet, used as ``FrozenSet[element_type]`` -* Tuple, used by listing the element types, for example - ``Tuple[int, int, str]``. - Arbitrary-length homogeneous tuples can be expressed - using one type and ellipsis, for example ``Tuple[int, ...]``. - (The ``...`` here are part of the syntax.) +Note: ``Dict``, ``List``, ``Set`` and ``FrozenSet`` are mainly useful +for annotating return values. For arguments, prefer the abstract +collection types defined below, e.g. ``Mapping``, ``Sequence`` or +``AbstractSet``. -* NamedTuple, used as - ``NamedTuple(type_name, [(field_name, field_type), ...])`` - and equivalent to - ``collections.namedtuple(type_name, [field_name, ...])``. - -The generic versions of concrete collection types (``Dict``, ``List``, -``Set``, ``FrozenSet``, and homogeneous arbitrary-length ``Tuple``) -are mainly useful for annotating return values. For arguments, prefer -the abstract collection types defined below, e.g. ``Mapping``, -``Sequence`` or ``AbstractSet``. - -The ``typing`` module defines the ``Generator`` type for return values -of generator functions. It is a subtype of ``Iterable`` and it has -additional type variables for the type accepted by the ``send()`` -method and the return type of the generator: - -* Generator, used as ``Generator[yield_type, send_type, return_type]`` - -It also introduces factories and helper members needed to express -generics and union types: - -* Any, used as ``def get(key: str) -> Any: ...`` - -* Union, used as ``Union[Type1, Type2, Type3]`` - -* TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply - ``Y = TypeVar('Y')`` - -* Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]`` - -* AnyStr, defined as ``TypeVar('AnyStr', str, bytes)`` - -All abstract base classes available in ``collections.abc`` are -importable from the ``typing`` module, with added generics support: +Generic variants of container ABCs (and a few non-containers): * ByteString -* Callable (see above) +* Callable (see above, listed here for completeness) * Container +* Generator, used as ``Generator[yield_type, send_type, + return_type]``. This represents the return value of generator + functions. It is a subtype of ``Iterable`` and it has additional + type variables for the type accepted by the ``send()`` method (which + is contravariant -- a generator that accepts sending it ``Employee`` + instance is valid in a context where a generator is required that + accepts sending it ``Manager`` instances) and the return type of the + generator. + * Hashable (not generic, but present for completeness) * ItemsView @@ -956,13 +1232,17 @@ * SupportsAbs, to test for ``__abs__`` +* SupportsComplex, to test for ``__complex__`` + * SupportsFloat, to test for ``__float__`` * SupportsInt, to test for ``__int__`` * SupportsRound, to test for ``__round__`` -The library includes literals for platform-specific type hinting: +* SupportsBytes, to test for ``__bytes__`` + +Constants for platform-specific type hinting: * PY2 @@ -972,41 +1252,46 @@ * POSIX, equivalent to ``not WINDOWS`` -The following conveniece functions and decorators are exported: +Convenience definitions: -* cast, described earlier +* AnyStr, defined as ``TypeVar('AnyStr', str, bytes)`` -* no_type_check, a decorator to disable type checking per class or +* NamedTuple, used as + ``NamedTuple(type_name, [(field_name, field_type), ...])`` + and equivalent to + ``collections.namedtuple(type_name, [field_name, ...])``. + This is useful to declare the types of the fields of a a named tuple + type. + +* cast(), described earlier + +* @no_type_check, a decorator to disable type checking per class or function (see below) -* no_type_check_decorator, a decorator to create your own decorators +* @no_type_check_decorator, a decorator to create your own decorators with the same meaning as ``@no_type_check`` (see below) -* overload, described earlier +* @overload, described earlier -* get_type_hints, a utility function to retrieve the type hints from a +* get_type_hints(), a utility function to retrieve the type hints from a function or method. Given a function or method object, it returns a dict with the same format as ``__annotations__``, but evaluating forward references (which are given as string literals) as expressions in the context of the original function or method definition. -The following types are available in the ``typing.io`` module: +Types available in the ``typing.io`` submodule: * IO (generic over ``AnyStr``) -* BinaryIO (a simple subclass of ``IO[bytes]``) +* BinaryIO (a simple subtype of ``IO[bytes]``) -* TextIO (a simple subclass of ``IO[str]``) +* TextIO (a simple subtype of ``IO[str]``) -The following types are provided by the ``typing.re`` module: +Types available in the ``typing.re`` submodule: * Match and Pattern, types of ``re.match()`` and ``re.compile()`` results (generic over ``AnyStr``) -As a convenience measure, types from ``typing.io`` and ``typing.re`` are -also available in ``typing`` (quoting Guido, "There's a reason those -modules have two-letter names."). - Rejected Alternatives ===================== @@ -1025,7 +1310,7 @@ express the parametrization of generic types. The problem with these is that they are really hard to parse, especially for a simple-minded parser like Python. In most languages the ambiguities are usually -dealy with by only allowing angular brackets in specific syntactic +dealt with by only allowing angular brackets in specific syntactic positions, where general expressions aren't allowed. (And also by using very powerful parsing techniques that can backtrack over an arbitrary section of code.) @@ -1187,7 +1472,7 @@ well known from other programming languages. But this use of ``::`` is unheard of in English, and in other languages (e.g. C++) it is used as a scoping operator, which is a very different beast. In - contrast, the single colon for type hints reads natural -- and no + contrast, the single colon for type hints reads naturally -- and no wonder, since it was carefully designed for this purpose (the idea long predates PEP 3107 [gvr-artima]_). It is also used in the same fashion in other languages from Pascal to Swift. @@ -1286,15 +1571,21 @@ .. [mypy] http://mypy-lang.org +.. [gvr-artima] + http://www.artima.com/weblogs/viewpost.jsp?thread=85551 + +.. [wiki-variance] + http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29 + +.. [typeshed] + https://github.com/JukkaL/typeshed/ + .. [pyflakes] https://github.com/pyflakes/pyflakes/ .. [pylint] http://www.pylint.org -.. [gvr-artima] - http://www.artima.com/weblogs/viewpost.jsp?thread=85551 - .. [roberge] http://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 22 17:30:50 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 15:30:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_docs=3A_Mention_PEP_479_in?= =?utf-8?q?_whatsnew=2E?= Message-ID: <20150522153050.16301.19551@psf.io> https://hg.python.org/cpython/rev/c8a3e49f35e7 changeset: 96207:c8a3e49f35e7 user: Yury Selivanov date: Fri May 22 11:30:45 2015 -0400 summary: docs: Mention PEP 479 in whatsnew. Issue 22906. files: Doc/whatsnew/3.5.rst | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -209,6 +209,27 @@ :pep:`475` -- Retry system calls failing with EINTR +PEP 479: Change StopIteration handling inside generators +-------------------------------------------------------- + +:pep:`479` changes the behavior of generators: when a :exc:`StopIteration` +exception is raised inside a generator, it is replaced with a +:exc:`RuntimeError`. To enable the feature a ``__future__`` import should +be used:: + + from __future__ import generator_stop + +Without a ``__future__`` import, a :exc:`PendingDeprecationWarning` will be +raised. + +PEP written by Chris Angelico and Guido van Rossum. Implemented by +Chris Angelico, Yury Selivanov and Nick Coghlan. + +.. seealso:: + + :pep:`479` -- Change StopIteration handling inside generators + + PEP 486: Make the Python Launcher aware of virtual environments --------------------------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 17:39:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 15:39:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_20438=3A_Deprecate_i?= =?utf-8?q?nspect=2Egetargspec=28=29_and_friends=2E?= Message-ID: <20150522153900.16715.69503@psf.io> https://hg.python.org/cpython/rev/3a5fec5e025d changeset: 96208:3a5fec5e025d user: Yury Selivanov date: Fri May 22 11:38:38 2015 -0400 summary: Issue 20438: Deprecate inspect.getargspec() and friends. files: Doc/library/inspect.rst | 13 +++++++------ Lib/inspect.py | 5 ++++- Lib/test/test_inspect.py | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -815,15 +815,16 @@ The first four items in the tuple correspond to :func:`getargspec`. - .. note:: - Consider using the new :ref:`Signature Object ` - interface, which provides a better way of introspecting functions. - .. versionchanged:: 3.4 This function is now based on :func:`signature`, but still ignores ``__wrapped__`` attributes and includes the already bound first parameter in the signature output for bound methods. + .. deprecated:: 3.5 + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. + .. function:: getargvalues(frame) @@ -896,8 +897,8 @@ .. versionadded:: 3.2 - .. note:: - Consider using the new :meth:`Signature.bind` instead. + .. deprecated:: 3.5 + Use :meth:`Signature.bind` and :meth:`Signature.bind_partial` instead. .. function:: getclosurevars(func) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1033,7 +1033,8 @@ and keyword arguments are supported. getargspec() will raise ValueError if the func has either annotations or keyword arguments. """ - + warnings.warn("inspect.getargspec() is deprecated, " + "use inspect.signature() instead", DeprecationWarning) args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ getfullargspec(func) if kwonlyargs or ann: @@ -1057,6 +1058,8 @@ 'annotations' is a dictionary mapping argument names to annotations. The first four items in the tuple correspond to getargspec(). + + This function is deprecated, use inspect.signature() instead. """ try: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -631,7 +631,8 @@ def assertArgSpecEquals(self, routine, args_e, varargs_e=None, varkw_e=None, defaults_e=None, formatted=None): - args, varargs, varkw, defaults = inspect.getargspec(routine) + with self.assertWarns(DeprecationWarning): + args, varargs, varkw, defaults = inspect.getargspec(routine) self.assertEqual(args, args_e) self.assertEqual(varargs, varargs_e) self.assertEqual(varkw, varkw_e) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 18:37:13 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 22 May 2015 16:37:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320035=3A_Reimplem?= =?utf-8?q?ent_tkinter=2E=5Ffix_module_as_a_C_function=2E?= Message-ID: <20150522163713.26094.65588@psf.io> https://hg.python.org/cpython/rev/951318b651be changeset: 96209:951318b651be user: Zachary Ware date: Fri May 22 11:36:53 2015 -0500 summary: Issue #20035: Reimplement tkinter._fix module as a C function. The new private C function makes no permanent changes to the environment and is #ifdef'd out on non-Windows platforms. files: Doc/whatsnew/3.5.rst | 10 +- Lib/test/test_tcl.py | 4 +- Lib/test/test_tk.py | 3 - Lib/test/test_ttk_guionly.py | 4 +- Lib/test/test_ttk_textonly.py | 3 - Lib/tkinter/__init__.py | 3 - Lib/tkinter/_fix.py | 78 -------------- Misc/NEWS | 4 + Modules/_tkinter.c | 119 +++++++++++++++++++++- PCbuild/_tkinter.vcxproj | 1 + Tools/buildbot/test-amd64.bat | 2 - Tools/buildbot/test.bat | 2 - 12 files changed, 134 insertions(+), 99 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1,4 +1,4 @@ -**************************** +?**************************** What's New In Python 3.5 **************************** @@ -659,6 +659,14 @@ * The :func:`time.monotonic` function is now always available. (Contributed by Victor Stinner in :issue:`22043`.) +tkinter +------- + +* The :module:`tkinter._fix` module used for setting up the Tcl/Tk environment + on Windows has been replaced by a private function in the :module:`_tkinter` + module which makes no permanent changes to environment variables. + (Contributed by Zachary Ware in :issue:`20035`.) + types ----- diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -7,9 +7,7 @@ # Skip this test if the _tkinter module wasn't built. _tkinter = support.import_module('_tkinter') -# Make sure tkinter._fix runs to set up the environment -tkinter = support.import_fresh_module('tkinter') - +import tkinter from tkinter import Tcl from _tkinter import TclError diff --git a/Lib/test/test_tk.py b/Lib/test/test_tk.py --- a/Lib/test/test_tk.py +++ b/Lib/test/test_tk.py @@ -2,9 +2,6 @@ # Skip test if _tkinter wasn't built. support.import_module('_tkinter') -# Make sure tkinter._fix runs to set up the environment -support.import_fresh_module('tkinter') - # Skip test if tk cannot be initialized. support.requires('gui') diff --git a/Lib/test/test_ttk_guionly.py b/Lib/test/test_ttk_guionly.py --- a/Lib/test/test_ttk_guionly.py +++ b/Lib/test/test_ttk_guionly.py @@ -5,12 +5,10 @@ # Skip this test if _tkinter wasn't built. support.import_module('_tkinter') -# Make sure tkinter._fix runs to set up the environment -tkinter = support.import_fresh_module('tkinter') - # Skip test if tk cannot be initialized. support.requires('gui') +import tkinter from _tkinter import TclError from tkinter import ttk from tkinter.test import runtktests diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -4,9 +4,6 @@ # Skip this test if _tkinter does not exist. support.import_module('_tkinter') -# Make sure tkinter._fix runs to set up the environment -support.import_fresh_module('tkinter') - from tkinter.test import runtktests def test_main(): diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -31,9 +31,6 @@ """ import sys -if sys.platform == "win32": - # Attempt to configure Tcl/Tk without requiring PATH - from tkinter import _fix import _tkinter # If this fails your Python may not be configured for Tk TclError = _tkinter.TclError diff --git a/Lib/tkinter/_fix.py b/Lib/tkinter/_fix.py deleted file mode 100644 --- a/Lib/tkinter/_fix.py +++ /dev/null @@ -1,78 +0,0 @@ -import sys, os - -# Delay import _tkinter until we have set TCL_LIBRARY, -# so that Tcl_FindExecutable has a chance to locate its -# encoding directory. - -# Unfortunately, we cannot know the TCL_LIBRARY directory -# if we don't know the tcl version, which we cannot find out -# without import Tcl. Fortunately, Tcl will itself look in -# \..\tcl, so anything close to -# the real Tcl library will do. - -# Expand symbolic links on Vista -try: - import ctypes - ctypes.windll.kernel32.GetFinalPathNameByHandleW -except (ImportError, AttributeError): - def convert_path(s): - return s -else: - def convert_path(s): - if isinstance(s, bytes): - s = s.decode("mbcs") - hdir = ctypes.windll.kernel32.\ - CreateFileW(s, 0x80, # FILE_READ_ATTRIBUTES - 1, # FILE_SHARE_READ - None, 3, # OPEN_EXISTING - 0x02000000, # FILE_FLAG_BACKUP_SEMANTICS - None) - if hdir == -1: - # Cannot open directory, give up - return s - buf = ctypes.create_unicode_buffer("", 32768) - res = ctypes.windll.kernel32.\ - GetFinalPathNameByHandleW(hdir, buf, len(buf), - 0) # VOLUME_NAME_DOS - ctypes.windll.kernel32.CloseHandle(hdir) - if res == 0: - # Conversion failed (e.g. network location) - return s - s = buf[:res] - # Ignore leading \\?\ - if s.startswith("\\\\?\\"): - s = s[4:] - if s.startswith("UNC"): - s = "\\" + s[3:] - return s - -prefix = os.path.join(sys.base_prefix,"tcl") -if not os.path.exists(prefix): - # devdir/externals/tcltk/lib - prefix = os.path.join(sys.base_prefix, "externals", "tcltk", "lib") - prefix = os.path.abspath(prefix) -# if this does not exist, no further search is needed -if os.path.exists(prefix): - prefix = convert_path(prefix) - if "TCL_LIBRARY" not in os.environ: - for name in os.listdir(prefix): - if name.startswith("tcl"): - tcldir = os.path.join(prefix,name) - if os.path.isdir(tcldir): - os.environ["TCL_LIBRARY"] = tcldir - # Compute TK_LIBRARY, knowing that it has the same version - # as Tcl - import _tkinter - ver = str(_tkinter.TCL_VERSION) - if "TK_LIBRARY" not in os.environ: - v = os.path.join(prefix, 'tk'+ver) - if os.path.exists(os.path.join(v, "tclIndex")): - os.environ['TK_LIBRARY'] = v - # We don't know the Tix version, so we must search the entire - # directory - if "TIX_LIBRARY" not in os.environ: - for name in os.listdir(prefix): - if name.startswith("tix"): - tixdir = os.path.join(prefix,name) - if os.path.isdir(tixdir): - os.environ["TIX_LIBRARY"] = tixdir diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,6 +58,10 @@ Library ------- +- Issue #20035: Replaced the ``tkinter._fix`` module used for setting up the + Tcl/Tk environment on Windows with a private function in the ``_tkinter`` + module that makes no permanent changes to the environment. + - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -101,7 +101,65 @@ #ifdef MS_WINDOWS #include #define WAIT_FOR_STDIN + +static PyObject * +_get_tcl_lib_path() +{ + static PyObject *tcl_library_path = NULL; + static int already_checked = 0; + + if (already_checked == 0) { + PyObject *prefix; + struct stat stat_buf; + int stat_return_value; + + prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1); + if (prefix == NULL) { + return NULL; + } + + /* Check expected location for an installed Python first */ + tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION); + if (tcl_library_path == NULL) { + return NULL; + } + tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path); + if (tcl_library_path == NULL) { + return NULL; + } + stat_return_value = _Py_stat(tcl_library_path, &stat_buf); + if (stat_return_value == -2) { + return NULL; + } + if (stat_return_value == -1) { + /* install location doesn't exist, reset errno and see if + we're a repository build */ + errno = 0; +#ifdef Py_TCLTK_DIR + tcl_library_path = PyUnicode_FromString( + Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION); + if (tcl_library_path == NULL) { + return NULL; + } + stat_return_value = _Py_stat(tcl_library_path, &stat_buf); + if (stat_return_value == -2) { + return NULL; + } + if (stat_return_value == -1) { + /* tcltkDir for a repository build doesn't exist either, + reset errno and leave Tcl to its own devices */ + errno = 0; + tcl_library_path = NULL; + } +#else + tcl_library_path = NULL; #endif + } + already_checked = 1; + } + return tcl_library_path; +} +#endif /* MS_WINDOWS */ #ifdef WITH_THREAD @@ -681,6 +739,33 @@ PyMem_Free(args); } +#ifdef MS_WINDOWS + { + PyObject *str_path; + PyObject *utf8_path; + DWORD ret; + + ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0); + if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { + str_path = _get_tcl_lib_path(); + if (str_path == NULL && PyErr_Occurred()) { + return NULL; + } + if (str_path != NULL) { + utf8_path = PyUnicode_AsUTF8String(str_path); + if (utf8_path == NULL) { + return NULL; + } + Tcl_SetVar(v->interp, + "tcl_library", + PyBytes_AsString(utf8_path), + TCL_GLOBAL_ONLY); + Py_DECREF(utf8_path); + } + } + } +#endif + if (Tcl_AppInit(v->interp) != TCL_OK) { PyObject *result = Tkinter_Error((PyObject *)v); #ifdef TKINTER_PROTECT_LOADTK @@ -3517,8 +3602,40 @@ uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1); if (uexe) { cexe = PyUnicode_EncodeFSDefault(uexe); - if (cexe) + if (cexe) { +#ifdef MS_WINDOWS + int set_var = 0; + PyObject *str_path; + wchar_t *wcs_path; + DWORD ret; + + ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0); + + if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { + str_path = _get_tcl_lib_path(); + if (str_path == NULL && PyErr_Occurred()) { + return NULL; + } + if (str_path != NULL) { + wcs_path = PyUnicode_AsWideCharString(str_path, NULL); + if (wcs_path == NULL) { + return NULL; + } + SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path); + set_var = 1; + } + } + Tcl_FindExecutable(PyBytes_AsString(cexe)); + + if (set_var) { + SetEnvironmentVariableW(L"TCL_LIBRARY", NULL); + PyMem_Free(wcs_path); + } +#else + Tcl_FindExecutable(PyBytes_AsString(cexe)); +#endif /* MS_WINDOWS */ + } Py_XDECREF(cexe); Py_DECREF(uexe); } diff --git a/PCbuild/_tkinter.vcxproj b/PCbuild/_tkinter.vcxproj --- a/PCbuild/_tkinter.vcxproj +++ b/PCbuild/_tkinter.vcxproj @@ -63,6 +63,7 @@ $(tcltkDir)include;%(AdditionalIncludeDirectories) WITH_APPINIT;%(PreprocessorDefinitions) + Py_TCLTK_DIR="$(tcltkDir.TrimEnd('\').Replace('\', '\\'))";%(PreprocessorDefinitions) $(tcltkLib);%(AdditionalDependencies) diff --git a/Tools/buildbot/test-amd64.bat b/Tools/buildbot/test-amd64.bat --- a/Tools/buildbot/test-amd64.bat +++ b/Tools/buildbot/test-amd64.bat @@ -1,7 +1,5 @@ @rem Used by the buildbot "test" step. setlocal -rem The following line should be removed before #20035 is closed -set TCL_LIBRARY=%~dp0..\..\externals\tcltk64\lib\tcl8.6 call "%~dp0..\..\PCbuild\rt.bat" -d -q -x64 -uall -rwW -n --timeout=3600 %* diff --git a/Tools/buildbot/test.bat b/Tools/buildbot/test.bat --- a/Tools/buildbot/test.bat +++ b/Tools/buildbot/test.bat @@ -1,7 +1,5 @@ @rem Used by the buildbot "test" step. setlocal -rem The following line should be removed before #20035 is closed -set TCL_LIBRARY=%~dp0..\..\externals\tcltk\lib\tcl8.6 call "%~dp0..\..\PCbuild\rt.bat" -d -q -uall -rwW -n --timeout=3600 %* -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 18:42:38 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 22 May 2015 16:42:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_extraneous_BOM_in_what?= =?utf-8?q?snew=2E?= Message-ID: <20150522164236.27943.86472@psf.io> https://hg.python.org/cpython/rev/a8568ea83599 changeset: 96210:a8568ea83599 user: Zachary Ware date: Fri May 22 11:42:20 2015 -0500 summary: Fix extraneous BOM in whatsnew. That's what I get for using Notepad to make a quick edit... files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1,4 +1,4 @@ -?**************************** +**************************** What's New In Python 3.5 **************************** -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 19:14:24 2015 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 22 May 2015 17:14:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Preliminary_typing=2Epy=2C?= =?utf-8?q?_anticipating_provisional_acceptance_of_PEP_484=2E?= Message-ID: <20150522171424.16289.43662@psf.io> https://hg.python.org/cpython/rev/3e96d7ca3f51 changeset: 96211:3e96d7ca3f51 user: Guido van Rossum date: Fri May 22 10:14:11 2015 -0700 summary: Preliminary typing.py, anticipating provisional acceptance of PEP 484. There area bunch of TODOs here, but the biggest (not mentioned in the file) is that I'm going to take out __instancecheck__ and __subclasscheck__. However my personal schedule is such that I probably won't have time for these before Larry tags beta 1. But I will try -- this commit is mostly to make sure that typing.py doesn't completely miss the train. PS. I'm tracking issues at https://github.com/ambv/typehinting/issues. files: Doc/library/typing.rst | 15 + Lib/test/test_typing.py | 1373 +++++++++++++++++++++ Lib/typing.py | 1714 +++++++++++++++++++++++++++ Misc/NEWS | 2 + 4 files changed, 3104 insertions(+), 0 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst new file mode 100644 --- /dev/null +++ b/Doc/library/typing.rst @@ -0,0 +1,15 @@ +:mod:`typing` --- Support for type hints +======================================== + +.. module:: typing + :synopsis: Support for type hints (see PEP 484). + +**Source code:** :source:`Lib/typing.py` + +-------------- + +This module supports type hints as specified by :pep:`484`. The most +fundamental support consists of the type :class:`Any`, :class:`Union`, +:class:`Tuple`, :class:`Callable`, :class:`TypeVar`, and +:class:`Generic`. For full specification please see :pep:`484`. For +a simplified introduction to type hints see :pep:`483`. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_typing.py @@ -0,0 +1,1373 @@ +from collections import namedtuple +import re +import sys +from unittest import TestCase, main +try: + from unittest import mock +except ImportError: + import mock # 3rd party install, for PY3.2. + +from typing import Any +from typing import TypeVar, AnyStr +from typing import T, KT, VT # Not in __all__. +from typing import Union, Optional +from typing import Tuple +from typing import Callable +from typing import Generic +from typing import cast +from typing import get_type_hints +from typing import no_type_check, no_type_check_decorator +from typing import NamedTuple +from typing import IO, TextIO, BinaryIO +from typing import Pattern, Match +import typing + + +class Employee: + pass + + +class Manager(Employee): + pass + + +class Founder(Employee): + pass + + +class ManagingFounder(Manager, Founder): + pass + + +class AnyTests(TestCase): + + def test_any_instance(self): + self.assertIsInstance(Employee(), Any) + self.assertIsInstance(42, Any) + self.assertIsInstance(None, Any) + self.assertIsInstance(object(), Any) + + def test_any_subclass(self): + self.assertTrue(issubclass(Employee, Any)) + self.assertTrue(issubclass(int, Any)) + self.assertTrue(issubclass(type(None), Any)) + self.assertTrue(issubclass(object, Any)) + + def test_others_any(self): + self.assertFalse(issubclass(Any, Employee)) + self.assertFalse(issubclass(Any, int)) + self.assertFalse(issubclass(Any, type(None))) + # However, Any is a subclass of object (this can't be helped). + self.assertTrue(issubclass(Any, object)) + + def test_repr(self): + self.assertEqual(repr(Any), 'typing.Any') + + def test_errors(self): + with self.assertRaises(TypeError): + issubclass(42, Any) + with self.assertRaises(TypeError): + Any[int] # Any is not a generic type. + + def test_cannot_subclass(self): + with self.assertRaises(TypeError): + class A(Any): + pass + + def test_cannot_instantiate(self): + with self.assertRaises(TypeError): + Any() + + def test_cannot_subscript(self): + with self.assertRaises(TypeError): + Any[int] + + def test_any_is_subclass(self): + # Any should be considered a subclass of everything. + assert issubclass(Any, Any) + assert issubclass(Any, typing.List) + assert issubclass(Any, typing.List[int]) + assert issubclass(Any, typing.List[T]) + assert issubclass(Any, typing.Mapping) + assert issubclass(Any, typing.Mapping[str, int]) + assert issubclass(Any, typing.Mapping[KT, VT]) + assert issubclass(Any, Generic) + assert issubclass(Any, Generic[T]) + assert issubclass(Any, Generic[KT, VT]) + assert issubclass(Any, AnyStr) + assert issubclass(Any, Union) + assert issubclass(Any, Union[int, str]) + assert issubclass(Any, typing.Match) + assert issubclass(Any, typing.Match[str]) + # These expressions must simply not fail. + typing.Match[Any] + typing.Pattern[Any] + typing.IO[Any] + + +class TypeVarTests(TestCase): + + def test_basic_plain(self): + T = TypeVar('T') + # Nothing is an instance if T. + with self.assertRaises(TypeError): + isinstance('', T) + # Every class is a subclass of T. + assert issubclass(int, T) + assert issubclass(str, T) + # T equals itself. + assert T == T + # T is a subclass of itself. + assert issubclass(T, T) + + def test_basic_constrained(self): + A = TypeVar('A', str, bytes) + # Nothing is an instance of A. + with self.assertRaises(TypeError): + isinstance('', A) + # Only str and bytes are subclasses of A. + assert issubclass(str, A) + assert issubclass(bytes, A) + assert not issubclass(int, A) + # A equals itself. + assert A == A + # A is a subclass of itself. + assert issubclass(A, A) + + def test_constrained_error(self): + with self.assertRaises(TypeError): + X = TypeVar('X', int) + + def test_union_unique(self): + X = TypeVar('X') + Y = TypeVar('Y') + assert X != Y + assert Union[X] == X + assert Union[X] != Union[X, Y] + assert Union[X, X] == X + assert Union[X, int] != Union[X] + assert Union[X, int] != Union[int] + assert Union[X, int].__union_params__ == (X, int) + assert Union[X, int].__union_set_params__ == {X, int} + + def test_union_constrained(self): + A = TypeVar('A', str, bytes) + assert Union[A, str] != Union[A] + + def test_repr(self): + self.assertEqual(repr(T), '~T') + self.assertEqual(repr(KT), '~KT') + self.assertEqual(repr(VT), '~VT') + self.assertEqual(repr(AnyStr), '~AnyStr') + T_co = TypeVar('T_co', covariant=True) + self.assertEqual(repr(T_co), '+T_co') + T_contra = TypeVar('T_contra', contravariant=True) + self.assertEqual(repr(T_contra), '-T_contra') + + def test_no_redefinition(self): + self.assertNotEqual(TypeVar('T'), TypeVar('T')) + self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str)) + + def test_subclass_as_unions(self): + # None of these are true -- each type var is its own world. + self.assertFalse(issubclass(TypeVar('T', int, str), + TypeVar('T', int, str))) + self.assertFalse(issubclass(TypeVar('T', int, float), + TypeVar('T', int, float, str))) + self.assertFalse(issubclass(TypeVar('T', int, str), + TypeVar('T', str, int))) + A = TypeVar('A', int, str) + B = TypeVar('B', int, str, float) + self.assertFalse(issubclass(A, B)) + self.assertFalse(issubclass(B, A)) + + def test_cannot_subclass_vars(self): + with self.assertRaises(TypeError): + class V(TypeVar('T')): + pass + + def test_cannot_subclass_var_itself(self): + with self.assertRaises(TypeError): + class V(TypeVar): + pass + + def test_cannot_instantiate_vars(self): + with self.assertRaises(TypeError): + TypeVar('A')() + + def test_bound(self): + X = TypeVar('X', bound=Employee) + assert issubclass(Employee, X) + assert issubclass(Manager, X) + assert not issubclass(int, X) + + def test_bound_errors(self): + with self.assertRaises(TypeError): + TypeVar('X', bound=42) + with self.assertRaises(TypeError): + TypeVar('X', str, float, bound=Employee) + + +class UnionTests(TestCase): + + def test_basics(self): + u = Union[int, float] + self.assertNotEqual(u, Union) + self.assertIsInstance(42, u) + self.assertIsInstance(3.14, u) + self.assertTrue(issubclass(int, u)) + self.assertTrue(issubclass(float, u)) + + def test_union_any(self): + u = Union[Any] + self.assertEqual(u, Any) + u = Union[int, Any] + self.assertEqual(u, Any) + u = Union[Any, int] + self.assertEqual(u, Any) + + def test_union_object(self): + u = Union[object] + self.assertEqual(u, object) + u = Union[int, object] + self.assertEqual(u, object) + u = Union[object, int] + self.assertEqual(u, object) + + def test_union_any_object(self): + u = Union[object, Any] + self.assertEqual(u, Any) + u = Union[Any, object] + self.assertEqual(u, Any) + + def test_unordered(self): + u1 = Union[int, float] + u2 = Union[float, int] + self.assertEqual(u1, u2) + + def test_subclass(self): + u = Union[int, Employee] + self.assertIsInstance(Manager(), u) + self.assertTrue(issubclass(Manager, u)) + + def test_self_subclass(self): + self.assertTrue(issubclass(Union[KT, VT], Union)) + self.assertFalse(issubclass(Union, Union[KT, VT])) + + def test_multiple_inheritance(self): + u = Union[int, Employee] + self.assertIsInstance(ManagingFounder(), u) + self.assertTrue(issubclass(ManagingFounder, u)) + + def test_single_class_disappears(self): + t = Union[Employee] + self.assertIs(t, Employee) + + def test_base_class_disappears(self): + u = Union[Employee, Manager, int] + self.assertEqual(u, Union[int, Employee]) + u = Union[Manager, int, Employee] + self.assertEqual(u, Union[int, Employee]) + u = Union[Employee, Manager] + self.assertIs(u, Employee) + + def test_weird_subclasses(self): + u = Union[Employee, int, float] + v = Union[int, float] + self.assertTrue(issubclass(v, u)) + w = Union[int, Manager] + self.assertTrue(issubclass(w, u)) + + def test_union_union(self): + u = Union[int, float] + v = Union[u, Employee] + self.assertEqual(v, Union[int, float, Employee]) + + def test_repr(self): + self.assertEqual(repr(Union), 'typing.Union') + u = Union[Employee, int] + self.assertEqual(repr(u), 'typing.Union[%s.Employee, int]' % __name__) + u = Union[int, Employee] + self.assertEqual(repr(u), 'typing.Union[int, %s.Employee]' % __name__) + + def test_cannot_subclass(self): + with self.assertRaises(TypeError): + class C(Union): + pass + with self.assertRaises(TypeError): + class C(Union[int, str]): + pass + + def test_cannot_instantiate(self): + with self.assertRaises(TypeError): + Union() + u = Union[int, float] + with self.assertRaises(TypeError): + u() + + def test_optional(self): + o = Optional[int] + u = Union[int, None] + self.assertEqual(o, u) + self.assertIsInstance(42, o) + self.assertIsInstance(None, o) + self.assertNotIsInstance(3.14, o) + + def test_empty(self): + with self.assertRaises(TypeError): + Union[()] + + def test_issubclass_union(self): + assert issubclass(Union[int, str], Union) + assert not issubclass(int, Union) + + def test_isinstance_union(self): + # Nothing is an instance of bare Union. + assert not isinstance(42, Union) + assert not isinstance(int, Union) + assert not isinstance(Union[int, str], Union) + + +class TypeVarUnionTests(TestCase): + + def test_simpler(self): + A = TypeVar('A', int, str, float) + B = TypeVar('B', int, str) + assert issubclass(A, A) + assert issubclass(B, B) + assert not issubclass(B, A) + assert issubclass(A, Union[int, str, float]) + assert not issubclass(Union[int, str, float], A) + assert not issubclass(Union[int, str], B) + assert issubclass(B, Union[int, str]) + assert not issubclass(A, B) + assert not issubclass(Union[int, str, float], B) + assert not issubclass(A, Union[int, str]) + + def test_var_union_subclass(self): + self.assertTrue(issubclass(T, Union[int, T])) + self.assertTrue(issubclass(KT, Union[KT, VT])) + + def test_var_union(self): + TU = TypeVar('TU', Union[int, float], None) + assert issubclass(int, TU) + assert issubclass(float, TU) + with self.assertRaises(TypeError): + isinstance(42, TU) + with self.assertRaises(TypeError): + isinstance('', TU) + + +class TupleTests(TestCase): + + def test_basics(self): + self.assertIsInstance((42, 3.14, ''), Tuple) + self.assertIsInstance((42, 3.14, ''), Tuple[int, float, str]) + self.assertIsInstance((42,), Tuple[int]) + self.assertNotIsInstance((3.14,), Tuple[int]) + self.assertNotIsInstance((42, 3.14), Tuple[int, float, str]) + self.assertNotIsInstance((42, 3.14, 100), Tuple[int, float, str]) + self.assertNotIsInstance((42, 3.14, 100), Tuple[int, float]) + self.assertTrue(issubclass(Tuple[int, str], Tuple)) + self.assertTrue(issubclass(Tuple[int, str], Tuple[int, str])) + self.assertFalse(issubclass(int, Tuple)) + self.assertFalse(issubclass(Tuple[float, str], Tuple[int, str])) + self.assertFalse(issubclass(Tuple[int, str, int], Tuple[int, str])) + self.assertFalse(issubclass(Tuple[int, str], Tuple[int, str, int])) + self.assertTrue(issubclass(tuple, Tuple)) + self.assertFalse(issubclass(Tuple, tuple)) # Can't have it both ways. + + def test_tuple_subclass(self): + class MyTuple(tuple): + pass + self.assertTrue(issubclass(MyTuple, Tuple)) + + def test_tuple_ellipsis(self): + t = Tuple[int, ...] + assert isinstance((), t) + assert isinstance((1,), t) + assert isinstance((1, 2), t) + assert isinstance((1, 2, 3), t) + assert not isinstance((3.14,), t) + assert not isinstance((1, 2, 3.14,), t) + + def test_tuple_ellipsis_subclass(self): + + class B: + pass + + class C(B): + pass + + assert not issubclass(Tuple[B], Tuple[B, ...]) + assert issubclass(Tuple[C, ...], Tuple[B, ...]) + assert not issubclass(Tuple[C, ...], Tuple[B]) + assert not issubclass(Tuple[C], Tuple[B, ...]) + + def test_repr(self): + self.assertEqual(repr(Tuple), 'typing.Tuple') + self.assertEqual(repr(Tuple[()]), 'typing.Tuple[]') + self.assertEqual(repr(Tuple[int, float]), 'typing.Tuple[int, float]') + self.assertEqual(repr(Tuple[int, ...]), 'typing.Tuple[int, ...]') + + def test_errors(self): + with self.assertRaises(TypeError): + issubclass(42, Tuple) + with self.assertRaises(TypeError): + issubclass(42, Tuple[int]) + + +class CallableTests(TestCase): + + def test_basics(self): + c = Callable[[int, float], str] + + def flub(a: int, b: float) -> str: + return str(a * b) + + def flob(a: int, b: int) -> str: + return str(a * b) + + self.assertIsInstance(flub, c) + self.assertNotIsInstance(flob, c) + + def test_self_subclass(self): + self.assertTrue(issubclass(Callable[[int], int], Callable)) + self.assertFalse(issubclass(Callable, Callable[[int], int])) + self.assertTrue(issubclass(Callable[[int], int], Callable[[int], int])) + self.assertFalse(issubclass(Callable[[Employee], int], + Callable[[Manager], int])) + self.assertFalse(issubclass(Callable[[Manager], int], + Callable[[Employee], int])) + self.assertFalse(issubclass(Callable[[int], Employee], + Callable[[int], Manager])) + self.assertFalse(issubclass(Callable[[int], Manager], + Callable[[int], Employee])) + + def test_eq_hash(self): + self.assertEqual(Callable[[int], int], Callable[[int], int]) + self.assertEqual(len({Callable[[int], int], Callable[[int], int]}), 1) + self.assertNotEqual(Callable[[int], int], Callable[[int], str]) + self.assertNotEqual(Callable[[int], int], Callable[[str], int]) + self.assertNotEqual(Callable[[int], int], Callable[[int, int], int]) + self.assertNotEqual(Callable[[int], int], Callable[[], int]) + self.assertNotEqual(Callable[[int], int], Callable) + + def test_with_none(self): + c = Callable[[None], None] + + def flub(self: None) -> None: + pass + + def flab(self: Any) -> None: + pass + + def flob(self: None) -> Any: + pass + + self.assertIsInstance(flub, c) + self.assertIsInstance(flab, c) + self.assertNotIsInstance(flob, c) # Test contravariance. + + def test_with_subclasses(self): + c = Callable[[Employee, Manager], Employee] + + def flub(a: Employee, b: Employee) -> Manager: + return Manager() + + def flob(a: Manager, b: Manager) -> Employee: + return Employee() + + self.assertIsInstance(flub, c) + self.assertNotIsInstance(flob, c) + + def test_with_default_args(self): + c = Callable[[int], int] + + def flub(a: int, b: float = 3.14) -> int: + return a + + def flab(a: int, *, b: float = 3.14) -> int: + return a + + def flob(a: int = 42) -> int: + return a + + self.assertIsInstance(flub, c) + self.assertIsInstance(flab, c) + self.assertIsInstance(flob, c) + + def test_with_varargs(self): + c = Callable[[int], int] + + def flub(*args) -> int: + return 42 + + def flab(*args: int) -> int: + return 42 + + def flob(*args: float) -> int: + return 42 + + self.assertIsInstance(flub, c) + self.assertIsInstance(flab, c) + self.assertNotIsInstance(flob, c) + + def test_with_method(self): + + class C: + + def imethod(self, arg: int) -> int: + self.last_arg = arg + return arg + 1 + + @classmethod + def cmethod(cls, arg: int) -> int: + cls.last_cls_arg = arg + return arg + 1 + + @staticmethod + def smethod(arg: int) -> int: + return arg + 1 + + ct = Callable[[int], int] + self.assertIsInstance(C().imethod, ct) + self.assertIsInstance(C().cmethod, ct) + self.assertIsInstance(C.cmethod, ct) + self.assertIsInstance(C().smethod, ct) + self.assertIsInstance(C.smethod, ct) + self.assertIsInstance(C.imethod, Callable[[Any, int], int]) + + def test_cannot_subclass(self): + with self.assertRaises(TypeError): + + class C(Callable): + pass + + with self.assertRaises(TypeError): + + class C(Callable[[int], int]): + pass + + def test_cannot_instantiate(self): + with self.assertRaises(TypeError): + Callable() + c = Callable[[int], str] + with self.assertRaises(TypeError): + c() + + def test_varargs(self): + ct = Callable[..., int] + + def foo(a, b) -> int: + return 42 + + def bar(a=42) -> int: + return a + + def baz(*, x, y, z) -> int: + return 100 + + self.assertIsInstance(foo, ct) + self.assertIsInstance(bar, ct) + self.assertIsInstance(baz, ct) + + def test_repr(self): + ct0 = Callable[[], bool] + self.assertEqual(repr(ct0), 'typing.Callable[[], bool]') + ct2 = Callable[[str, float], int] + self.assertEqual(repr(ct2), 'typing.Callable[[str, float], int]') + ctv = Callable[..., str] + self.assertEqual(repr(ctv), 'typing.Callable[..., str]') + + +XK = TypeVar('XK', str, bytes) +XV = TypeVar('XV') + + +class SimpleMapping(Generic[XK, XV]): + + def __getitem__(self, key: XK) -> XV: + ... + + def __setitem__(self, key: XK, value: XV): + ... + + def get(self, key: XK, default: XV = None) -> XV: + ... + + +class MySimpleMapping(SimpleMapping): + + def __init__(self): + self.store = {} + + def __getitem__(self, key: str): + return self.store[key] + + def __setitem__(self, key: str, value): + self.store[key] = value + + def get(self, key: str, default=None): + try: + return self.store[key] + except KeyError: + return default + + +class ProtocolTests(TestCase): + + def test_supports_int(self): + assert issubclass(int, typing.SupportsInt) + assert not issubclass(str, typing.SupportsInt) + + def test_supports_float(self): + assert issubclass(float, typing.SupportsFloat) + assert not issubclass(str, typing.SupportsFloat) + + def test_supports_complex(self): + + # Note: complex itself doesn't have __complex__. + class C: + def __complex__(self): + return 0j + + assert issubclass(C, typing.SupportsComplex) + assert not issubclass(str, typing.SupportsComplex) + + def test_supports_bytes(self): + + # Note: bytes itself doesn't have __bytes__. + class B: + def __bytes__(self): + return b'' + + assert issubclass(B, typing.SupportsBytes) + assert not issubclass(str, typing.SupportsBytes) + + def test_supports_abs(self): + assert issubclass(float, typing.SupportsAbs) + assert issubclass(int, typing.SupportsAbs) + assert not issubclass(str, typing.SupportsAbs) + + def test_supports_round(self): + assert issubclass(float, typing.SupportsRound) + assert issubclass(int, typing.SupportsRound) + assert not issubclass(str, typing.SupportsRound) + + def test_reversible(self): + assert issubclass(list, typing.Reversible) + assert not issubclass(int, typing.Reversible) + + +class GenericTests(TestCase): + + def test_basics(self): + X = SimpleMapping[str, Any] + Y = SimpleMapping[XK, str] + X[str, str] + Y[str, str] + with self.assertRaises(TypeError): + X[int, str] + with self.assertRaises(TypeError): + Y[str, bytes] + + def test_repr(self): + self.assertEqual(repr(SimpleMapping), + __name__ + '.' + 'SimpleMapping[~XK, ~XV]') + self.assertEqual(repr(MySimpleMapping), + __name__ + '.' + 'MySimpleMapping[~XK, ~XV]') + + def test_errors(self): + with self.assertRaises(TypeError): + B = SimpleMapping[XK, Any] + + class C(Generic[B]): + pass + + def test_repr_2(self): + PY32 = sys.version_info[:2] < (3, 3) + + class C(Generic[T]): + pass + + assert C.__module__ == __name__ + if not PY32: + assert C.__qualname__ == 'GenericTests.test_repr_2..C' + assert repr(C).split('.')[-1] == 'C[~T]' + X = C[int] + assert X.__module__ == __name__ + if not PY32: + assert X.__qualname__ == 'C' + assert repr(X).split('.')[-1] == 'C[int]' + + class Y(C[int]): + pass + + assert Y.__module__ == __name__ + if not PY32: + assert Y.__qualname__ == 'GenericTests.test_repr_2..Y' + assert repr(Y).split('.')[-1] == 'Y[int]' + + def test_eq_1(self): + assert Generic == Generic + assert Generic[T] == Generic[T] + assert Generic[KT] != Generic[VT] + + def test_eq_2(self): + + class A(Generic[T]): + pass + + class B(Generic[T]): + pass + + assert A == A + assert A != B + assert A[T] == A[T] + assert A[T] != B[T] + + def test_multiple_inheritance(self): + + class A(Generic[T, VT]): + pass + + class B(Generic[KT, T]): + pass + + class C(A, Generic[KT, VT], B): + pass + + assert C.__parameters__ == (T, VT, KT) + + def test_nested(self): + + class G(Generic): + pass + + class Visitor(G[T]): + + a = None + + def set(self, a: T): + self.a = a + + def get(self): + return self.a + + def visit(self) -> T: + return self.a + + V = Visitor[typing.List[int]] + + class IntListVisitor(V): + + def append(self, x: int): + self.a.append(x) + + a = IntListVisitor() + a.set([]) + a.append(1) + a.append(42) + assert a.get() == [1, 42] + + def test_type_erasure(self): + T = TypeVar('T') + + class Node(Generic[T]): + def __init__(self, label: T, left: 'Node[T]' = None, right: 'Node[T]' = None): + self.label = label # type: T + self.left = left # type: Optional[Node[T]] + self.right = right # type: Optional[Node[T]] + + def foo(x: T): + a = Node(x) + b = Node[T](x) + c = Node[Any](x) + assert type(a) is Node + assert type(b) is Node + assert type(c) is Node + + foo(42) + + +class VarianceTests(TestCase): + + def test_invariance(self): + # Because of invariance, List[subclass of X] is not a subclass + # of List[X], and ditto for MutableSequence. + assert not issubclass(typing.List[Manager], typing.List[Employee]) + assert not issubclass(typing.MutableSequence[Manager], + typing.MutableSequence[Employee]) + # It's still reflexive. + assert issubclass(typing.List[Employee], typing.List[Employee]) + assert issubclass(typing.MutableSequence[Employee], + typing.MutableSequence[Employee]) + + def test_covariance_tuple(self): + # Check covariace for Tuple (which are really special cases). + assert issubclass(Tuple[Manager], Tuple[Employee]) + assert not issubclass(Tuple[Employee], Tuple[Manager]) + # And pairwise. + assert issubclass(Tuple[Manager, Manager], Tuple[Employee, Employee]) + assert not issubclass(Tuple[Employee, Employee], + Tuple[Manager, Employee]) + # And using ellipsis. + assert issubclass(Tuple[Manager, ...], Tuple[Employee, ...]) + assert not issubclass(Tuple[Employee, ...], Tuple[Manager, ...]) + + def test_covariance_sequence(self): + # Check covariance for Sequence (which is just a generic class + # for this purpose, but using a covariant type variable). + assert issubclass(typing.Sequence[Manager], typing.Sequence[Employee]) + assert not issubclass(typing.Sequence[Employee], + typing.Sequence[Manager]) + + def test_covariance_mapping(self): + # Ditto for Mapping (a generic class with two parameters). + assert issubclass(typing.Mapping[Employee, Manager], + typing.Mapping[Employee, Employee]) + assert issubclass(typing.Mapping[Manager, Employee], + typing.Mapping[Employee, Employee]) + assert not issubclass(typing.Mapping[Employee, Manager], + typing.Mapping[Manager, Manager]) + assert not issubclass(typing.Mapping[Manager, Employee], + typing.Mapping[Manager, Manager]) + + +class CastTests(TestCase): + + def test_basics(self): + assert cast(int, 42) == 42 + assert cast(float, 42) == 42 + assert type(cast(float, 42)) is int + assert cast(Any, 42) == 42 + assert cast(list, 42) == 42 + assert cast(Union[str, float], 42) == 42 + assert cast(AnyStr, 42) == 42 + assert cast(None, 42) == 42 + + def test_errors(self): + # Bogus calls are not expected to fail. + cast(42, 42) + cast('hello', 42) + + +class ForwardRefTests(TestCase): + + def test_basics(self): + + class Node(Generic[T]): + + def __init__(self, label: T): + self.label = label + self.left = self.right = None + + def add_both(self, + left: 'Optional[Node[T]]', + right: 'Node[T]' = None, + stuff: int = None, + blah=None): + self.left = left + self.right = right + + def add_left(self, node: Optional['Node[T]']): + self.add_both(node, None) + + def add_right(self, node: 'Node[T]' = None): + self.add_both(None, node) + + t = Node[int] + both_hints = get_type_hints(t.add_both, globals(), locals()) + assert both_hints['left'] == both_hints['right'] == Optional[Node[T]] + assert both_hints['stuff'] == Optional[int] + assert 'blah' not in both_hints + + left_hints = get_type_hints(t.add_left, globals(), locals()) + assert left_hints['node'] == Optional[Node[T]] + + right_hints = get_type_hints(t.add_right, globals(), locals()) + assert right_hints['node'] == Optional[Node[T]] + + def test_union_forward(self): + + def foo(a: Union['T']): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Union[T]}) + + def test_tuple_forward(self): + + def foo(a: Tuple['T']): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Tuple[T]}) + + def test_callable_forward(self): + + def foo(a: Callable[['T'], 'T']): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Callable[[T], T]}) + + def test_syntax_error(self): + + with self.assertRaises(SyntaxError): + Generic['/T'] + + def test_delayed_syntax_error(self): + + def foo(a: 'Node[T'): + pass + + with self.assertRaises(SyntaxError): + get_type_hints(foo) + + def test_type_error(self): + + def foo(a: Tuple['42']): + pass + + with self.assertRaises(TypeError): + get_type_hints(foo) + + def test_name_error(self): + + def foo(a: 'Noode[T]'): + pass + + with self.assertRaises(NameError): + get_type_hints(foo, locals()) + + def test_no_type_check(self): + + @no_type_check + def foo(a: 'whatevers') -> {}: + pass + + th = get_type_hints(foo) + self.assertEqual(th, {}) + + def test_no_type_check_class(self): + + @no_type_check + class C: + def foo(a: 'whatevers') -> {}: + pass + + cth = get_type_hints(C.foo) + self.assertEqual(cth, {}) + ith = get_type_hints(C().foo) + self.assertEqual(ith, {}) + + def test_meta_no_type_check(self): + + @no_type_check_decorator + def magic_decorator(deco): + return deco + + self.assertEqual(magic_decorator.__name__, 'magic_decorator') + + @magic_decorator + def foo(a: 'whatevers') -> {}: + pass + + @magic_decorator + class C: + def foo(a: 'whatevers') -> {}: + pass + + self.assertEqual(foo.__name__, 'foo') + th = get_type_hints(foo) + self.assertEqual(th, {}) + cth = get_type_hints(C.foo) + self.assertEqual(cth, {}) + ith = get_type_hints(C().foo) + self.assertEqual(ith, {}) + + def test_default_globals(self): + code = ("class C:\n" + " def foo(self, a: 'C') -> 'D': pass\n" + "class D:\n" + " def bar(self, b: 'D') -> C: pass\n" + ) + ns = {} + exec(code, ns) + hints = get_type_hints(ns['C'].foo) + assert hints == {'a': ns['C'], 'return': ns['D']} + + +class OverloadTests(TestCase): + + def test_overload_exists(self): + from typing import overload + + def test_overload_fails(self): + from typing import overload + + with self.assertRaises(RuntimeError): + @overload + def blah(): + pass + + +class CollectionsAbcTests(TestCase): + + def test_hashable(self): + assert isinstance(42, typing.Hashable) + assert not isinstance([], typing.Hashable) + + def test_iterable(self): + assert isinstance([], typing.Iterable) + assert isinstance([], typing.Iterable[int]) + assert not isinstance(42, typing.Iterable) + + def test_iterator(self): + it = iter([]) + assert isinstance(it, typing.Iterator) + assert isinstance(it, typing.Iterator[int]) + assert not isinstance(42, typing.Iterator) + + def test_sized(self): + assert isinstance([], typing.Sized) + assert not isinstance(42, typing.Sized) + + def test_container(self): + assert isinstance([], typing.Container) + assert not isinstance(42, typing.Container) + + def test_abstractset(self): + assert isinstance(set(), typing.AbstractSet) + assert not isinstance(42, typing.AbstractSet) + + def test_mutableset(self): + assert isinstance(set(), typing.MutableSet) + assert not isinstance(frozenset(), typing.MutableSet) + + def test_mapping(self): + assert isinstance({}, typing.Mapping) + assert not isinstance(42, typing.Mapping) + + def test_mutablemapping(self): + assert isinstance({}, typing.MutableMapping) + assert not isinstance(42, typing.MutableMapping) + + def test_sequence(self): + assert isinstance([], typing.Sequence) + assert not isinstance(42, typing.Sequence) + + def test_mutablesequence(self): + assert isinstance([], typing.MutableSequence) + assert not isinstance((), typing.MutableSequence) + + def test_bytestring(self): + assert isinstance(b'', typing.ByteString) + assert isinstance(bytearray(b''), typing.ByteString) + + def test_list(self): + assert issubclass(list, typing.List) + assert isinstance([], typing.List) + assert not isinstance((), typing.List) + t = typing.List[int] + assert isinstance([], t) + assert isinstance([42], t) + assert not isinstance([''], t) + + def test_set(self): + assert issubclass(set, typing.Set) + assert not issubclass(frozenset, typing.Set) + assert isinstance(set(), typing.Set) + assert not isinstance({}, typing.Set) + t = typing.Set[int] + assert isinstance(set(), t) + assert isinstance({42}, t) + assert not isinstance({''}, t) + + def test_frozenset(self): + assert issubclass(frozenset, typing.FrozenSet) + assert not issubclass(set, typing.FrozenSet) + assert isinstance(frozenset(), typing.FrozenSet) + assert not isinstance({}, typing.FrozenSet) + t = typing.FrozenSet[int] + assert isinstance(frozenset(), t) + assert isinstance(frozenset({42}), t) + assert not isinstance(frozenset({''}), t) + assert not isinstance({42}, t) + + def test_mapping_views(self): + # TODO: These tests are kind of lame. + assert isinstance({}.keys(), typing.KeysView) + assert isinstance({}.items(), typing.ItemsView) + assert isinstance({}.values(), typing.ValuesView) + + def test_dict(self): + assert issubclass(dict, typing.Dict) + assert isinstance({}, typing.Dict) + assert not isinstance([], typing.Dict) + t = typing.Dict[int, str] + assert isinstance({}, t) + assert isinstance({42: ''}, t) + assert not isinstance({42: 42}, t) + assert not isinstance({'': 42}, t) + assert not isinstance({'': ''}, t) + + def test_no_list_instantiation(self): + with self.assertRaises(TypeError): + typing.List() + with self.assertRaises(TypeError): + typing.List[T]() + with self.assertRaises(TypeError): + typing.List[int]() + + def test_list_subclass_instantiation(self): + + class MyList(typing.List[int]): + pass + + a = MyList() + assert isinstance(a, MyList) + + def test_no_dict_instantiation(self): + with self.assertRaises(TypeError): + typing.Dict() + with self.assertRaises(TypeError): + typing.Dict[KT, VT]() + with self.assertRaises(TypeError): + typing.Dict[str, int]() + + def test_dict_subclass_instantiation(self): + + class MyDict(typing.Dict[str, int]): + pass + + d = MyDict() + assert isinstance(d, MyDict) + + def test_no_set_instantiation(self): + with self.assertRaises(TypeError): + typing.Set() + with self.assertRaises(TypeError): + typing.Set[T]() + with self.assertRaises(TypeError): + typing.Set[int]() + + def test_set_subclass_instantiation(self): + + class MySet(typing.Set[int]): + pass + + d = MySet() + assert isinstance(d, MySet) + + def test_no_frozenset_instantiation(self): + with self.assertRaises(TypeError): + typing.FrozenSet() + with self.assertRaises(TypeError): + typing.FrozenSet[T]() + with self.assertRaises(TypeError): + typing.FrozenSet[int]() + + def test_frozenset_subclass_instantiation(self): + + class MyFrozenSet(typing.FrozenSet[int]): + pass + + d = MyFrozenSet() + assert isinstance(d, MyFrozenSet) + + def test_no_tuple_instantiation(self): + with self.assertRaises(TypeError): + Tuple() + with self.assertRaises(TypeError): + Tuple[T]() + with self.assertRaises(TypeError): + Tuple[int]() + + def test_generator(self): + def foo(): + yield 42 + g = foo() + assert issubclass(type(g), typing.Generator) + assert isinstance(g, typing.Generator) + assert not isinstance(foo, typing.Generator) + assert issubclass(typing.Generator[Manager, Employee, Manager], + typing.Generator[Employee, Manager, Employee]) + assert not issubclass(typing.Generator[Manager, Manager, Manager], + typing.Generator[Employee, Employee, Employee]) + + def test_no_generator_instantiation(self): + with self.assertRaises(TypeError): + typing.Generator() + with self.assertRaises(TypeError): + typing.Generator[T, T, T]() + with self.assertRaises(TypeError): + typing.Generator[int, int, int]() + + def test_subclassing(self): + + class MMA(typing.MutableMapping): + pass + + with self.assertRaises(TypeError): # It's abstract + MMA() + + class MMC(MMA): + def __len__(self): + return 0 + + assert len(MMC()) == 0 + + class MMB(typing.MutableMapping[KT, VT]): + def __len__(self): + return 0 + + assert len(MMB()) == 0 + assert len(MMB[str, str]()) == 0 + assert len(MMB[KT, VT]()) == 0 + + def test_recursive_dict(self): + D = typing.Dict[int, 'D'] # Uses a _ForwardRef + assert isinstance({}, D) # Easy + assert isinstance({0: {}}, D) # Touches _ForwardRef + assert isinstance({0: {0: {}}}, D) # Etc... + + +class NamedTupleTests(TestCase): + + def test_basics(self): + Emp = NamedTuple('Emp', [('name', str), ('id', int)]) + assert issubclass(Emp, tuple) + joe = Emp('Joe', 42) + jim = Emp(name='Jim', id=1) + assert isinstance(joe, Emp) + assert isinstance(joe, tuple) + assert joe.name == 'Joe' + assert joe.id == 42 + assert jim.name == 'Jim' + assert jim.id == 1 + assert Emp.__name__ == 'Emp' + assert Emp._fields == ('name', 'id') + assert Emp._field_types == dict(name=str, id=int) + + +class IOTests(TestCase): + + def test_io(self): + + def stuff(a: IO) -> AnyStr: + return a.readline() + + a = stuff.__annotations__['a'] + assert a.__parameters__ == (AnyStr,) + + def test_textio(self): + + def stuff(a: TextIO) -> str: + return a.readline() + + a = stuff.__annotations__['a'] + assert a.__parameters__ == (str,) + + def test_binaryio(self): + + def stuff(a: BinaryIO) -> bytes: + return a.readline() + + a = stuff.__annotations__['a'] + assert a.__parameters__ == (bytes,) + + def test_io_submodule(self): + from typing.io import IO, TextIO, BinaryIO, __all__, __name__ + assert IO is typing.IO + assert TextIO is typing.TextIO + assert BinaryIO is typing.BinaryIO + assert set(__all__) == set(['IO', 'TextIO', 'BinaryIO']) + assert __name__ == 'typing.io' + + +class RETests(TestCase): + # Much of this is really testing _TypeAlias. + + def test_basics(self): + pat = re.compile('[a-z]+', re.I) + assert issubclass(pat.__class__, Pattern) + assert isinstance(pat, Pattern[str]) + assert not isinstance(pat, Pattern[bytes]) + assert issubclass(type(pat), Pattern) + assert issubclass(type(pat), Pattern[str]) + + mat = pat.search('12345abcde.....') + assert issubclass(mat.__class__, Match) + assert issubclass(mat.__class__, Match[str]) + assert issubclass(mat.__class__, Match[bytes]) # Sad but true. + assert issubclass(type(mat), Match) + assert issubclass(type(mat), Match[str]) + + p = Pattern[Union[str, bytes]] + assert isinstance(pat, p) + assert issubclass(Pattern[str], Pattern) + assert issubclass(Pattern[str], p) + + m = Match[Union[bytes, str]] + assert isinstance(mat, m) + assert issubclass(Match[bytes], Match) + assert issubclass(Match[bytes], m) + + def test_errors(self): + with self.assertRaises(TypeError): + # Doesn't fit AnyStr. + Pattern[int] + with self.assertRaises(TypeError): + # Can't change type vars? + Match[T] + m = Match[Union[str, bytes]] + with self.assertRaises(TypeError): + # Too complicated? + m[str] + + def test_repr(self): + assert repr(Pattern) == 'Pattern[~AnyStr]' + assert repr(Pattern[str]) == 'Pattern[str]' + assert repr(Pattern[bytes]) == 'Pattern[bytes]' + assert repr(Match) == 'Match[~AnyStr]' + assert repr(Match[str]) == 'Match[str]' + assert repr(Match[bytes]) == 'Match[bytes]' + + def test_re_submodule(self): + from typing.re import Match, Pattern, __all__, __name__ + assert Match is typing.Match + assert Pattern is typing.Pattern + assert set(__all__) == set(['Match', 'Pattern']) + assert __name__ == 'typing.re' + + def test_cannot_subclass(self): + with self.assertRaises(TypeError) as ex: + + class A(typing.Match): + pass + + assert str(ex.exception) == "A type alias cannot be subclassed" + + +class AllTests(TestCase): + """Tests for __all__.""" + + def test_all(self): + from typing import __all__ as a + # Just spot-check the first and last of every category. + assert 'AbstractSet' in a + assert 'ValuesView' in a + assert 'cast' in a + assert 'overload' in a + assert 'io' in a + assert 're' in a + # Spot-check that stdlib modules aren't exported. + assert 'os' not in a + assert 'sys' not in a + + +if __name__ == '__main__': + main() diff --git a/Lib/typing.py b/Lib/typing.py new file mode 100644 --- /dev/null +++ b/Lib/typing.py @@ -0,0 +1,1714 @@ +# TODO: +# - Generic[T, T] is invalid +# - Look for TODO below + +# TODO nits: +# Get rid of asserts that are the caller's fault. +# Docstrings (e.g. ABCs). + +import abc +from abc import abstractmethod, abstractproperty +import collections +import functools +import re as stdlib_re # Avoid confusion with the re we export. +import sys +import types +try: + import collections.abc as collections_abc +except ImportError: + import collections as collections_abc # Fallback for PY3.2. + + +# Please keep __all__ alphabetized within each category. +__all__ = [ + # Super-special typing primitives. + 'Any', + 'Callable', + 'Generic', + 'Optional', + 'TypeVar', + 'Union', + 'Tuple', + + # ABCs (from collections.abc). + 'AbstractSet', # collections.abc.Set. + 'ByteString', + 'Container', + 'Hashable', + 'ItemsView', + 'Iterable', + 'Iterator', + 'KeysView', + 'Mapping', + 'MappingView', + 'MutableMapping', + 'MutableSequence', + 'MutableSet', + 'Sequence', + 'Sized', + 'ValuesView', + + # Structural checks, a.k.a. protocols. + 'Reversible', + 'SupportsAbs', + 'SupportsFloat', + 'SupportsInt', + 'SupportsRound', + + # Concrete collection types. + 'Dict', + 'List', + 'Set', + 'NamedTuple', # Not really a type. + 'Generator', + + # One-off things. + 'AnyStr', + 'cast', + 'get_type_hints', + 'no_type_check', + 'no_type_check_decorator', + 'overload', + + # Submodules. + 'io', + 're', +] + + +def _qualname(x): + if sys.version_info[:2] >= (3, 3): + return x.__qualname__ + else: + # Fall back to just name. + return x.__name__ + + +class TypingMeta(type): + """Metaclass for every type defined below. + + This overrides __new__() to require an extra keyword parameter + '_root', which serves as a guard against naive subclassing of the + typing classes. Any legitimate class defined using a metaclass + derived from TypingMeta (including internal subclasses created by + e.g. Union[X, Y]) must pass _root=True. + + This also defines a dummy constructor (all the work is done in + __new__) and a nicer repr(). + """ + + _is_protocol = False + + def __new__(cls, name, bases, namespace, *, _root=False): + if not _root: + raise TypeError("Cannot subclass %s" % + (', '.join(map(_type_repr, bases)) or '()')) + return super().__new__(cls, name, bases, namespace) + + def __init__(self, *args, **kwds): + pass + + def _eval_type(self, globalns, localns): + """Override this in subclasses to interpret forward references. + + For example, Union['C'] is internally stored as + Union[_ForwardRef('C')], which should evaluate to _Union[C], + where C is an object found in globalns or localns (searching + localns first, of course). + """ + return self + + def _has_type_var(self): + return False + + def __repr__(self): + return '%s.%s' % (self.__module__, _qualname(self)) + + +class Final: + """Mix-in class to prevent instantiation.""" + + def __new__(self, *args, **kwds): + raise TypeError("Cannot instantiate %r" % self.__class__) + + +class _ForwardRef(TypingMeta): + """Wrapper to hold a forward reference.""" + + def __new__(cls, arg): + if not isinstance(arg, str): + raise TypeError('ForwardRef must be a string -- got %r' % (arg,)) + try: + code = compile(arg, '', 'eval') + except SyntaxError: + raise SyntaxError('ForwardRef must be an expression -- got %r' % + (arg,)) + self = super().__new__(cls, arg, (), {}, _root=True) + self.__forward_arg__ = arg + self.__forward_code__ = code + self.__forward_evaluated__ = False + self.__forward_value__ = None + typing_globals = globals() + frame = sys._getframe(1) + while frame is not None and frame.f_globals is typing_globals: + frame = frame.f_back + assert frame is not None + self.__forward_frame__ = frame + return self + + def _eval_type(self, globalns, localns): + if not isinstance(localns, dict): + raise TypeError('ForwardRef localns must be a dict -- got %r' % + (localns,)) + if not isinstance(globalns, dict): + raise TypeError('ForwardRef globalns must be a dict -- got %r' % + (globalns,)) + if not self.__forward_evaluated__: + if globalns is None and localns is None: + globalns = localns = {} + elif globalns is None: + globalns = localns + elif localns is None: + localns = globalns + self.__forward_value__ = _type_check( + eval(self.__forward_code__, globalns, localns), + "Forward references must evaluate to types.") + self.__forward_evaluated__ = True + return self.__forward_value__ + + def __subclasscheck__(self, cls): + if not self.__forward_evaluated__: + globalns = self.__forward_frame__.f_globals + localns = self.__forward_frame__.f_locals + try: + self._eval_type(globalns, localns) + except NameError: + return False # Too early. + return issubclass(cls, self.__forward_value__) + + def __instancecheck__(self, obj): + if not self.__forward_evaluated__: + globalns = self.__forward_frame__.f_globals + localns = self.__forward_frame__.f_locals + try: + self._eval_type(globalns, localns) + except NameError: + return False # Too early. + return isinstance(obj, self.__forward_value__) + + def __repr__(self): + return '_ForwardRef(%r)' % (self.__forward_arg__,) + + +class _TypeAlias: + """Internal helper class for defining generic variants of concrete types. + + Note that this is not a type; let's call it a pseudo-type. It can + be used in instance and subclass checks, e.g. isinstance(m, Match) + or issubclass(type(m), Match). However, it cannot be itself the + target of an issubclass() call; e.g. issubclass(Match, C) (for + some arbitrary class C) raises TypeError rather than returning + False. + """ + + def __new__(cls, *args, **kwds): + """Constructor. + + This only exists to give a better error message in case + someone tries to subclass a type alias (not a good idea). + """ + if (len(args) == 3 and + isinstance(args[0], str) and + isinstance(args[1], tuple)): + # Close enough. + raise TypeError("A type alias cannot be subclassed") + return object.__new__(cls) + + def __init__(self, name, type_var, impl_type, type_checker): + """Initializer. + + Args: + name: The name, e.g. 'Pattern'. + type_var: The type parameter, e.g. AnyStr, or the + specific type, e.g. str. + impl_type: The implementation type. + type_checker: Function that takes an impl_type instance. + and returns a value that should be a type_var instance. + """ + assert isinstance(name, str), repr(name) + assert isinstance(type_var, type), repr(type_var) + assert isinstance(impl_type, type), repr(impl_type) + assert not isinstance(impl_type, TypingMeta), repr(impl_type) + self.name = name + self.type_var = type_var + self.impl_type = impl_type + self.type_checker = type_checker + + def __repr__(self): + return "%s[%s]" % (self.name, _type_repr(self.type_var)) + + def __getitem__(self, parameter): + assert isinstance(parameter, type), repr(parameter) + if not isinstance(self.type_var, TypeVar): + raise TypeError("%s cannot be further parameterized." % self) + if self.type_var.__constraints__: + if not issubclass(parameter, Union[self.type_var.__constraints__]): + raise TypeError("%s is not a valid substitution for %s." % + (parameter, self.type_var)) + return self.__class__(self.name, parameter, + self.impl_type, self.type_checker) + + def __instancecheck__(self, obj): + return (isinstance(obj, self.impl_type) and + isinstance(self.type_checker(obj), self.type_var)) + + def __subclasscheck__(self, cls): + if cls is Any: + return True + if isinstance(cls, _TypeAlias): + # Covariance. For now, we compare by name. + return (cls.name == self.name and + issubclass(cls.type_var, self.type_var)) + else: + # Note that this is too lenient, because the + # implementation type doesn't carry information about + # whether it is about bytes or str (for example). + return issubclass(cls, self.impl_type) + + +def _has_type_var(t): + return t is not None and isinstance(t, TypingMeta) and t._has_type_var() + + +def _eval_type(t, globalns, localns): + if isinstance(t, TypingMeta): + return t._eval_type(globalns, localns) + else: + return t + + +def _type_check(arg, msg): + """Check that the argument is a type, and return it. + + As a special case, accept None and return type(None) instead. + Also, _TypeAlias instances (e.g. Match, Pattern) are acceptable. + + The msg argument is a human-readable error message, e.g. + + "Union[arg, ...]: arg should be a type." + + We append the repr() of the actual value (truncated to 100 chars). + """ + if arg is None: + return type(None) + if isinstance(arg, str): + arg = _ForwardRef(arg) + if not isinstance(arg, (type, _TypeAlias)): + raise TypeError(msg + " Got %.100r." % (arg,)) + return arg + + +def _type_repr(obj): + """Return the repr() of an object, special-casing types. + + If obj is a type, we return a shorter version than the default + type.__repr__, based on the module and qualified name, which is + typically enough to uniquely identify a type. For everything + else, we fall back on repr(obj). + """ + if isinstance(obj, type) and not isinstance(obj, TypingMeta): + if obj.__module__ == 'builtins': + return _qualname(obj) + else: + return '%s.%s' % (obj.__module__, _qualname(obj)) + else: + return repr(obj) + + +class AnyMeta(TypingMeta): + """Metaclass for Any.""" + + def __new__(cls, name, bases, namespace, _root=False): + self = super().__new__(cls, name, bases, namespace, _root=_root) + return self + + def __instancecheck__(self, instance): + return True + + def __subclasscheck__(self, cls): + if not isinstance(cls, type): + return super().__subclasscheck__(cls) # To TypeError. + return True + + +class Any(Final, metaclass=AnyMeta, _root=True): + """Special type indicating an unconstrained type. + + - Any object is an instance of Any. + - Any class is a subclass of Any. + - As a special case, Any and object are subclasses of each other. + """ + + +class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): + """Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + def repeat(x: T, n: int) -> Sequence[T]: + '''Return a list containing n references to x.''' + return [x]*n + + def longest(x: A, y: A) -> A: + '''Return the longest of two strings.''' + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of (str, str) -> str and (bytes, bytes) -> bytes. Also note + that if the arguments are instances of some subclass of str, + the return type is still plain str. + + At runtime, isinstance(x, T) will raise TypeError. However, + issubclass(C, T) is true for any class C, and issubclass(str, A) + and issubclass(bytes, A) are true, and issubclass(int, A) is + false. + + Type variables may be marked covariant or contravariant by passing + covariant=True or contravariant=True. See PEP 484 for more + details. By default type variables are invariant. + + Type variables can be introspected. e.g.: + + T.__name__ == 'T' + T.__constraints__ == () + T.__covariant__ == False + T.__contravariant__ = False + A.__constraints__ == (str, bytes) + """ + + def __new__(cls, name, *constraints, bound=None, + covariant=False, contravariant=False): + self = super().__new__(cls, name, (Final,), {}, _root=True) + if covariant and contravariant: + raise ValueError("Bivariant type variables are not supported.") + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + if constraints and bound is not None: + raise TypeError("Constraints cannot be combined with bound=...") + if constraints and len(constraints) == 1: + raise TypeError("A single constraint is not allowed") + msg = "TypeVar(name, constraint, ...): constraints must be types." + self.__constraints__ = tuple(_type_check(t, msg) for t in constraints) + if bound: + self.__bound__ = _type_check(bound, "Bound must be a type.") + else: + self.__bound__ = None + return self + + def _has_type_var(self): + return True + + def __repr__(self): + if self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __instancecheck__(self, instance): + raise TypeError("Type variables cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + # TODO: Make this raise TypeError too? + if cls is self: + return True + if cls is Any: + return True + if self.__bound__ is not None: + return issubclass(cls, self.__bound__) + if self.__constraints__: + return any(issubclass(cls, c) for c in self.__constraints__) + return True + + +# Some unconstrained type variables. These are used by the container types. +T = TypeVar('T') # Any type. +KT = TypeVar('KT') # Key type. +VT = TypeVar('VT') # Value type. +T_co = TypeVar('T_co', covariant=True) # Any type covariant containers. +V_co = TypeVar('V_co', covariant=True) # Any type covariant containers. +KT_co = TypeVar('KT_co', covariant=True) # Key type covariant containers. +VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers. +T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant. + +# A useful type variable with constraints. This represents string types. +# TODO: What about bytearray, memoryview? +AnyStr = TypeVar('AnyStr', bytes, str) + + +class UnionMeta(TypingMeta): + """Metaclass for Union.""" + + def __new__(cls, name, bases, namespace, parameters=None, _root=False): + if parameters is None: + return super().__new__(cls, name, bases, namespace, _root=_root) + if not isinstance(parameters, tuple): + raise TypeError("Expected parameters=") + # Flatten out Union[Union[...], ...] and type-check non-Union args. + params = [] + msg = "Union[arg, ...]: each arg must be a type." + for p in parameters: + if isinstance(p, UnionMeta): + params.extend(p.__union_params__) + else: + params.append(_type_check(p, msg)) + # Weed out strict duplicates, preserving the first of each occurrence. + all_params = set(params) + if len(all_params) < len(params): + new_params = [] + for t in params: + if t in all_params: + new_params.append(t) + all_params.remove(t) + params = new_params + assert not all_params, all_params + # Weed out subclasses. + # E.g. Union[int, Employee, Manager] == Union[int, Employee]. + # If Any or object is present it will be the sole survivor. + # If both Any and object are present, Any wins. + # Never discard type variables, except against Any. + # (In particular, Union[str, AnyStr] != AnyStr.) + all_params = set(params) + for t1 in params: + if t1 is Any: + return Any + if isinstance(t1, TypeVar): + continue + if any(issubclass(t1, t2) + for t2 in all_params - {t1} if not isinstance(t2, TypeVar)): + all_params.remove(t1) + # It's not a union if there's only one type left. + if len(all_params) == 1: + return all_params.pop() + # Create a new class with these params. + self = super().__new__(cls, name, bases, {}, _root=True) + self.__union_params__ = tuple(t for t in params if t in all_params) + self.__union_set_params__ = frozenset(self.__union_params__) + return self + + def _eval_type(self, globalns, localns): + p = tuple(_eval_type(t, globalns, localns) + for t in self.__union_params__) + if p == self.__union_params__: + return self + else: + return self.__class__(self.__name__, self.__bases__, {}, + p, _root=True) + + def _has_type_var(self): + if self.__union_params__: + for t in self.__union_params__: + if _has_type_var(t): + return True + return False + + def __repr__(self): + r = super().__repr__() + if self.__union_params__: + r += '[%s]' % (', '.join(_type_repr(t) + for t in self.__union_params__)) + return r + + def __getitem__(self, parameters): + if self.__union_params__ is not None: + raise TypeError( + "Cannot subscript an existing Union. Use Union[u, t] instead.") + if parameters == (): + raise TypeError("Cannot take a Union of no types.") + if not isinstance(parameters, tuple): + parameters = (parameters,) + return self.__class__(self.__name__, self.__bases__, + dict(self.__dict__), parameters, _root=True) + + def __eq__(self, other): + if not isinstance(other, UnionMeta): + return NotImplemented + return self.__union_set_params__ == other.__union_set_params__ + + def __hash__(self): + return hash(self.__union_set_params__) + + def __instancecheck__(self, instance): + return (self.__union_set_params__ is not None and + any(isinstance(instance, t) for t in self.__union_params__)) + + def __subclasscheck__(self, cls): + if cls is Any: + return True + if self.__union_params__ is None: + return isinstance(cls, UnionMeta) + elif isinstance(cls, UnionMeta): + if cls.__union_params__ is None: + return False + return all(issubclass(c, self) for c in (cls.__union_params__)) + elif isinstance(cls, TypeVar): + if cls in self.__union_params__: + return True + if cls.__constraints__: + return issubclass(Union[cls.__constraints__], self) + return False + else: + return any(issubclass(cls, t) for t in self.__union_params__) + + +class Union(Final, metaclass=UnionMeta, _root=True): + """Union type; Union[X, Y] means either X or Y. + + To define a union, use e.g. Union[int, str]. Details: + + - The arguments must be types and there must be at least one. + + - None as an argument is a special case and is replaced by + type(None). + + - Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + - Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + - Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + - When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + - When two arguments have a subclass relationship, the least + derived argument is kept, e.g.:: + + class Employee: pass + class Manager(Employee): pass + Union[int, Employee, Manager] == Union[int, Employee] + Union[Manager, int, Employee] == Union[int, Employee] + Union[Employee, Manager] == Employee + + - Corollary: if Any is present it is the sole survivor, e.g.:: + + Union[int, Any] == Any + + - Similar for object:: + + Union[int, object] == object + + - To cut a tie: Union[object, Any] == Union[Any, object] == Any. + + - You cannot subclass or instantiate a union. + + - You cannot write Union[X][Y] (what would it mean?). + + - You can use Optional[X] as a shorthand for Union[X, None]. + """ + + # Unsubscripted Union type has params set to None. + __union_params__ = None + __union_set_params__ = None + + +class OptionalMeta(TypingMeta): + """Metaclass for Optional.""" + + def __new__(cls, name, bases, namespace, _root=False): + return super().__new__(cls, name, bases, namespace, _root=_root) + + def __getitem__(self, arg): + arg = _type_check(arg, "Optional[t] requires a single type.") + return Union[arg, type(None)] + + +class Optional(Final, metaclass=OptionalMeta, _root=True): + """Optional type. + + Optional[X] is equivalent to Union[X, type(None)]. + """ + + +class TupleMeta(TypingMeta): + """Metaclass for Tuple.""" + + def __new__(cls, name, bases, namespace, parameters=None, + use_ellipsis=False, _root=False): + self = super().__new__(cls, name, bases, namespace, _root=_root) + self.__tuple_params__ = parameters + self.__tuple_use_ellipsis__ = use_ellipsis + return self + + def _has_type_var(self): + if self.__tuple_params__: + for t in self.__tuple_params__: + if _has_type_var(t): + return True + return False + + def _eval_type(self, globalns, localns): + tp = self.__tuple_params__ + if tp is None: + return self + p = tuple(_eval_type(t, globalns, localns) for t in tp) + if p == self.__tuple_params__: + return self + else: + return self.__class__(self.__name__, self.__bases__, {}, + p, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__tuple_params__ is not None: + params = [_type_repr(p) for p in self.__tuple_params__] + if self.__tuple_use_ellipsis__: + params.append('...') + r += '[%s]' % ( + ', '.join(params)) + return r + + def __getitem__(self, parameters): + if self.__tuple_params__ is not None: + raise TypeError("Cannot re-parameterize %r" % (self,)) + if not isinstance(parameters, tuple): + parameters = (parameters,) + if len(parameters) == 2 and parameters[1] == Ellipsis: + parameters = parameters[:1] + use_ellipsis = True + msg = "Tuple[t, ...]: t must be a type." + else: + use_ellipsis = False + msg = "Tuple[t0, t1, ...]: each t must be a type." + parameters = tuple(_type_check(p, msg) for p in parameters) + return self.__class__(self.__name__, self.__bases__, + dict(self.__dict__), parameters, + use_ellipsis=use_ellipsis, _root=True) + + def __eq__(self, other): + if not isinstance(other, TupleMeta): + return NotImplemented + return self.__tuple_params__ == other.__tuple_params__ + + def __hash__(self): + return hash(self.__tuple_params__) + + def __instancecheck__(self, t): + if not isinstance(t, tuple): + return False + if self.__tuple_params__ is None: + return True + if self.__tuple_use_ellipsis__: + p = self.__tuple_params__[0] + return all(isinstance(x, p) for x in t) + else: + return (len(t) == len(self.__tuple_params__) and + all(isinstance(x, p) + for x, p in zip(t, self.__tuple_params__))) + + def __subclasscheck__(self, cls): + if cls is Any: + return True + if not isinstance(cls, type): + return super().__subclasscheck__(cls) # To TypeError. + if issubclass(cls, tuple): + return True # Special case. + if not isinstance(cls, TupleMeta): + return super().__subclasscheck__(cls) # False. + if self.__tuple_params__ is None: + return True + if cls.__tuple_params__ is None: + return False # ??? + if cls.__tuple_use_ellipsis__ != self.__tuple_use_ellipsis__: + return False + # Covariance. + return (len(self.__tuple_params__) == len(cls.__tuple_params__) and + all(issubclass(x, p) + for x, p in zip(cls.__tuple_params__, + self.__tuple_params__))) + + +class Tuple(Final, metaclass=TupleMeta, _root=True): + """Tuple type; Tuple[X, Y] is the cross-product type of X and Y. + + Example: Tuple[T1, T2] is a tuple of two elements corresponding + to type variables T1 and T2. Tuple[int, float, str] is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, use Sequence[T]. + """ + + +class CallableMeta(TypingMeta): + """Metaclass for Callable.""" + + def __new__(cls, name, bases, namespace, _root=False, + args=None, result=None): + if args is None and result is None: + pass # Must be 'class Callable'. + else: + if args is not Ellipsis: + if not isinstance(args, list): + raise TypeError("Callable[args, result]: " + "args must be a list." + " Got %.100r." % (args,)) + msg = "Callable[[arg, ...], result]: each arg must be a type." + args = tuple(_type_check(arg, msg) for arg in args) + msg = "Callable[args, result]: result must be a type." + result = _type_check(result, msg) + self = super().__new__(cls, name, bases, namespace, _root=_root) + self.__args__ = args + self.__result__ = result + return self + + def _has_type_var(self): + if self.__args__: + for t in self.__args__: + if _has_type_var(t): + return True + return _has_type_var(self.__result__) + + def _eval_type(self, globalns, localns): + if self.__args__ is None and self.__result__ is None: + return self + args = [_eval_type(t, globalns, localns) for t in self.__args__] + result = _eval_type(self.__result__, globalns, localns) + if args == self.__args__ and result == self.__result__: + return self + else: + return self.__class__(self.__name__, self.__bases__, {}, + args=args, result=result, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__args__ is not None or self.__result__ is not None: + if self.__args__ is Ellipsis: + args_r = '...' + else: + args_r = '[%s]' % ', '.join(_type_repr(t) + for t in self.__args__) + r += '[%s, %s]' % (args_r, _type_repr(self.__result__)) + return r + + def __getitem__(self, parameters): + if self.__args__ is not None or self.__result__ is not None: + raise TypeError("This Callable type is already parameterized.") + if not isinstance(parameters, tuple) or len(parameters) != 2: + raise TypeError( + "Callable must be used as Callable[[arg, ...], result].") + args, result = parameters + return self.__class__(self.__name__, self.__bases__, + dict(self.__dict__), _root=True, + args=args, result=result) + + def __eq__(self, other): + if not isinstance(other, CallableMeta): + return NotImplemented + return (self.__args__ == other.__args__ and + self.__result__ == other.__result__) + + def __hash__(self): + return hash(self.__args__) ^ hash(self.__result__) + + def __instancecheck__(self, instance): + if not callable(instance): + return False + if self.__args__ is None and self.__result__ is None: + return True + assert self.__args__ is not None + assert self.__result__ is not None + my_args, my_result = self.__args__, self.__result__ + import inspect # TODO: Avoid this import. + # Would it be better to use Signature objects? + try: + (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, + annotations) = inspect.getfullargspec(instance) + except TypeError: + return False # We can't find the signature. Give up. + msg = ("When testing isinstance(, Callable[...], " + "'s annotations must be types.") + if my_args is not Ellipsis: + if kwonlyargs and (not kwonlydefaults or + len(kwonlydefaults) < len(kwonlyargs)): + return False + if isinstance(instance, types.MethodType): + # For methods, getfullargspec() includes self/cls, + # but it's not part of the call signature, so drop it. + del args[0] + min_call_args = len(args) + if defaults: + min_call_args -= len(defaults) + if varargs: + max_call_args = 999999999 + if len(args) < len(my_args): + args += [varargs] * (len(my_args) - len(args)) + else: + max_call_args = len(args) + if not min_call_args <= len(my_args) <= max_call_args: + return False + for my_arg_type, name in zip(my_args, args): + if name in annotations: + annot_type = _type_check(annotations[name], msg) + else: + annot_type = Any + if not issubclass(my_arg_type, annot_type): + return False + # TODO: If mutable type, check invariance? + if 'return' in annotations: + annot_return_type = _type_check(annotations['return'], msg) + # Note contravariance here! + if not issubclass(annot_return_type, my_result): + return False + # Can't find anything wrong... + return True + + def __subclasscheck__(self, cls): + if cls is Any: + return True + if not isinstance(cls, CallableMeta): + return super().__subclasscheck__(cls) + if self.__args__ is None and self.__result__ is None: + return True + # We're not doing covariance or contravariance -- this is *invariance*. + return self == cls + + +class Callable(Final, metaclass=CallableMeta, _root=True): + """Callable type; Callable[[int], str] is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + """ + + +def _gorg(a): + """Return the farthest origin of a generic class.""" + assert isinstance(a, GenericMeta) + while a.__origin__ is not None: + a = a.__origin__ + return a + + +def _geqv(a, b): + """Return whether two generic classes are equivalent. + + The intention is to consider generic class X and any of its + parameterized forms (X[T], X[int], etc.) as equivalent. + + However, X is not equivalent to a subclass of X. + + The relation is reflexive, symmetric and transitive. + """ + assert isinstance(a, GenericMeta) and isinstance(b, GenericMeta) + # Reduce each to its origin. + return _gorg(a) is _gorg(b) + + +class GenericMeta(TypingMeta, abc.ABCMeta): + """Metaclass for generic types.""" + + # TODO: Constrain more how Generic is used; only a few + # standard patterns should be allowed. + + # TODO: Use a more precise rule than matching __name__ to decide + # whether two classes are the same. Also, save the formal + # parameters. (These things are related! A solution lies in + # using origin.) + + __extra__ = None + + def __new__(cls, name, bases, namespace, + parameters=None, origin=None, extra=None): + if parameters is None: + # Extract parameters from direct base classes. Only + # direct bases are considered and only those that are + # themselves generic, and parameterized with type + # variables. Don't use bases like Any, Union, Tuple, + # Callable or type variables. + params = None + for base in bases: + if isinstance(base, TypingMeta): + if not isinstance(base, GenericMeta): + raise TypeError( + "You cannot inherit from magic class %s" % + repr(base)) + if base.__parameters__ is None: + continue # The base is unparameterized. + for bp in base.__parameters__: + if _has_type_var(bp) and not isinstance(bp, TypeVar): + raise TypeError( + "Cannot inherit from a generic class " + "parameterized with " + "non-type-variable %s" % bp) + if params is None: + params = [] + if bp not in params: + params.append(bp) + if params is not None: + parameters = tuple(params) + self = super().__new__(cls, name, bases, namespace, _root=True) + self.__parameters__ = parameters + if extra is not None: + self.__extra__ = extra + # Else __extra__ is inherited, eventually from the + # (meta-)class default above. + self.__origin__ = origin + return self + + def _has_type_var(self): + if self.__parameters__: + for t in self.__parameters__: + if _has_type_var(t): + return True + return False + + def __repr__(self): + r = super().__repr__() + if self.__parameters__ is not None: + r += '[%s]' % ( + ', '.join(_type_repr(p) for p in self.__parameters__)) + return r + + def __eq__(self, other): + if not isinstance(other, GenericMeta): + return NotImplemented + return (_geqv(self, other) and + self.__parameters__ == other.__parameters__) + + def __hash__(self): + return hash((self.__name__, self.__parameters__)) + + def __getitem__(self, params): + if not isinstance(params, tuple): + params = (params,) + if not params: + raise TypeError("Cannot have empty parameter list") + msg = "Parameters to generic types must be types." + params = tuple(_type_check(p, msg) for p in params) + if self.__parameters__ is None: + for p in params: + if not isinstance(p, TypeVar): + raise TypeError("Initial parameters must be " + "type variables; got %s" % p) + else: + if len(params) != len(self.__parameters__): + raise TypeError("Cannot change parameter count from %d to %d" % + (len(self.__parameters__), len(params))) + for new, old in zip(params, self.__parameters__): + if isinstance(old, TypeVar): + if not old.__constraints__: + # Substituting for an unconstrained TypeVar is OK. + continue + if issubclass(new, Union[old.__constraints__]): + # Specializing a constrained type variable is OK. + continue + if not issubclass(new, old): + raise TypeError( + "Cannot substitute %s for %s in %s" % + (_type_repr(new), _type_repr(old), self)) + + return self.__class__(self.__name__, self.__bases__, + dict(self.__dict__), + parameters=params, + origin=self, + extra=self.__extra__) + + def __subclasscheck__(self, cls): + if cls is Any: + return True + if isinstance(cls, GenericMeta): + # For a class C(Generic[T]) where T is co-variant, + # C[X] is a subclass of C[Y] iff X is a subclass of Y. + origin = self.__origin__ + if origin is not None and origin is cls.__origin__: + assert len(self.__parameters__) == len(origin.__parameters__) + assert len(cls.__parameters__) == len(origin.__parameters__) + for p_self, p_cls, p_origin in zip(self.__parameters__, + cls.__parameters__, + origin.__parameters__): + if isinstance(p_origin, TypeVar): + if p_origin.__covariant__: + # Covariant -- p_cls must be a subclass of p_self. + if not issubclass(p_cls, p_self): + break + elif p_origin.__contravariant__: + # Contravariant. I think it's the opposite. :-) + if not issubclass(p_self, p_cls): + break + else: + # Invariant -- p_cls and p_self must equal. + if p_self != p_cls: + break + else: + # If the origin's parameter is not a typevar, + # insist on invariance. + if p_self != p_cls: + break + else: + return True + # If we break out of the loop, the superclass gets a chance. + if super().__subclasscheck__(cls): + return True + if self.__extra__ is None or isinstance(cls, GenericMeta): + return False + return issubclass(cls, self.__extra__) + + def __instancecheck__(self, obj): + if super().__instancecheck__(obj): + return True + if self.__extra__ is None: + return False + return isinstance(obj, self.__extra__) + + +class Generic(metaclass=GenericMeta): + """Abstract base class for generic types. + + A generic type is typically declared by inheriting from an + instantiation of this class with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + def lookup_name(mapping: Mapping, key: KT, default: VT) -> VT: + try: + return mapping[key] + except KeyError: + return default + + For clarity the type variables may be redefined, e.g.:: + + X = TypeVar('X') + Y = TypeVar('Y') + def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: + # Same body as above. + """ + + def __new__(cls, *args, **kwds): + next_in_mro = object + # Look for the last occurrence of Generic or Generic[...]. + for i, c in enumerate(cls.__mro__[:-1]): + if isinstance(c, GenericMeta) and _gorg(c) is Generic: + next_in_mro = cls.__mro__[i+1] + return next_in_mro.__new__(_gorg(cls)) + + +def cast(typ, val): + """Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + """ + return val + + +def _get_defaults(func): + """Internal helper to extract the default arguments, by name.""" + code = func.__code__ + pos_count = code.co_argcount + kw_count = code.co_kwonlyargcount + arg_names = code.co_varnames + kwarg_names = arg_names[pos_count:pos_count + kw_count] + arg_names = arg_names[:pos_count] + defaults = func.__defaults__ or () + kwdefaults = func.__kwdefaults__ + res = dict(kwdefaults) if kwdefaults else {} + pos_offset = pos_count - len(defaults) + for name, value in zip(arg_names[pos_offset:], defaults): + assert name not in res + res[name] = value + return res + + +def get_type_hints(obj, globalns=None, localns=None): + """Return type hints for a function or method object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, and if necessary + adds Optional[t] if a default value equal to None is set. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj, and these are also used as the locals. If the + object does not appear to have globals, an exception is raised. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + if getattr(obj, '__no_type_check__', None): + return {} + if globalns is None: + globalns = getattr(obj, '__globals__', {}) + if localns is None: + localns = globalns + elif localns is None: + localns = globalns + defaults = _get_defaults(obj) + hints = dict(obj.__annotations__) + for name, value in hints.items(): + if isinstance(value, str): + value = _ForwardRef(value) + value = _eval_type(value, globalns, localns) + if name in defaults and defaults[name] is None: + value = Optional[value] + hints[name] = value + return hints + + +# TODO: Also support this as a class decorator. +def no_type_check(arg): + """Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods defined in that class (but not + to methods defined in its superclasses or subclasses). + + This mutates the function(s) in place. + """ + if isinstance(arg, type): + for obj in arg.__dict__.values(): + if isinstance(obj, types.FunctionType): + obj.__no_type_check__ = True + else: + arg.__no_type_check__ = True + return arg + + +def no_type_check_decorator(decorator): + """Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. + """ + + @functools.wraps(decorator) + def wrapped_decorator(*args, **kwds): + func = decorator(*args, **kwds) + func = no_type_check(func) + return func + + return wrapped_decorator + + +def overload(func): + raise RuntimeError("Overloading is only supported in library stubs") + + +class _ProtocolMeta(GenericMeta): + """Internal metaclass for _Protocol. + + This exists so _Protocol classes can be generic without deriving + from Generic. + """ + + def __subclasscheck__(self, cls): + if not self._is_protocol: + # No structural checks since this isn't a protocol. + return NotImplemented + + if self is _Protocol: + # Every class is a subclass of the empty protocol. + return True + + # Find all attributes defined in the protocol. + attrs = self._get_protocol_attrs() + + for attr in attrs: + if not any(attr in d.__dict__ for d in cls.__mro__): + return False + return True + + def _get_protocol_attrs(self): + # Get all Protocol base classes. + protocol_bases = [] + for c in self.__mro__: + if getattr(c, '_is_protocol', False) and c.__name__ != '_Protocol': + protocol_bases.append(c) + + # Get attributes included in protocol. + attrs = set() + for base in protocol_bases: + for attr in base.__dict__.keys(): + # Include attributes not defined in any non-protocol bases. + for c in self.__mro__: + if (c is not base and attr in c.__dict__ and + not getattr(c, '_is_protocol', False)): + break + else: + if (not attr.startswith('_abc_') and + attr != '__abstractmethods__' and + attr != '_is_protocol' and + attr != '__dict__' and + attr != '_get_protocol_attrs' and + attr != '__parameters__' and + attr != '__origin__' and + attr != '__module__'): + attrs.add(attr) + + return attrs + + +class _Protocol(metaclass=_ProtocolMeta): + """Internal base class for protocol classes. + + This implements a simple-minded structural isinstance check + (similar but more general than the one-offs in collections.abc + such as Hashable). + """ + + _is_protocol = True + + +# Various ABCs mimicking those in collections.abc. +# A few are simply re-exported for completeness. + +Hashable = collections_abc.Hashable # Not generic. + + +class Iterable(Generic[T_co], extra=collections_abc.Iterable): + pass + + +class Iterator(Iterable[T_co], extra=collections_abc.Iterator): + pass + + +class SupportsInt(_Protocol): + + @abstractmethod + def __int__(self) -> int: + pass + + +class SupportsFloat(_Protocol): + + @abstractmethod + def __float__(self) -> float: + pass + + +class SupportsComplex(_Protocol): + + @abstractmethod + def __complex__(self) -> complex: + pass + + +class SupportsBytes(_Protocol): + + @abstractmethod + def __bytes__(self) -> bytes: + pass + + +class SupportsAbs(_Protocol[T]): + + @abstractmethod + def __abs__(self) -> T: + pass + + +class SupportsRound(_Protocol[T]): + + @abstractmethod + def __round__(self, ndigits: int = 0) -> T: + pass + + +class Reversible(_Protocol[T]): + + @abstractmethod + def __reversed__(self) -> 'Iterator[T]': + pass + + +Sized = collections_abc.Sized # Not generic. + + +class Container(Generic[T_co], extra=collections_abc.Container): + pass + + +# Callable was defined earlier. + + +class AbstractSet(Sized, Iterable[T_co], Container[T_co], + extra=collections_abc.Set): + pass + + +class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet): + pass + + +class Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co], + extra=collections_abc.Mapping): + pass + + +class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping): + pass + + +class Sequence(Sized, Iterable[T_co], Container[T_co], + extra=collections_abc.Sequence): + pass + + +class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence): + pass + + +class ByteString(Sequence[int], extra=collections_abc.ByteString): + pass + + +ByteString.register(type(memoryview(b''))) + + +class _ListMeta(GenericMeta): + + def __instancecheck__(self, obj): + if not super().__instancecheck__(obj): + return False + itemtype = self.__parameters__[0] + for x in obj: + if not isinstance(x, itemtype): + return False + return True + + +class List(list, MutableSequence[T], metaclass=_ListMeta): + + def __new__(cls, *args, **kwds): + if _geqv(cls, List): + raise TypeError("Type List cannot be instantiated; " + "use list() instead") + return list.__new__(cls, *args, **kwds) + + +class _SetMeta(GenericMeta): + + def __instancecheck__(self, obj): + if not super().__instancecheck__(obj): + return False + itemtype = self.__parameters__[0] + for x in obj: + if not isinstance(x, itemtype): + return False + return True + + +class Set(set, MutableSet[T], metaclass=_SetMeta): + + def __new__(cls, *args, **kwds): + if _geqv(cls, Set): + raise TypeError("Type Set cannot be instantiated; " + "use set() instead") + return set.__new__(cls, *args, **kwds) + + +class _FrozenSetMeta(_SetMeta): + """This metaclass ensures set is not a subclass of FrozenSet. + + Without this metaclass, set would be considered a subclass of + FrozenSet, because FrozenSet.__extra__ is collections.abc.Set, and + set is a subclass of that. + """ + + def __subclasscheck__(self, cls): + if issubclass(cls, Set): + return False + return super().__subclasscheck__(cls) + + def __instancecheck__(self, obj): + if issubclass(obj.__class__, Set): + return False + return super().__instancecheck__(obj) + + +class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta): + + def __new__(cls, *args, **kwds): + if _geqv(cls, FrozenSet): + raise TypeError("Type FrozenSet cannot be instantiated; " + "use frozenset() instead") + return frozenset.__new__(cls, *args, **kwds) + + +class MappingView(Sized, Iterable[T_co], extra=collections_abc.MappingView): + pass + + +class KeysView(MappingView[KT_co], AbstractSet[KT_co], + extra=collections_abc.KeysView): + pass + + +# TODO: Enable Set[Tuple[KT_co, VT_co]] instead of Generic[KT_co, VT_co]. +class ItemsView(MappingView, Generic[KT_co, VT_co], + extra=collections_abc.ItemsView): + pass + + +class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView): + pass + + +class _DictMeta(GenericMeta): + + def __instancecheck__(self, obj): + if not super().__instancecheck__(obj): + return False + keytype, valuetype = self.__parameters__ + for key, value in obj.items(): + if not (isinstance(key, keytype) and + isinstance(value, valuetype)): + return False + return True + + +class Dict(dict, MutableMapping[KT, VT], metaclass=_DictMeta): + + def __new__(cls, *args, **kwds): + if _geqv(cls, Dict): + raise TypeError("Type Dict cannot be instantiated; " + "use dict() instead") + return dict.__new__(cls, *args, **kwds) + + +# Determine what base class to use for Generator. +if hasattr(collections_abc, 'Generator'): + # Sufficiently recent versions of 3.5 have a Generator ABC. + _G_base = collections_abc.Generator +else: + # Fall back on the exact type. + _G_base = types.GeneratorType + + +class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co], + extra=_G_base): + + def __new__(cls, *args, **kwds): + if _geqv(cls, Generator): + raise TypeError("Type Generator cannot be instantiated; " + "create a subclass instead") + return super().__new__(cls, *args, **kwds) + + +def NamedTuple(typename, fields): + """Typed version of namedtuple. + + Usage:: + + Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) + """ + fields = [(n, t) for n, t in fields] + cls = collections.namedtuple(typename, [n for n, t in fields]) + cls._field_types = dict(fields) + return cls + + +class IO(Generic[AnyStr]): + """Generic base class for TextIO and BinaryIO. + + This is an abstract, generic version of the return of open(). + + NOTE: This does not distinguish between the different possible + classes (text vs. binary, read vs. write vs. read/write, + append-only, unbuffered). The TextIO and BinaryIO subclasses + below capture the distinctions between text vs. binary, which is + pervasive in the interface; however we currently do not offer a + way to track the other distinctions in the type system. + """ + + @abstractproperty + def mode(self) -> str: + pass + + @abstractproperty + def name(self) -> str: + pass + + @abstractmethod + def close(self) -> None: + pass + + @abstractmethod + def closed(self) -> bool: + pass + + @abstractmethod + def fileno(self) -> int: + pass + + @abstractmethod + def flush(self) -> None: + pass + + @abstractmethod + def isatty(self) -> bool: + pass + + @abstractmethod + def read(self, n: int = -1) -> AnyStr: + pass + + @abstractmethod + def readable(self) -> bool: + pass + + @abstractmethod + def readline(self, limit: int = -1) -> AnyStr: + pass + + @abstractmethod + def readlines(self, hint: int = -1) -> List[AnyStr]: + pass + + @abstractmethod + def seek(self, offset: int, whence: int = 0) -> int: + pass + + @abstractmethod + def seekable(self) -> bool: + pass + + @abstractmethod + def tell(self) -> int: + pass + + @abstractmethod + def truncate(self, size: int = None) -> int: + pass + + @abstractmethod + def writable(self) -> bool: + pass + + @abstractmethod + def write(self, s: AnyStr) -> int: + pass + + @abstractmethod + def writelines(self, lines: List[AnyStr]) -> None: + pass + + @abstractmethod + def __enter__(self) -> 'IO[AnyStr]': + pass + + @abstractmethod + def __exit__(self, type, value, traceback) -> None: + pass + + +class BinaryIO(IO[bytes]): + """Typed version of the return of open() in binary mode.""" + + @abstractmethod + def write(self, s: Union[bytes, bytearray]) -> int: + pass + + @abstractmethod + def __enter__(self) -> 'BinaryIO': + pass + + +class TextIO(IO[str]): + """Typed version of the return of open() in text mode.""" + + @abstractproperty + def buffer(self) -> BinaryIO: + pass + + @abstractproperty + def encoding(self) -> str: + pass + + @abstractproperty + def errors(self) -> str: + pass + + @abstractproperty + def line_buffering(self) -> bool: + pass + + @abstractproperty + def newlines(self) -> Any: + pass + + @abstractmethod + def __enter__(self) -> 'TextIO': + pass + + +class io: + """Wrapper namespace for IO generic classes.""" + + __all__ = ['IO', 'TextIO', 'BinaryIO'] + IO = IO + TextIO = TextIO + BinaryIO = BinaryIO + +io.__name__ = __name__ + '.io' +sys.modules[io.__name__] = io + + +Pattern = _TypeAlias('Pattern', AnyStr, type(stdlib_re.compile('')), + lambda p: p.pattern) +Match = _TypeAlias('Match', AnyStr, type(stdlib_re.match('', '')), + lambda m: m.re.pattern) + + +class re: + """Wrapper namespace for re type aliases.""" + + __all__ = ['Pattern', 'Match'] + Pattern = Pattern + Match = Match + +re.__name__ = __name__ + '.re' +sys.modules[re.__name__] = re diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,6 +58,8 @@ Library ------- +- Issue #23973: PEP 484: Add the typing module. + - Issue #20035: Replaced the ``tkinter._fix`` module used for setting up the Tcl/Tk environment on Windows with a private function in the ``_tkinter`` module that makes no permanent changes to the environment. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 22:09:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 20:09:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_20438=3A_Adjust_stac?= =?utf-8?q?klevel_of_inspect=2Egetargspec=28=29_warning=2E?= Message-ID: <20150522200954.27955.67489@psf.io> https://hg.python.org/cpython/rev/666e5b554f32 changeset: 96212:666e5b554f32 user: Yury Selivanov date: Fri May 22 16:09:44 2015 -0400 summary: Issue 20438: Adjust stacklevel of inspect.getargspec() warning. files: Lib/inspect.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1034,7 +1034,8 @@ if the func has either annotations or keyword arguments. """ warnings.warn("inspect.getargspec() is deprecated, " - "use inspect.signature() instead", DeprecationWarning) + "use inspect.signature() instead", DeprecationWarning, + stacklevel=2) args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ getfullargspec(func) if kwonlyargs or ann: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 22:28:13 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 20:28:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_20438=3A_Add_a_note_?= =?utf-8?q?about_deprecating_old_inspect_APIs_to_whatsnew=2E?= Message-ID: <20150522202813.16285.53842@psf.io> https://hg.python.org/cpython/rev/621e98bfc74b changeset: 96213:621e98bfc74b user: Yury Selivanov date: Fri May 22 16:28:05 2015 -0400 summary: Issue 20438: Add a note about deprecating old inspect APIs to whatsnew. Also, deprecate formatargspec, formatargvalues, and getargvalues functions. Since we are deprecating 'getfullargspec' function in 3.5 (documentation only, no DeprecationWarning), it makes sense to also deprecate functions designed to be directly used with it. In 3.6 we will remove 'getargsspec' function (was deprecated since Python 3.0), and start raising DeprecationWarnings in other 'getarg*' family of functions. We can remove them in 3.7 or later. Also, it is worth noting, that Signature API does not provide 100% of functionality that deprecated APIs have. It is important to do a soft deprecation of outdated APIs in 3.5 to gather users feedback, and improve Signature object. files: Doc/library/inspect.rst | 21 +++++++++++++++++++-- Doc/whatsnew/3.5.rst | 10 ++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -793,8 +793,10 @@ *n* elements listed in *args*. .. deprecated:: 3.0 - Use :func:`getfullargspec` instead, which provides information about - keyword-only arguments and annotations. + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. This function will be removed + in Python 3.6. .. function:: getfullargspec(func) @@ -834,6 +836,11 @@ are the names of the ``*`` and ``**`` arguments or ``None``. *locals* is the locals dictionary of the given frame. + .. deprecated:: 3.5 + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. + .. function:: formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations[, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]]) @@ -856,6 +863,11 @@ >>> formatargspec(*getfullargspec(f)) '(a: int, b: float)' + .. deprecated:: 3.5 + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. + .. function:: formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue]) @@ -863,6 +875,11 @@ :func:`getargvalues`. The format\* arguments are the corresponding optional formatting functions that are called to turn names and values into strings. + .. deprecated:: 3.5 + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. + .. function:: getmro(cls) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -815,6 +815,16 @@ :meth:`inspect.Signature.from_callable` instead. (Contributed by Yury Selivanov in :issue:`24248`.) +* :func:`inspect.getargspec` is deprecated and scheduled to be removed in + Python 3.6. (See :issue:`20438` for details.) + +* :func:`~inspect.getfullargspec`, :func:`~inspect.getargvalues`, + :func:`~inspect.getcallargs`, :func:`~inspect.getargvalues`, + :func:`~inspect.formatargspec`, and :func:`~inspect.formatargvalues` are + deprecated in favor of :func:`inspect.signature` API. (See :issue:`20438` + for details.) + + Deprecated functions and types of the C API ------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 22 23:45:53 2015 From: python-checkins at python.org (eric.snow) Date: Fri, 22 May 2015 21:45:53 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_The_PEP_is_accepte?= =?utf-8?q?d=2E?= Message-ID: <20150522214552.126970.6375@psf.io> https://hg.python.org/peps/rev/1fbc23a1078c changeset: 5874:1fbc23a1078c user: Eric Snow date: Fri May 22 15:45:38 2015 -0600 summary: PEP 489: The PEP is accepted. files: pep-0489.txt | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -7,13 +7,13 @@ Nick Coghlan BDFL-Delegate: Eric Snow Discussions-To: import-sig at python.org -Status: Draft +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 11-Aug-2013 Python-Version: 3.5 -Post-History: 23-Aug-2013, 20-Feb-2015, 16-Apr-2015 -Resolution: +Post-History: 23-Aug-2013, 20-Feb-2015, 16-Apr-2015, 7-May-2015, 18-May-2015 +Resolution: https://mail.python.org/pipermail/python-dev/2015-May/140108.html Abstract @@ -730,8 +730,13 @@ * PyModuleDef_Slot +Other changes: + PyModuleDef.m_reload changes to PyModuleDef.m_slots. +``BuiltinImporter`` and ``ExtensionFileLoader`` will now implement +``create_module`` and ``exec_module``. + The internal ``_imp`` module will have backwards incompatible changes: ``create_builtin``, ``create_dynamic``, and ``exec_dynamic`` will be added; ``init_builtin``, ``load_dynamic`` will be removed. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 23 00:08:56 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 22 May 2015 22:08:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24244=3A_Prevents_te?= =?utf-8?q?rmination_when_an_invalid_format_string_is_encountered?= Message-ID: <20150522220856.16717.86147@psf.io> https://hg.python.org/cpython/rev/254b8e68959e changeset: 96214:254b8e68959e user: Steve Dower date: Fri May 22 15:08:34 2015 -0700 summary: Issue 24244: Prevents termination when an invalid format string is encountered on Windows. files: Misc/NEWS | 3 +++ Modules/timemodule.c | 9 ++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,6 +58,9 @@ Library ------- +- Issue 24244: Prevents termination when an invalid format string is + encountered on Windows in strftime. + - Issue #23973: PEP 484: Add the typing module. - Issue #20035: Replaced the ``tkinter._fix`` module used for setting up the diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -616,13 +616,6 @@ { if (outbuf[1]=='#') ++outbuf; /* not documented by python, */ - if (outbuf[1]=='\0' || - !strchr("aAbBcdHIjmMpSUwWxXyYzZ%", outbuf[1])) - { - PyErr_SetString(PyExc_ValueError, "Invalid format string"); - Py_DECREF(format); - return NULL; - } if ((outbuf[1] == 'y') && buf.tm_year < 0) { PyErr_SetString(PyExc_ValueError, @@ -660,7 +653,9 @@ PyErr_NoMemory(); break; } + _Py_BEGIN_SUPPRESS_IPH buflen = format_time(outbuf, i, fmt, &buf); + _Py_END_SUPPRESS_IPH #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) err = errno; #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 00:16:49 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 22 May 2015 22:16:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323955=3A_Add_pyve?= =?utf-8?q?nv=2Ecfg_option_to_suppress_registry/environment_lookup_for?= Message-ID: <20150522221649.70401.10197@psf.io> https://hg.python.org/cpython/rev/620a247b4960 changeset: 96215:620a247b4960 user: Steve Dower date: Fri May 22 15:10:10 2015 -0700 summary: Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path. Also cleans up and secures getpathp.c files: Doc/using/windows.rst | 21 +++- Misc/NEWS | 3 + PC/getpathp.c | 178 +++++++++++++++++------------ Tools/msi/make_zip.py | 3 + 4 files changed, 127 insertions(+), 78 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -661,6 +661,17 @@ the environment, and no registry entries can be found, a default path with relative entries is used (e.g. ``.\Lib;.\plat-win``, etc). +If a ``pyvenv.cfg`` file is found alongside the main executable or in the +directory one level above the executable, the following variations apply: + +* If ``home`` is an absolute path and :envvar:`PYTHONHOME` is not set, this + path is used instead of the path to the main executable when deducing the + home location. + +* If ``applocal`` is set to true, the ``home`` property or the main executable + is always used as the home path, and all environment variables or registry + values affecting the path are ignored. The landmark file is not checked. + The end result of all this is: * When running :file:`python.exe`, or any other .exe in the main Python @@ -672,13 +683,17 @@ etc), the "Python Home" will not be deduced, so the core path from the registry is used. Other "application paths" in the registry are always read. -* If Python can't find its home and there is no registry (eg, frozen .exe, some - very strange installation setup) you get a path with some default, but +* If Python can't find its home and there are no registry value (frozen .exe, + some very strange installation setup) you get a path with some default, but relative, paths. For those who want to bundle Python into their application or distribution, the following advice will prevent conflicts with other installations: +* Include a ``pyvenv.cfg`` file alongside your executable containing + ``applocal = true``. This will ensure that your own directory will be used to + resolve paths even if you have included the standard library in a ZIP file. + * If you are loading :file:`python3.dll` or :file:`python35.dll` in your own executable, explicitly call :c:func:`Py_SetPath` or (at least) :c:func:`Py_SetProgramName` before :c:func:`Py_Initialize`. @@ -688,7 +703,7 @@ * If you cannot use the previous suggestions (for example, you are a distribution that allows people to run :file:`python.exe` directly), ensure - that the landmark file (:file:`Lib\\os.py`) exists in your bundled library. + that the landmark file (:file:`Lib\\os.py`) exists in your install directory. (Note that it will not be detected inside a ZIP file.) These will ensure that the files in a system-wide installation will not take diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23955: Add pyvenv.cfg option to suppress registry/environment + lookup for generating sys.path on Windows. + - Issue #24257: Fixed system error in the comparison of faked types.SimpleNamespace. diff --git a/PC/getpathp.c b/PC/getpathp.c --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -113,7 +113,10 @@ static void reduce(wchar_t *dir) { - size_t i = wcslen(dir); + size_t i = wcsnlen_s(dir, MAXPATHLEN+1); + if (i >= MAXPATHLEN+1) + Py_FatalError("buffer overflow in getpathp.c's reduce()"); + while (i > 0 && !is_sep(dir[i])) --i; dir[i] = '\0'; @@ -130,16 +133,23 @@ may extend 'filename' by one character. */ static int -ismodule(wchar_t *filename) /* Is module -- check for .pyc/.pyo too */ +ismodule(wchar_t *filename, int update_filename) /* Is module -- check for .pyc/.pyo too */ { + int n; + if (exists(filename)) return 1; /* Check for the compiled version of prefix. */ - if (wcslen(filename) < MAXPATHLEN) { - wcscat(filename, Py_OptimizeFlag ? L"o" : L"c"); - if (exists(filename)) - return 1; + n = wcsnlen_s(filename, MAXPATHLEN+1); + if (n < MAXPATHLEN) { + int exist = 0; + filename[n] = Py_OptimizeFlag ? L'o' : L'c'; + filename[n + 1] = L'\0'; + exist = exists(filename); + if (!update_filename) + filename[n] = L'\0'; + return exist; } return 0; } @@ -154,23 +164,23 @@ stuff as fits will be appended. */ static void -join(wchar_t *buffer, wchar_t *stuff) +join(wchar_t *buffer, const wchar_t *stuff) { - size_t n, k; - if (is_sep(stuff[0])) - n = 0; - else { - n = wcslen(buffer); - if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN) - buffer[n++] = SEP; + size_t n; + if (is_sep(stuff[0]) || + (wcsnlen_s(stuff, 4) >= 3 && stuff[1] == ':' && is_sep(stuff[2]))) { + if (wcscpy_s(buffer, MAXPATHLEN+1, stuff) != 0) + Py_FatalError("buffer overflow in getpathp.c's join()"); + return; } - if (n > MAXPATHLEN) - Py_FatalError("buffer overflow in getpathp.c's joinpath()"); - k = wcslen(stuff); - if (n + k > MAXPATHLEN) - k = MAXPATHLEN - n; - wcsncpy(buffer+n, stuff, k); - buffer[n+k] = '\0'; + + n = wcsnlen_s(buffer, MAXPATHLEN+1); + if (n > 0 && !is_sep(buffer[n - 1]) && n < MAXPATHLEN) { + buffer[n] = SEP; + buffer[n + 1] = '\0'; + } + if (wcscat_s(buffer, MAXPATHLEN+1, stuff) != 0) + Py_FatalError("buffer overflow in getpathp.c's join()"); } /* gotlandmark only called by search_for_prefix, which ensures @@ -181,11 +191,10 @@ gotlandmark(wchar_t *landmark) { int ok; - Py_ssize_t n; + Py_ssize_t n = wcsnlen_s(prefix, MAXPATHLEN); - n = wcslen(prefix); join(prefix, landmark); - ok = ismodule(prefix); + ok = ismodule(prefix, FALSE); prefix[n] = '\0'; return ok; } @@ -196,7 +205,7 @@ search_for_prefix(wchar_t *argv0_path, wchar_t *landmark) { /* Search from argv0_path, until landmark is found */ - wcscpy(prefix, argv0_path); + wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path); do { if (gotlandmark(landmark)) return 1; @@ -236,7 +245,7 @@ WCHAR *dataBuf = NULL; static const WCHAR keyPrefix[] = L"Software\\Python\\PythonCore\\"; static const WCHAR keySuffix[] = L"\\PythonPath"; - size_t versionLen; + size_t versionLen, keyBufLen; DWORD index; WCHAR *keyBuf = NULL; WCHAR *keyBufPtr; @@ -245,12 +254,13 @@ /* Tried to use sysget("winver") but here is too early :-( */ versionLen = strlen(PyWin_DLLVersionString); /* Space for all the chars, plus one \0 */ - keyBuf = keyBufPtr = PyMem_RawMalloc(sizeof(keyPrefix) + - sizeof(WCHAR)*(versionLen-1) + - sizeof(keySuffix)); + keyBufLen = sizeof(keyPrefix) + + sizeof(WCHAR)*(versionLen-1) + + sizeof(keySuffix); + keyBuf = keyBufPtr = PyMem_RawMalloc(keyBufLen); if (keyBuf==NULL) goto done; - memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR)); + memcpy_s(keyBufPtr, keyBufLen, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR)); keyBufPtr += Py_ARRAY_LENGTH(keyPrefix) - 1; mbstowcs(keyBufPtr, PyWin_DLLVersionString, versionLen); keyBufPtr += versionLen; @@ -484,7 +494,7 @@ wchar_t *machinepath = NULL; wchar_t *userpath = NULL; wchar_t zip_path[MAXPATHLEN+1]; - size_t len; + int applocal = 0; if (!Py_IgnoreEnvironmentFlag) { envpath = _wgetenv(L"PYTHONPATH"); @@ -502,7 +512,7 @@ get_progpath(); /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */ - wcscpy(argv0_path, progpath); + wcscpy_s(argv0_path, MAXPATHLEN+1, progpath); reduce(argv0_path); /* Search for an environment configuration file, first in the @@ -511,27 +521,39 @@ */ { + wchar_t envbuffer[MAXPATHLEN+1]; wchar_t tmpbuffer[MAXPATHLEN+1]; - wchar_t *env_cfg = L"pyvenv.cfg"; + const wchar_t *env_cfg = L"pyvenv.cfg"; FILE * env_file = NULL; - wcscpy(tmpbuffer, argv0_path); - join(tmpbuffer, env_cfg); - env_file = _Py_wfopen(tmpbuffer, L"r"); + wcscpy_s(envbuffer, MAXPATHLEN+1, argv0_path); + join(envbuffer, env_cfg); + env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; - reduce(tmpbuffer); - reduce(tmpbuffer); - join(tmpbuffer, env_cfg); - env_file = _Py_wfopen(tmpbuffer, L"r"); + reduce(envbuffer); + reduce(envbuffer); + join(envbuffer, env_cfg); + env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; } } if (env_file != NULL) { + /* Look for an 'applocal' variable and, if true, ignore all registry + * keys and environment variables, but retain the default paths + * (DLLs, Lib) and the zip file. Setting pythonhome here suppresses + * the search for LANDMARK below and overrides %PYTHONHOME%. + */ + if (find_env_config_value(env_file, L"applocal", tmpbuffer) && + (applocal = (wcsicmp(tmpbuffer, L"true") == 0))) { + envpath = NULL; + pythonhome = argv0_path; + } + /* Look for a 'home' variable and set argv0_path to it, if found */ if (find_env_config_value(env_file, L"home", tmpbuffer)) { - wcscpy(argv0_path, tmpbuffer); + wcscpy_s(argv0_path, MAXPATHLEN+1, tmpbuffer); } fclose(env_file); env_file = NULL; @@ -545,33 +567,30 @@ pythonhome = NULL; } else - wcsncpy(prefix, pythonhome, MAXPATHLEN); + wcscpy_s(prefix, MAXPATHLEN+1, pythonhome); if (envpath && *envpath == '\0') envpath = NULL; #ifdef MS_WINDOWS - /* Calculate zip archive path */ - if (dllpath[0]) /* use name of python DLL */ - wcsncpy(zip_path, dllpath, MAXPATHLEN); - else /* use name of executable program */ - wcsncpy(zip_path, progpath, MAXPATHLEN); - zip_path[MAXPATHLEN] = '\0'; - len = wcslen(zip_path); - if (len > 4) { - zip_path[len-3] = 'z'; /* change ending to "zip" */ - zip_path[len-2] = 'i'; - zip_path[len-1] = 'p'; - } + /* Calculate zip archive path from DLL or exe path */ + if (wcscpy_s(zip_path, MAXPATHLEN+1, dllpath[0] ? dllpath : progpath)) + /* exceeded buffer length - ignore zip_path */ + zip_path[0] = '\0'; else { - zip_path[0] = 0; + wchar_t *dot = wcsrchr(zip_path, '.'); + if (!dot || wcscpy_s(dot, MAXPATHLEN+1 - (dot - zip_path), L".zip")) + /* exceeded buffer length - ignore zip_path */ + zip_path[0] = L'\0'; } skiphome = pythonhome==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED - machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome); - userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome); + if (!applocal) { + machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome); + userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome); + } #endif /* We only use the default relative PYTHONPATH if we havent anything better to use! */ @@ -590,6 +609,7 @@ Extra rules: - If PYTHONHOME is set (in any way) item (3) is ignored. - If registry values are used, (4) and (5) are ignored. + - If applocal is set, (1), (3), and registry values are ignored */ /* Calculate size of return buffer */ @@ -600,21 +620,21 @@ if (*p == DELIM) bufsz++; /* number of DELIM plus one */ } - bufsz *= wcslen(pythonhome); + bufsz *= wcsnlen_s(pythonhome, MAXPATHLEN+1); } else bufsz = 0; - bufsz += wcslen(PYTHONPATH) + 1; - bufsz += wcslen(argv0_path) + 1; + bufsz += wcsnlen_s(PYTHONPATH, MAXPATHLEN+1) + 1; + bufsz += wcsnlen_s(argv0_path, MAXPATHLEN+1) + 1; #ifdef MS_WINDOWS - if (userpath) - bufsz += wcslen(userpath) + 1; - if (machinepath) - bufsz += wcslen(machinepath) + 1; - bufsz += wcslen(zip_path) + 1; + if (!applocal && userpath) + bufsz += wcsnlen_s(userpath, MAXPATHLEN+1) + 1; + if (!applocal && machinepath) + bufsz += wcsnlen_s(machinepath, MAXPATHLEN+1) + 1; + bufsz += wcsnlen_s(zip_path, MAXPATHLEN+1) + 1; #endif if (envpath != NULL) - bufsz += wcslen(envpath) + 1; + bufsz += wcsnlen_s(envpath, MAXPATHLEN+1) + 1; module_search_path = buf = PyMem_RawMalloc(bufsz*sizeof(wchar_t)); if (buf == NULL) { @@ -636,38 +656,45 @@ } if (envpath) { - wcscpy(buf, envpath); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), envpath)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } #ifdef MS_WINDOWS if (zip_path[0]) { - wcscpy(buf, zip_path); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), zip_path)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (userpath) { - wcscpy(buf, userpath); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), userpath)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; PyMem_RawFree(userpath); } if (machinepath) { - wcscpy(buf, machinepath); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), machinepath)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; PyMem_RawFree(machinepath); } if (pythonhome == NULL) { if (!skipdefault) { - wcscpy(buf, PYTHONPATH); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), PYTHONPATH)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); + *buf++ = DELIM; } } #else if (pythonhome == NULL) { wcscpy(buf, PYTHONPATH); buf = wcschr(buf, L'\0'); + *buf++ = DELIM; } #endif /* MS_WINDOWS */ else { @@ -681,25 +708,26 @@ else n = q-p; if (p[0] == '.' && is_sep(p[1])) { - wcscpy(buf, pythonhome); + if (wcscpy_s(buf, bufsz - (buf - module_search_path), pythonhome)) + Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); p++; n--; } wcsncpy(buf, p, n); buf += n; + *buf++ = DELIM; if (q == NULL) break; - *buf++ = DELIM; p = q+1; } } if (argv0_path) { - *buf++ = DELIM; wcscpy(buf, argv0_path); buf = wcschr(buf, L'\0'); + *buf++ = DELIM; } - *buf = L'\0'; + *(buf - 1) = L'\0'; /* Now to pull one last hack/trick. If sys.prefix is empty, then try and find it somewhere on the paths we calculated. We scan backwards, as our general policy diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -149,6 +149,9 @@ copied = copy_to_layout(temp / t.rstrip('/'), rglob(s, p, c)) print('Copied {} files'.format(copied)) + with open(str(temp / 'pyvenv.cfg'), 'w') as f: + print('applocal = true', file=f) + total = copy_to_layout(out, rglob(temp, '*', None)) print('Wrote {} files to {}'.format(total, out)) finally: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 00:46:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 22 May 2015 22:46:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-478=3A_Promote_PEPs_484_?= =?utf-8?q?=26_489_to_Implemented/Final_section?= Message-ID: <20150522224641.126966.92846@psf.io> https://hg.python.org/peps/rev/4c8727bc8e47 changeset: 5875:4c8727bc8e47 user: Yury Selivanov date: Fri May 22 18:46:38 2015 -0400 summary: pep-478: Promote PEPs 484 & 489 to Implemented/Final section files: pep-0478.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -67,6 +67,8 @@ * PEP 475, retrying system calls that fail with EINTR * PEP 492, coroutines with async and await syntax * PEP 488, elimination of PYO files +* PEP 484, type hints +* PEP 489, redesigning extension module loading Accepted PEPs: @@ -74,8 +76,6 @@ Proposed changes for 3.5: -* PEP 484, type hints -* PEP 489, redesigning extension module loading * PEP 431, improved support for time zone databases * PEP 432, simplifying Python's startup sequence * PEP 436, a build tool generating boilerplate for extension modules -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 23 00:55:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 22 May 2015 22:55:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge_2=2E7=2E10_release_branch?= Message-ID: <20150522225527.27935.31784@psf.io> https://hg.python.org/cpython/rev/dce981bac5da changeset: 96217:dce981bac5da branch: 2.7 parent: 96203:bccaba8a5482 parent: 96216:117af4bc0513 user: Benjamin Peterson date: Fri May 22 17:55:22 2015 -0500 summary: merge 2.7.10 release branch files: Lib/idlelib/idlever.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,4 @@ -IDLE_VERSION = "2.7.10rc1" +"""Unused by Idle: there is no separate Idle version anymore. +Kept only for possible existing extension use.""" +from sys import version +IDLE_VERSION = version[:version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 00:55:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 22 May 2015 22:55:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_make_idlever?= =?utf-8?q?=2Epy_self-updating_=28closes_=2324199=29?= Message-ID: <20150522225527.45377.19@psf.io> https://hg.python.org/cpython/rev/117af4bc0513 changeset: 96216:117af4bc0513 branch: 2.7 parent: 96062:7adfc99103d2 user: Benjamin Peterson date: Fri May 22 17:53:06 2015 -0500 summary: make idlever.py self-updating (closes #24199) files: Lib/idlelib/idlever.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,4 @@ -IDLE_VERSION = "2.7.10rc1" +"""Unused by Idle: there is no separate Idle version anymore. +Kept only for possible existing extension use.""" +from sys import version +IDLE_VERSION = version[:version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 00:56:02 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 22 May 2015 22:56:02 +0000 Subject: [Python-checkins] =?utf-8?q?release=3A_stop_updating_idlever=2Epy?= =?utf-8?b?ICgjMjQxOTkp?= Message-ID: <20150522225602.70429.64375@psf.io> https://hg.python.org/release/rev/ab27d3fc0e64 changeset: 95:ab27d3fc0e64 user: Benjamin Peterson date: Fri May 22 17:55:56 2015 -0500 summary: stop updating idlever.py (#24199) files: release.py | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-) diff --git a/release.py b/release.py --- a/release.py +++ b/release.py @@ -138,12 +138,6 @@ tweak_patchlevel(tag) - print('Updating Lib/idlelib/idlever.py...', end=' ') - with open('Lib/idlelib/idlever.py', 'w', encoding="ascii") as fp: - new = 'IDLE_VERSION = "%s"\n' % tag.text - fp.write(new) - print('done') - print('Updating Lib/distutils/__init__.py...', end=' ') new = '__version__ = "%s"' % tag.text constant_replace('Lib/distutils/__init__.py', new, '#', '') -- Repository URL: https://hg.python.org/release From python-checkins at python.org Sat May 23 01:18:30 2015 From: python-checkins at python.org (gregory.p.smith) Date: Fri, 22 May 2015 23:18:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24230=3A_The_tempfil?= =?utf-8?q?e_module_now_accepts_bytes_for_prefix=2C_suffix_and_dir?= Message-ID: <20150522231830.17939.34602@psf.io> https://hg.python.org/cpython/rev/870899ce71f4 changeset: 96218:870899ce71f4 parent: 96215:620a247b4960 user: Gregory P. Smith date: Fri May 22 16:18:14 2015 -0700 summary: Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). files: Doc/library/tempfile.rst | 37 +++++- Doc/whatsnew/3.5.rst | 7 +- Lib/tempfile.py | 115 +++++++++++++---- Lib/test/test_tempfile.py | 169 ++++++++++++++++++++++--- Misc/NEWS | 3 + 5 files changed, 281 insertions(+), 50 deletions(-) diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -119,7 +119,7 @@ .. versionadded:: 3.2 -.. function:: mkstemp(suffix='', prefix='tmp', dir=None, text=False) +.. function:: mkstemp(suffix=None, prefix=None, dir=None, text=False) Creates a temporary file in the most secure manner possible. There are no race conditions in the file's creation, assuming that the platform @@ -148,6 +148,16 @@ filename will have any nice properties, such as not requiring quoting when passed to external commands via ``os.popen()``. + *suffix*, *prefix*, and *dir* must all contain the same type, if specified. + If they are bytes, the returned name will be bytes instead of str. + If you want to force a bytes return value with otherwise default behavior, + pass ``suffix=b''``. + + A *prefix* value of ``None`` means use the return value of + :func:`gettempprefix` or :func:`gettempprefixb` as appropriate. + + A *suffix* value of ``None`` means use an appropriate empty value. + If *text* is specified, it indicates whether to open the file in binary mode (the default) or text mode. On some platforms, this makes no difference. @@ -156,8 +166,14 @@ file (as would be returned by :func:`os.open`) and the absolute pathname of that file, in that order. + .. versionchanged:: 3.5 + *suffix*, *prefix*, and *dir* may now be supplied in bytes in order to + obtain a bytes return value. Prior to this, only str was allowed. + *suffix* and *prefix* now accept and default to ``None`` to cause + an appropriate default value to be used. -.. function:: mkdtemp(suffix='', prefix='tmp', dir=None) + +.. function:: mkdtemp(suffix=None, prefix=None, dir=None) Creates a temporary directory in the most secure manner possible. There are no race conditions in the directory's creation. The directory is @@ -171,6 +187,12 @@ :func:`mkdtemp` returns the absolute pathname of the new directory. + .. versionchanged:: 3.5 + *suffix*, *prefix*, and *dir* may now be supplied in bytes in order to + obtain a bytes return value. Prior to this, only str was allowed. + *suffix* and *prefix* now accept and default to ``None`` to cause + an appropriate default value to be used. + .. function:: mktemp(suffix='', prefix='tmp', dir=None) @@ -239,12 +261,23 @@ :data:`tempdir` is not ``None``, this simply returns its contents; otherwise, the search described above is performed, and the result returned. +.. function:: gettempdirb() + + Same as :func:`gettempdir` but the return value is in bytes. + + .. versionadded:: 3.5 .. function:: gettempprefix() Return the filename prefix used to create temporary files. This does not contain the directory component. +.. function:: gettempprefixb() + + Same as :func:`gettempprefixb` but the return value is in bytes. + + .. versionadded:: 3.5 + Examples -------- diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -96,7 +96,12 @@ Significantly Improved Library Modules: -* None yet. +* You may now pass bytes to the :mod:`tempfile` module's APIs and it will + return the temporary pathname as bytes instead of str. It also accepts + a value of ``None`` on parameters where only str was accepted in the past to + do the right thing based on the types of the other inputs. Two functions, + :func:`gettempdirb` and :func:`gettempprefixb`, have been added to go along + with this. This behavior matches that of the :mod:`os` APIs. Security improvements: diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -6,6 +6,14 @@ except for 'mktemp'. 'mktemp' is subject to race conditions and should not be used; it is provided for backward compatibility only. +The default path names are returned as str. If you supply bytes as +input, all return values will be in bytes. Ex: + + >>> tempfile.mkstemp() + (4, '/tmp/tmptpu9nin8') + >>> tempfile.mkdtemp(suffix=b'') + b'/tmp/tmppbi8f0hy' + This module also provides some data items to the user: TMP_MAX - maximum number of names that will be tried before @@ -21,7 +29,8 @@ "mkstemp", "mkdtemp", # low level safe interfaces "mktemp", # deprecated unsafe interface "TMP_MAX", "gettempprefix", # constants - "tempdir", "gettempdir" + "tempdir", "gettempdir", + "gettempprefixb", "gettempdirb", ] @@ -55,8 +64,10 @@ else: TMP_MAX = 10000 -# Although it does not have an underscore for historical reasons, this -# variable is an internal implementation detail (see issue 10354). +# This variable _was_ unused for legacy reasons, see issue 10354. +# But as of 3.5 we actually use it at runtime so changing it would +# have a possibly desirable side effect... But we do not want to support +# that as an API. It is undocumented on purpose. Do not depend on this. template = "tmp" # Internal routines. @@ -82,6 +93,46 @@ else: return True + +def _infer_return_type(*args): + """Look at the type of all args and divine their implied return type.""" + return_type = None + for arg in args: + if arg is None: + continue + if isinstance(arg, bytes): + if return_type is str: + raise TypeError("Can't mix bytes and non-bytes in " + "path components.") + return_type = bytes + else: + if return_type is bytes: + raise TypeError("Can't mix bytes and non-bytes in " + "path components.") + return_type = str + if return_type is None: + return str # tempfile APIs return a str by default. + return return_type + + +def _sanitize_params(prefix, suffix, dir): + """Common parameter processing for most APIs in this module.""" + output_type = _infer_return_type(prefix, suffix, dir) + if suffix is None: + suffix = output_type() + if prefix is None: + if output_type is str: + prefix = template + else: + prefix = _os.fsencode(template) + if dir is None: + if output_type is str: + dir = gettempdir() + else: + dir = gettempdirb() + return prefix, suffix, dir, output_type + + class _RandomNameSequence: """An instance of _RandomNameSequence generates an endless sequence of unpredictable strings which can safely be incorporated @@ -195,17 +246,18 @@ return _name_sequence -def _mkstemp_inner(dir, pre, suf, flags): +def _mkstemp_inner(dir, pre, suf, flags, output_type): """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" names = _get_candidate_names() + if output_type is bytes: + names = map(_os.fsencode, names) for seq in range(TMP_MAX): name = next(names) file = _os.path.join(dir, pre + name + suf) try: fd = _os.open(file, flags, 0o600) - return (fd, _os.path.abspath(file)) except FileExistsError: continue # try again except PermissionError: @@ -216,6 +268,7 @@ continue else: raise + return (fd, _os.path.abspath(file)) raise FileExistsError(_errno.EEXIST, "No usable temporary file name found") @@ -224,9 +277,13 @@ # User visible interfaces. def gettempprefix(): - """Accessor for tempdir.template.""" + """The default prefix for temporary directories.""" return template +def gettempprefixb(): + """The default prefix for temporary directories as bytes.""" + return _os.fsencode(gettempprefix()) + tempdir = None def gettempdir(): @@ -241,7 +298,11 @@ _once_lock.release() return tempdir -def mkstemp(suffix="", prefix=template, dir=None, text=False): +def gettempdirb(): + """A bytes version of tempfile.gettempdir().""" + return _os.fsencode(gettempdir()) + +def mkstemp(suffix=None, prefix=None, dir=None, text=False): """User-callable function to create and return a unique temporary file. The return value is a pair (fd, name) where fd is the file descriptor returned by os.open, and name is the filename. @@ -259,6 +320,10 @@ mode. Else (the default) the file is opened in binary mode. On some operating systems, this makes no difference. + suffix, prefix and dir must all contain the same type if specified. + If they are bytes, the returned name will be bytes; str otherwise. + A value of None will cause an appropriate default to be used. + The file is readable and writable only by the creating user ID. If the operating system uses permission bits to indicate whether a file is executable, the file is executable by no one. The file @@ -267,18 +332,17 @@ Caller is responsible for deleting the file when done with it. """ - if dir is None: - dir = gettempdir() + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) if text: flags = _text_openflags else: flags = _bin_openflags - return _mkstemp_inner(dir, prefix, suffix, flags) + return _mkstemp_inner(dir, prefix, suffix, flags, output_type) -def mkdtemp(suffix="", prefix=template, dir=None): +def mkdtemp(suffix=None, prefix=None, dir=None): """User-callable function to create and return a unique temporary directory. The return value is the pathname of the directory. @@ -291,17 +355,17 @@ Caller is responsible for deleting the directory when done with it. """ - if dir is None: - dir = gettempdir() + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) names = _get_candidate_names() + if output_type is bytes: + names = map(_os.fsencode, names) for seq in range(TMP_MAX): name = next(names) file = _os.path.join(dir, prefix + name + suffix) try: _os.mkdir(file, 0o700) - return file except FileExistsError: continue # try again except PermissionError: @@ -312,6 +376,7 @@ continue else: raise + return file raise FileExistsError(_errno.EEXIST, "No usable temporary directory name found") @@ -323,8 +388,8 @@ Arguments are as for mkstemp, except that the 'text' argument is not accepted. - This function is unsafe and should not be used. The file name - refers to a file that did not exist at some point, but by the time + THIS FUNCTION IS UNSAFE AND SHOULD NOT BE USED. The file name may + refer to a file that did not exist at some point, but by the time you get around to creating it, someone else may have beaten you to the punch. """ @@ -454,7 +519,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, - newline=None, suffix="", prefix=template, + newline=None, suffix=None, prefix=None, dir=None, delete=True): """Create and return a temporary file. Arguments: @@ -471,8 +536,7 @@ when it is closed unless the 'delete' argument is set to False. """ - if dir is None: - dir = gettempdir() + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) flags = _bin_openflags @@ -481,7 +545,7 @@ if _os.name == 'nt' and delete: flags |= _os.O_TEMPORARY - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) + (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) try: file = _io.open(fd, mode, buffering=buffering, newline=newline, encoding=encoding) @@ -503,7 +567,7 @@ _O_TMPFILE_WORKS = hasattr(_os, 'O_TMPFILE') def TemporaryFile(mode='w+b', buffering=-1, encoding=None, - newline=None, suffix="", prefix=template, + newline=None, suffix=None, prefix=None, dir=None): """Create and return a temporary file. Arguments: @@ -519,8 +583,7 @@ """ global _O_TMPFILE_WORKS - if dir is None: - dir = gettempdir() + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) flags = _bin_openflags if _O_TMPFILE_WORKS: @@ -544,7 +607,7 @@ raise # Fallback to _mkstemp_inner(). - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) + (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) try: _os.unlink(name) return _io.open(fd, mode, buffering=buffering, @@ -562,7 +625,7 @@ def __init__(self, max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, - suffix="", prefix=template, dir=None): + suffix=None, prefix=None, dir=None): if 'b' in mode: self._file = _io.BytesIO() else: @@ -713,7 +776,7 @@ in it are removed. """ - def __init__(self, suffix="", prefix=template, dir=None): + def __init__(self, suffix=None, prefix=None, dir=None): self.name = mkdtemp(suffix, prefix, dir) self._finalizer = _weakref.finalize( self, self._cleanup, self.name, diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -36,10 +36,38 @@ # in order of their appearance in the file. Testing which requires # threads is not done here. +class TestLowLevelInternals(unittest.TestCase): + def test_infer_return_type_singles(self): + self.assertIs(str, tempfile._infer_return_type('')) + self.assertIs(bytes, tempfile._infer_return_type(b'')) + self.assertIs(str, tempfile._infer_return_type(None)) + + def test_infer_return_type_multiples(self): + self.assertIs(str, tempfile._infer_return_type('', '')) + self.assertIs(bytes, tempfile._infer_return_type(b'', b'')) + with self.assertRaises(TypeError): + tempfile._infer_return_type('', b'') + with self.assertRaises(TypeError): + tempfile._infer_return_type(b'', '') + + def test_infer_return_type_multiples_and_none(self): + self.assertIs(str, tempfile._infer_return_type(None, '')) + self.assertIs(str, tempfile._infer_return_type('', None)) + self.assertIs(str, tempfile._infer_return_type(None, None)) + self.assertIs(bytes, tempfile._infer_return_type(b'', None)) + self.assertIs(bytes, tempfile._infer_return_type(None, b'')) + with self.assertRaises(TypeError): + tempfile._infer_return_type('', None, b'') + with self.assertRaises(TypeError): + tempfile._infer_return_type(b'', None, '') + + # Common functionality. + class BaseTestCase(unittest.TestCase): str_check = re.compile(r"^[a-z0-9_-]{8}$") + b_check = re.compile(br"^[a-z0-9_-]{8}$") def setUp(self): self._warnings_manager = support.check_warnings() @@ -56,18 +84,31 @@ npre = nbase[:len(pre)] nsuf = nbase[len(nbase)-len(suf):] + if dir is not None: + self.assertIs(type(name), str if type(dir) is str else bytes, + "unexpected return type") + if pre is not None: + self.assertIs(type(name), str if type(pre) is str else bytes, + "unexpected return type") + if suf is not None: + self.assertIs(type(name), str if type(suf) is str else bytes, + "unexpected return type") + if (dir, pre, suf) == (None, None, None): + self.assertIs(type(name), str, "default return type must be str") + # check for equality of the absolute paths! self.assertEqual(os.path.abspath(ndir), os.path.abspath(dir), - "file '%s' not in directory '%s'" % (name, dir)) + "file %r not in directory %r" % (name, dir)) self.assertEqual(npre, pre, - "file '%s' does not begin with '%s'" % (nbase, pre)) + "file %r does not begin with %r" % (nbase, pre)) self.assertEqual(nsuf, suf, - "file '%s' does not end with '%s'" % (nbase, suf)) + "file %r does not end with %r" % (nbase, suf)) nbase = nbase[len(pre):len(nbase)-len(suf)] - self.assertTrue(self.str_check.match(nbase), - "random string '%s' does not match ^[a-z0-9_-]{8}$" - % nbase) + check = self.str_check if isinstance(nbase, str) else self.b_check + self.assertTrue(check.match(nbase), + "random characters %r do not match %r" + % (nbase, check.pattern)) class TestExports(BaseTestCase): @@ -83,7 +124,9 @@ "mktemp" : 1, "TMP_MAX" : 1, "gettempprefix" : 1, + "gettempprefixb" : 1, "gettempdir" : 1, + "gettempdirb" : 1, "tempdir" : 1, "template" : 1, "SpooledTemporaryFile" : 1, @@ -320,7 +363,8 @@ if bin: flags = self._bflags else: flags = self._tflags - (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags) + output_type = tempfile._infer_return_type(dir, pre, suf) + (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags, output_type) def write(self, str): os.write(self.fd, str) @@ -329,9 +373,17 @@ self._close(self.fd) self._unlink(self.name) - def do_create(self, dir=None, pre="", suf="", bin=1): + def do_create(self, dir=None, pre=None, suf=None, bin=1): + output_type = tempfile._infer_return_type(dir, pre, suf) if dir is None: - dir = tempfile.gettempdir() + if output_type is str: + dir = tempfile.gettempdir() + else: + dir = tempfile.gettempdirb() + if pre is None: + pre = output_type() + if suf is None: + suf = output_type() file = self.mkstemped(dir, pre, suf, bin) self.nameCheck(file.name, dir, pre, suf) @@ -345,6 +397,23 @@ self.do_create(pre="a", suf="b").write(b"blat") self.do_create(pre="aa", suf=".txt").write(b"blat") + def test_basic_with_bytes_names(self): + # _mkstemp_inner can create files when given name parts all + # specified as bytes. + dir_b = tempfile.gettempdirb() + self.do_create(dir=dir_b, suf=b"").write(b"blat") + self.do_create(dir=dir_b, pre=b"a").write(b"blat") + self.do_create(dir=dir_b, suf=b"b").write(b"blat") + self.do_create(dir=dir_b, pre=b"a", suf=b"b").write(b"blat") + self.do_create(dir=dir_b, pre=b"aa", suf=b".txt").write(b"blat") + # Can't mix str & binary types in the args. + with self.assertRaises(TypeError): + self.do_create(dir="", suf=b"").write(b"blat") + with self.assertRaises(TypeError): + self.do_create(dir=dir_b, pre="").write(b"blat") + with self.assertRaises(TypeError): + self.do_create(dir=dir_b, pre=b"", suf="").write(b"blat") + def test_basic_many(self): # _mkstemp_inner can create many files (stochastic) extant = list(range(TEST_FILES)) @@ -424,9 +493,10 @@ def make_temp(self): return tempfile._mkstemp_inner(tempfile.gettempdir(), - tempfile.template, + tempfile.gettempprefix(), '', - tempfile._bin_openflags) + tempfile._bin_openflags, + str) def test_collision_with_existing_file(self): # _mkstemp_inner tries another name when a file with @@ -462,7 +532,12 @@ p = tempfile.gettempprefix() self.assertIsInstance(p, str) - self.assertTrue(len(p) > 0) + self.assertGreater(len(p), 0) + + pb = tempfile.gettempprefixb() + + self.assertIsInstance(pb, bytes) + self.assertGreater(len(pb), 0) def test_usable_template(self): # gettempprefix returns a usable prefix string @@ -487,11 +562,11 @@ def test_directory_exists(self): # gettempdir returns a directory which exists - dir = tempfile.gettempdir() - self.assertTrue(os.path.isabs(dir) or dir == os.curdir, - "%s is not an absolute path" % dir) - self.assertTrue(os.path.isdir(dir), - "%s is not a directory" % dir) + for d in (tempfile.gettempdir(), tempfile.gettempdirb()): + self.assertTrue(os.path.isabs(d) or d == os.curdir, + "%r is not an absolute path" % d) + self.assertTrue(os.path.isdir(d), + "%r is not a directory" % d) def test_directory_writable(self): # gettempdir returns a directory writable by the user @@ -507,8 +582,11 @@ # gettempdir always returns the same object a = tempfile.gettempdir() b = tempfile.gettempdir() + c = tempfile.gettempdirb() self.assertTrue(a is b) + self.assertNotEqual(type(a), type(c)) + self.assertEqual(a, os.fsdecode(c)) def test_case_sensitive(self): # gettempdir should not flatten its case @@ -528,9 +606,17 @@ class TestMkstemp(BaseTestCase): """Test mkstemp().""" - def do_create(self, dir=None, pre="", suf=""): + def do_create(self, dir=None, pre=None, suf=None): + output_type = tempfile._infer_return_type(dir, pre, suf) if dir is None: - dir = tempfile.gettempdir() + if output_type is str: + dir = tempfile.gettempdir() + else: + dir = tempfile.gettempdirb() + if pre is None: + pre = output_type() + if suf is None: + suf = output_type() (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf) (ndir, nbase) = os.path.split(name) adir = os.path.abspath(dir) @@ -552,6 +638,24 @@ self.do_create(pre="aa", suf=".txt") self.do_create(dir=".") + def test_basic_with_bytes_names(self): + # mkstemp can create files when given name parts all + # specified as bytes. + d = tempfile.gettempdirb() + self.do_create(dir=d, suf=b"") + self.do_create(dir=d, pre=b"a") + self.do_create(dir=d, suf=b"b") + self.do_create(dir=d, pre=b"a", suf=b"b") + self.do_create(dir=d, pre=b"aa", suf=b".txt") + self.do_create(dir=b".") + with self.assertRaises(TypeError): + self.do_create(dir=".", pre=b"aa", suf=b".txt") + with self.assertRaises(TypeError): + self.do_create(dir=b".", pre="aa", suf=b".txt") + with self.assertRaises(TypeError): + self.do_create(dir=b".", pre=b"aa", suf=".txt") + + def test_choose_directory(self): # mkstemp can create directories in a user-selected directory dir = tempfile.mkdtemp() @@ -567,9 +671,17 @@ def make_temp(self): return tempfile.mkdtemp() - def do_create(self, dir=None, pre="", suf=""): + def do_create(self, dir=None, pre=None, suf=None): + output_type = tempfile._infer_return_type(dir, pre, suf) if dir is None: - dir = tempfile.gettempdir() + if output_type is str: + dir = tempfile.gettempdir() + else: + dir = tempfile.gettempdirb() + if pre is None: + pre = output_type() + if suf is None: + suf = output_type() name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf) try: @@ -587,6 +699,21 @@ os.rmdir(self.do_create(pre="a", suf="b")) os.rmdir(self.do_create(pre="aa", suf=".txt")) + def test_basic_with_bytes_names(self): + # mkdtemp can create directories when given all binary parts + d = tempfile.gettempdirb() + os.rmdir(self.do_create(dir=d)) + os.rmdir(self.do_create(dir=d, pre=b"a")) + os.rmdir(self.do_create(dir=d, suf=b"b")) + os.rmdir(self.do_create(dir=d, pre=b"a", suf=b"b")) + os.rmdir(self.do_create(dir=d, pre=b"aa", suf=b".txt")) + with self.assertRaises(TypeError): + os.rmdir(self.do_create(dir=d, pre="aa", suf=b".txt")) + with self.assertRaises(TypeError): + os.rmdir(self.do_create(dir=d, pre=b"aa", suf=".txt")) + with self.assertRaises(TypeError): + os.rmdir(self.do_create(dir="", pre=b"aa", suf=b".txt")) + def test_basic_many(self): # mkdtemp can create many directories (stochastic) extant = list(range(TEST_FILES)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir + parameters and returns bytes in such situations (matching the os module APIs). + - Issue 24244: Prevents termination when an invalid format string is encountered on Windows in strftime. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 01:22:47 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 22 May 2015 23:22:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Removes_lingering_referenc?= =?utf-8?q?es_to_RAR_now_that_make=5Fzip=2Epy_actually_makes_a_ZIP?= Message-ID: <20150522232247.27935.37234@psf.io> https://hg.python.org/cpython/rev/0308ee35181c changeset: 96219:0308ee35181c user: Steve Dower date: Fri May 22 16:22:27 2015 -0700 summary: Removes lingering references to RAR now that make_zip.py actually makes a ZIP files: Tools/msi/make_zip.py | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -113,17 +113,14 @@ parser.add_argument('-t', '--temp', metavar='dir', help='A directory to temporarily extract files into', type=Path, default=None) parser.add_argument('-e', '--embed', help='Create an embedding layout', action='store_true', default=False) parser.add_argument('-a', '--arch', help='Specify the architecture to use (win32/amd64)', type=str, default="win32") - parser.add_argument('--rar', help='Full path to WinRAR compressor (rar.exe)', type=Path, default=Path("rar.exe")) ns = parser.parse_args() source = ns.source or (Path(__file__).parent.parent.parent) out = ns.out arch = ns.arch - rar = getattr(ns, 'rar') assert isinstance(source, Path) assert isinstance(out, Path) assert isinstance(arch, str) - assert isinstance(rar, Path) if ns.temp: temp = ns.temp -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 01:38:21 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 22 May 2015 23:38:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MjE5?= =?utf-8?q?=3A_Remove_duplicate_literal_in_docs=2E?= Message-ID: <20150522233821.17931.79053@psf.io> https://hg.python.org/cpython/rev/645a03e93008 changeset: 96220:645a03e93008 branch: 3.4 parent: 96204:c7b9645a6f35 user: Raymond Hettinger date: Fri May 22 16:37:49 2015 -0700 summary: Issue #24219: Remove duplicate literal in docs. files: Doc/reference/lexical_analysis.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -632,8 +632,7 @@ Some examples of integer literals:: 7 2147483647 0o177 0b100110111 - 3 79228162514264337593543950336 0o377 0x100000000 - 79228162514264337593543950336 0xdeadbeef + 3 79228162514264337593543950336 0o377 0xdeadbeef .. _floating: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 01:38:21 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 22 May 2015 23:38:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150522233821.27947.50557@psf.io> https://hg.python.org/cpython/rev/ecde84db7022 changeset: 96221:ecde84db7022 parent: 96219:0308ee35181c parent: 96220:645a03e93008 user: Raymond Hettinger date: Fri May 22 16:38:16 2015 -0700 summary: merge files: Doc/reference/lexical_analysis.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -632,8 +632,7 @@ Some examples of integer literals:: 7 2147483647 0o177 0b100110111 - 3 79228162514264337593543950336 0o377 0x100000000 - 79228162514264337593543950336 0xdeadbeef + 3 79228162514264337593543950336 0o377 0xdeadbeef .. _floating: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 01:56:38 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 22 May 2015 23:56:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_22189=3A__Add_missin?= =?utf-8?q?g_methods_to_UserString?= Message-ID: <20150522235638.126978.80308@psf.io> https://hg.python.org/cpython/rev/c06b2480766d changeset: 96222:c06b2480766d user: Raymond Hettinger date: Fri May 22 16:56:32 2015 -0700 summary: Issue 22189: Add missing methods to UserString files: Lib/collections/__init__.py | 10 +++++++++ Lib/test/test_collections.py | 25 ++++++++++++++++++++++- Misc/NEWS | 4 +++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1060,6 +1060,8 @@ def __float__(self): return float(self.data) def __complex__(self): return complex(self.data) def __hash__(self): return hash(self.data) + def __getnewargs__(self): + return (self.data[:],) def __eq__(self, string): if isinstance(string, UserString): @@ -1104,9 +1106,13 @@ __rmul__ = __mul__ def __mod__(self, args): return self.__class__(self.data % args) + def __rmod__(self, format): + return self.__class__(format % args) # the following methods are defined in alphabetical order: def capitalize(self): return self.__class__(self.data.capitalize()) + def casefold(self): + return self.__class__(self.data.casefold()) def center(self, width, *args): return self.__class__(self.data.center(width, *args)) def count(self, sub, start=0, end=_sys.maxsize): @@ -1129,6 +1135,8 @@ return self.data.find(sub, start, end) def format(self, *args, **kwds): return self.data.format(*args, **kwds) + def format_map(self, mapping): + return self.data.format_map(mapping) def index(self, sub, start=0, end=_sys.maxsize): return self.data.index(sub, start, end) def isalpha(self): return self.data.isalpha() @@ -1138,6 +1146,7 @@ def isidentifier(self): return self.data.isidentifier() def islower(self): return self.data.islower() def isnumeric(self): return self.data.isnumeric() + def isprintable(self): return self.data.isprintable() def isspace(self): return self.data.isspace() def istitle(self): return self.data.istitle() def isupper(self): return self.data.isupper() @@ -1146,6 +1155,7 @@ return self.__class__(self.data.ljust(width, *args)) def lower(self): return self.__class__(self.data.lower()) def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) + maketrans = str.maketrans def partition(self, sep): return self.data.partition(sep) def replace(self, old, new, maxsplit=-1): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -12,7 +12,7 @@ import re import sys import types -from collections import UserDict +from collections import UserDict, UserString, UserList from collections import ChainMap from collections import deque from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable @@ -24,6 +24,26 @@ from collections.abc import ByteString +class TestUserObjects(unittest.TestCase): + def _superset_test(self, a, b): + self.assertGreaterEqual( + set(dir(a)), + set(dir(b)), + '{a} should have all the methods of {b}'.format( + a=a.__name__, + b=b.__name__, + ), + ) + def test_str_protocol(self): + self._superset_test(UserString, str) + + def test_list_protocol(self): + self._superset_test(UserList, list) + + def test_dict_protocol(self): + self._superset_test(UserDict, dict) + + ################################################################################ ### ChainMap (helper class for configparser and the string module) ################################################################################ @@ -1848,7 +1868,8 @@ NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, TestCollectionABCs, TestCounter, TestChainMap, - TestOrderedDict, GeneralMappingTests, SubclassMappingTests] + TestOrderedDict, GeneralMappingTests, SubclassMappingTests, + TestUserObjects] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,10 @@ - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). +- Issue #22189: collections.UserString now supports __getnewargs__(), + __rmod__(), casefold(), format_map(), isprintable(), and maketrans(). + Patch by Joe Jevnik. + - Issue 24244: Prevents termination when an invalid format string is encountered on Windows in strftime. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 02:23:37 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 23 May 2015 00:23:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321448=3A_Improve_?= =?utf-8?q?performance_of______the_email_feedparser?= Message-ID: <20150523002337.26094.52135@psf.io> https://hg.python.org/cpython/rev/830bcf4fb29b changeset: 96223:830bcf4fb29b user: Raymond Hettinger date: Fri May 22 17:23:28 2015 -0700 summary: Issue #21448: Improve performance of the email feedparser files: Lib/email/feedparser.py | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/email/feedparser.py b/Lib/email/feedparser.py --- a/Lib/email/feedparser.py +++ b/Lib/email/feedparser.py @@ -26,6 +26,7 @@ from email import errors from email import message from email._policybase import compat32 +from collections import deque NLCRE = re.compile('\r\n|\r|\n') NLCRE_bol = re.compile('(\r\n|\r|\n)') @@ -52,8 +53,8 @@ def __init__(self): # Chunks of the last partial line pushed into this object. self._partial = [] - # The list of full, pushed lines, in reverse order - self._lines = [] + # A deque of full, pushed lines + self._lines = deque() # The stack of false-EOF checking predicates. self._eofstack = [] # A flag indicating whether the file has been closed or not. @@ -78,21 +79,21 @@ return NeedMoreData # Pop the line off the stack and see if it matches the current # false-EOF predicate. - line = self._lines.pop() + line = self._lines.popleft() # RFC 2046, section 5.1.2 requires us to recognize outer level # boundaries at any level of inner nesting. Do this, but be sure it's # in the order of most to least nested. - for ateof in self._eofstack[::-1]: + for ateof in reversed(self._eofstack): if ateof(line): # We're at the false EOF. But push the last line back first. - self._lines.append(line) + self._lines.appendleft(line) return '' return line def unreadline(self, line): # Let the consumer push a line back into the buffer. assert line is not NeedMoreData - self._lines.append(line) + self._lines.appendleft(line) def push(self, data): """Push some new data into this object.""" @@ -119,8 +120,7 @@ self.pushlines(parts) def pushlines(self, lines): - # Reverse and insert at the front of the lines. - self._lines[:0] = lines[::-1] + self._lines.extend(lines) def __iter__(self): return self -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 02:28:58 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 23 May 2015 00:28:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Upgrade_pip_to?= =?utf-8?b?IDcuMC4x?= Message-ID: <20150523002858.27951.67856@psf.io> https://hg.python.org/cpython/rev/428d2eec7e77 changeset: 96224:428d2eec7e77 branch: 2.7 parent: 96217:dce981bac5da user: Donald Stufft date: Fri May 22 20:28:52 2015 -0400 summary: Upgrade pip to 7.0.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -14,7 +14,7 @@ _SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "7.0.0" +_PIP_VERSION = "7.0.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl deleted file mode 100644 index 926d2a79fa715a9f9a9825a6304bcbd96683612e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..30a61f0a0e9dde9b4dde32876e65213e7ceb4f8e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 02:30:22 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 23 May 2015 00:30:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Upgrade_pip_to?= =?utf-8?b?IDcuMC4x?= Message-ID: <20150523003022.126958.66861@psf.io> https://hg.python.org/cpython/rev/4c16773052d1 changeset: 96225:4c16773052d1 branch: 3.4 parent: 96220:645a03e93008 user: Donald Stufft date: Fri May 22 20:30:16 2015 -0400 summary: Upgrade pip to 7.0.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "7.0.0" +_PIP_VERSION = "7.0.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl deleted file mode 100644 index 926d2a79fa715a9f9a9825a6304bcbd96683612e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..30a61f0a0e9dde9b4dde32876e65213e7ceb4f8e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 02:31:14 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 23 May 2015 00:31:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_into_default=2C_upgrading_pip_to_7=2E0=2E1?= Message-ID: <20150523003114.16713.73458@psf.io> https://hg.python.org/cpython/rev/29b95625a07c changeset: 96226:29b95625a07c parent: 96223:830bcf4fb29b parent: 96225:4c16773052d1 user: Donald Stufft date: Fri May 22 20:30:57 2015 -0400 summary: Merge 3.4 into default, upgrading pip to 7.0.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "7.0.0" +_PIP_VERSION = "7.0.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.0-py2.py3-none-any.whl deleted file mode 100644 index 926d2a79fa715a9f9a9825a6304bcbd96683612e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..30a61f0a0e9dde9b4dde32876e65213e7ceb4f8e GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 04:01:42 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 23 May 2015 02:01:42 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_484_=28type_hints=29_acce?= =?utf-8?q?pted_by_BDFL-Delegate_=28Mark_Shannon=29=2E?= Message-ID: <20150523020142.16699.56689@psf.io> https://hg.python.org/peps/rev/ad8738e41ced changeset: 5876:ad8738e41ced user: Guido van Rossum date: Fri May 22 19:00:21 2015 -0700 summary: PEP 484 (type hints) accepted by BDFL-Delegate (Mark Shannon). files: pep-0484.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -5,12 +5,12 @@ Author: Guido van Rossum , Jukka Lehtosalo , ?ukasz Langa BDFL-Delegate: Mark Shannon Discussions-To: Python-Dev -Status: Draft +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 29-Sep-2014 Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015,20-May-2015,22-May-2015 -Resolution: +Resolution: https://mail.python.org/pipermail/python-dev/2015-May/140104.html Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 23 04:29:32 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 23 May 2015 02:29:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323086=3A_Add_star?= =?utf-8?q?t_and_stop_arguments_to_the_Sequence=2Eindex=28=29_mixin_method?= =?utf-8?q?=2E?= Message-ID: <20150523022932.16711.10663@psf.io> https://hg.python.org/cpython/rev/cabd7261ae80 changeset: 96227:cabd7261ae80 user: Raymond Hettinger date: Fri May 22 19:29:22 2015 -0700 summary: Issue #23086: Add start and stop arguments to the Sequence.index() mixin method. files: Doc/library/collections.abc.rst | 14 ++++++++ Lib/_collections_abc.py | 20 +++++++++--- Lib/test/test_collections.py | 35 +++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -121,6 +121,20 @@ ABCs for read-only and mutable :term:`sequences `. + Implementation note: Some of the mixin methods, such as + :meth:`__iter__`, :meth:`__reversed__` and :meth:`index`, make + repeated calls to the underlying :meth:`__getitem__` method. + Consequently, if :meth:`__getitem__` is implemented with constant + access speed, the mixin methods will have linear performance; + however, if the underlying method is linear (as it would be with a + linked list), the mixins will have quadratic performance and will + likely need to be overridden. + + .. versionchanged:: 3.5 + The index() method added support for *stop* and *start* + arguments. + + .. class:: Set MutableSet diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -825,13 +825,23 @@ for i in reversed(range(len(self))): yield self[i] - def index(self, value): - '''S.index(value) -> integer -- return first index of value. + def index(self, value, start=0, stop=None): + '''S.index(value, [start, [stop]]) -> integer -- return first index of value. Raises ValueError if the value is not present. ''' - for i, v in enumerate(self): - if v == value: - return i + if start is not None and start < 0: + start = max(len(self) + start, 0) + if stop is not None and stop < 0: + stop += len(self) + + i = start + while stop is None or i < stop: + try: + if self[i] == value: + return i + except IndexError: + break + i += 1 raise ValueError def count(self, value): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1227,6 +1227,41 @@ self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__', '__getitem__') + def test_Sequence_mixins(self): + class SequenceSubclass(Sequence): + def __init__(self, seq=()): + self.seq = seq + + def __getitem__(self, index): + return self.seq[index] + + def __len__(self): + return len(self.seq) + + # Compare Sequence.index() behavior to (list|str).index() behavior + def assert_index_same(seq1, seq2, index_args): + try: + expected = seq1.index(*index_args) + except ValueError: + with self.assertRaises(ValueError): + seq2.index(*index_args) + else: + actual = seq2.index(*index_args) + self.assertEqual( + actual, expected, '%r.index%s' % (seq1, index_args)) + + for ty in list, str: + nativeseq = ty('abracadabra') + indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3)) + seqseq = SequenceSubclass(nativeseq) + for letter in set(nativeseq) | {'z'}: + assert_index_same(nativeseq, seqseq, (letter,)) + for start in range(-3, len(nativeseq) + 3): + assert_index_same(nativeseq, seqseq, (letter, start)) + for stop in range(-3, len(nativeseq) + 3): + assert_index_same( + nativeseq, seqseq, (letter, start, stop)) + def test_ByteString(self): for sample in [bytes, bytearray]: self.assertIsInstance(sample(), ByteString) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -660,6 +660,7 @@ Thomas Jarosch Juhana Jauhiainen Rajagopalasarma Jayakrishnan +Devin Jeanpierre Zbigniew J?drzejewski-Szmek Julien Jehannet Muhammad Jehanzeb diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -73,6 +73,10 @@ - Issue #23973: PEP 484: Add the typing module. +- Issue #23086: The collections.abc.Sequence() abstract base class added + *start* and *stop* parameters to the index() mixin. + Patch by Devin Jeanpierre. + - Issue #20035: Replaced the ``tkinter._fix`` module used for setting up the Tcl/Tk environment on Windows with a private function in the ``_tkinter`` module that makes no permanent changes to the environment. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 10:32:26 2015 From: python-checkins at python.org (larry.hastings) Date: Sat, 23 May 2015 08:32:26 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Updated_dev_guide_to_refl?= =?utf-8?q?ect_the_new_workflow_we=27re_trying_for_3=2E5=2E?= Message-ID: <20150523083226.126986.26481@psf.io> https://hg.python.org/devguide/rev/64966376d8ea changeset: 744:64966376d8ea user: Larry Hastings date: Sat May 23 01:32:22 2015 -0700 summary: Updated dev guide to reflect the new workflow we're trying for 3.5. files: devcycle.rst | 27 +++++++++++++++++++++++++-- 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/devcycle.rst b/devcycle.rst --- a/devcycle.rst +++ b/devcycle.rst @@ -54,10 +54,18 @@ changes, performance improvements, bug fixes. As the name indicates, it is the branch :ref:`checked out ` by default by Mercurial. -Once a :ref:`final` release (say, 3.3) is made from the in-development branch, a +At some point during the life-cycle of a release, a new :ref:`maintenance branch ` is created to host all bug fixing activity for further micro versions (3.3.1, 3.3.2, etc.). +For versions 3.4 and before, this was conventionally done when the final +release was cut (for example, 3.4.0 final). + +.. note:: + For the 3.5 release we're trying something new. We're creating the 3.5 + maintenance branch at the time we enter beta (3.5.0 beta 1). This will + allow feature development for 3.6 to occur alongside the beta and release + candidate stabilization periods for 3.5. .. _maintbranch: @@ -110,7 +118,7 @@ There are 5 open branches right now in the Mercurial repository: - the ``default`` branch holds the future 3.5 version and descends from ``3.4`` - (future RM: Larry Hastings) + (RM: Larry Hastings) - the ``3.4`` branch holds bug fixes for future 3.4.x maintenance releases and descends from ``3.3`` (RM: Larry Hastings) - the ``3.3`` branch holds security fixes for future 3.3.x security releases @@ -162,6 +170,10 @@ Being in beta can be viewed much like being in RC_ but without the extra overhead of needing commit reviews. +Please see the note in the `In-development (main) branch`_ section above +for new information about the creation of the 3.5 maintenance branch during beta. + + .. _rc: Release Candidate (RC) @@ -177,6 +189,17 @@ it is a simple copy-and-paste change, **everything** requires peer review from a core developer. +.. note:: + For the 3.5 release we're trying something new. At the point that we reach 3.5.0 + release candidate 1, the official release branch will no longer be hosted at + ``hg.python.org``. Instead, 3.5.0 rc 1 through final will be hosted + by the 3.5 release manager on bitbucket. + + Bugfixes for 3.5 should still be checked in to the 3.5 branch. However, if the + core developer responsible for the bugfix feels it should be merged into 3.5.0, they + will need to create a bitbucket "pull request" for this change. Any bugfixes not + merged into 3.5.0 in this way will be automatically shipped with 3.5.1. + .. _final: Final -- Repository URL: https://hg.python.org/devguide From solipsis at pitrou.net Sat May 23 11:08:41 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 23 May 2015 09:08:41 +0000 Subject: [Python-checkins] Daily reference leaks (cabd7261ae80): sum=4 Message-ID: <20150523090840.45367.59210@psf.io> results for cabd7261ae80 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogQMkaPZ', '--timeout', '7200'] From python-checkins at python.org Sat May 23 14:57:57 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 23 May 2015 12:57:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_PEP_489=3A_Multi-phase_ext?= =?utf-8?q?ension_module_initialization?= Message-ID: <20150523125757.16705.19524@psf.io> https://hg.python.org/cpython/rev/e729b946cc03 changeset: 96228:e729b946cc03 user: Nick Coghlan date: Sat May 23 22:24:10 2015 +1000 summary: PEP 489: Multi-phase extension module initialization Known limitations of the current implementation: - documentation changes are incomplete - there's a reference leak I haven't tracked down yet The leak is most visible by running: ./python -m test -R3:3 test_importlib However, you can also see it by running: ./python -X showrefcount Importing the array or _testmultiphase modules, and then deleting them from both sys.modules and the local namespace shows significant increases in the total number of active references each cycle. By contrast, with _testcapi (which continues to use single-phase initialisation) the global refcounts stabilise after a couple of cycles. files: Doc/c-api/module.rst | 92 +- Doc/library/importlib.rst | 28 +- Doc/whatsnew/3.5.rst | 19 +- Include/modsupport.h | 62 +- Include/moduleobject.h | 16 +- Lib/imp.py | 33 +- Lib/importlib/_bootstrap.py | 23 +- Lib/importlib/_bootstrap_external.py | 33 +- Lib/test/test_importlib/extension/test_loader.py | 167 + Misc/ACKS | 1 + Misc/NEWS | 2 + Modules/_testcapimodule.c | 3 + Modules/_testmultiphase.c | 567 + Modules/arraymodule.c | 50 +- Modules/config.c.in | 2 +- Modules/xxlimited.c | 55 +- Modules/xxmodule.c | 54 +- Modules/xxsubtype.c | 61 +- Objects/moduleobject.c | 339 +- PC/config.c | 2 +- Python/clinic/import.c.h | 103 +- Python/dynload_aix.c | 5 +- Python/dynload_dl.c | 7 +- Python/dynload_hpux.c | 12 +- Python/dynload_next.c | 7 +- Python/dynload_shlib.c | 8 +- Python/dynload_win.c | 7 +- Python/import.c | 189 +- Python/importdl.c | 231 +- Python/importdl.h | 3 +- Python/importlib.h | 1526 ++- Python/importlib_external.h | 3854 +++++---- Python/pystate.c | 19 +- setup.py | 2 + 34 files changed, 4460 insertions(+), 3122 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -7,8 +7,6 @@ .. index:: object: module -There are only a few functions special to module objects. - .. c:var:: PyTypeObject PyModule_Type @@ -109,6 +107,14 @@ unencodable filenames, use :c:func:`PyModule_GetFilenameObject` instead. +Per-interpreter module state +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Single-phase initialization creates singleton modules that can store additional +information as part of the interpreter, allow that state to be retrieved later +with only a reference to the module definition, rather than to the module +itself. + .. c:function:: void* PyModule_GetState(PyObject *module) Return the "state" of the module, that is, a pointer to the block of memory @@ -146,27 +152,6 @@ Initializing C modules ^^^^^^^^^^^^^^^^^^^^^^ -These functions are usually used in the module initialization function. - -.. c:function:: PyObject* PyModule_Create(PyModuleDef *module) - - Create a new module object, given the definition in *module*. This behaves - like :c:func:`PyModule_Create2` with *module_api_version* set to - :const:`PYTHON_API_VERSION`. - - -.. c:function:: PyObject* PyModule_Create2(PyModuleDef *module, int module_api_version) - - Create a new module object, given the definition in *module*, assuming the - API version *module_api_version*. If that version does not match the version - of the running interpreter, a :exc:`RuntimeWarning` is emitted. - - .. note:: - - Most uses of this function should be using :c:func:`PyModule_Create` - instead; only use this if you are sure you need it. - - .. c:type:: PyModuleDef This struct holds all information that is needed to create a module object. @@ -210,9 +195,10 @@ A pointer to a table of module-level functions, described by :c:type:`PyMethodDef` values. Can be *NULL* if no functions are present. - .. c:member:: inquiry m_reload + .. c:member:: PyModuleDef_Slot* m_slots - Currently unused, should be *NULL*. + An array of slot definitions for multi-phase initialization, terminated by + a *NULL* entry. .. c:member:: traverseproc m_traverse @@ -229,6 +215,61 @@ A function to call during deallocation of the module object, or *NULL* if not needed. +The module initialization function may create and return the module object +directly. This is referred to as "single-phase initialization", and uses one +of the following two module creation functions: + +.. c:function:: PyObject* PyModule_Create(PyModuleDef *module) + + Create a new module object, given the definition in *module*. This behaves + like :c:func:`PyModule_Create2` with *module_api_version* set to + :const:`PYTHON_API_VERSION`. + + +.. c:function:: PyObject* PyModule_Create2(PyModuleDef *module, int module_api_version) + + Create a new module object, given the definition in *module*, assuming the + API version *module_api_version*. If that version does not match the version + of the running interpreter, a :exc:`RuntimeWarning` is emitted. + + .. note:: + + Most uses of this function should be using :c:func:`PyModule_Create` + instead; only use this if you are sure you need it. + + +Alternatively, the module initialization function may instead return a +:c:type:`PyModuleDef` instance with a non-empty ``m_slots`` array. This is +referred to as "multi-phase initialization", and ``PyModuleDef`` instance +should be initialized with the following function: + +.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *module) + + Ensures a module definition is a properly initialized Python object that + correctly reports its type and reference count. + +.. XXX (ncoghlan): It's not clear if it makes sense to document PyModule_ExecDef + PyModule_FromDefAndSpec or PyModule_FromDefAndSpec2 here, as end user code + generally shouldn't be calling those. + +The module initialization function (if using single phase initialization) or +a function called from a module execution slot (if using multiphase +initialization), can use the following functions to help initialize the module +state: + +.. c:function:: int PyModule_SetDocString(PyObject *module, const char *docstring) + + Set the docstring for *module* to *docstring*. Return ``-1`` on error, ``0`` + on success. + +.. c:function:: int PyModule_AddFunctions(PyObject *module, PyMethodDef *functions) + + Add the functions from the ``NULL`` terminated *functions* array to *module*. + Refer to the :c:type:`PyMethodDef` documentation for details on individual + entries (due to the lack of a shared module namespace, module level + "functions" implemented in C typically receive the module as their first + parameter, making them similar to instance methods on Python classes). + .. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value) @@ -236,7 +277,6 @@ be used from the module's initialization function. This steals a reference to *value*. Return ``-1`` on error, ``0`` on success. - .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value) Add an integer constant to *module* as *name*. This convenience function can be diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -55,6 +55,12 @@ :pep:`451` A ModuleSpec Type for the Import System + :pep:`488` + Elimination of PYO files + + :pep:`489` + Multi-phase extension module initialization + :pep:`3120` Using UTF-8 as the Default Source Encoding @@ -756,9 +762,9 @@ Only class methods are defined by this class to alleviate the need for instantiation. - .. note:: - Due to limitations in the extension module C-API, for now - BuiltinImporter does not implement :meth:`Loader.exec_module`. + .. versionchanged:: 3.5 + As part of :pep:`489`, the builtin importer now implements + :meth:`Loader.create_module` and :meth:`Loader.exec_module` .. class:: FrozenImporter @@ -973,14 +979,18 @@ Path to the extension module. - .. method:: load_module(name=None) + .. method:: create_module(spec) - Loads the extension module if and only if *fullname* is the same as - :attr:`name` or is ``None``. + Creates the module object from the given specification in accordance + with :pep:`489`. - .. note:: - Due to limitations in the extension module C-API, for now - ExtensionFileLoader does not implement :meth:`Loader.exec_module`. + .. versionadded:: 3.5 + + .. method:: exec_module(module) + + Initializes the given module object in accordance with :pep:`489`. + + .. versionadded:: 3.5 .. method:: is_package(fullname) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -93,6 +93,7 @@ (:issue:`19977`). * :pep:`488`, the elimination of ``.pyo`` files. +* :pep:`489`, multi-phase initialization of extension modules. Significantly Improved Library Modules: @@ -265,6 +266,21 @@ :pep:`488` -- Elimination of PYO files +PEP 489: Multi-phase extension module initialization +---------------------------------------------------- + +:pep:`489` updates extension module initialization to take advantage of the +two step module loading mechanism introduced by :pep:`451` in Python 3.4. + +This change brings the import semantics of extension modules that opt-in to +using the new mechanism much closer to those of Python source and bytecode +modules, including the ability to any valid identifier as a module name, +rather than being restricted to ASCII. + +.. seealso:: + + :pep:`488` -- Multi-phase extension module initialization + Other Language Changes ====================== @@ -667,7 +683,7 @@ tkinter ------- -* The :module:`tkinter._fix` module used for setting up the Tcl/Tk environment +* The :mod:`tkinter._fix` module used for setting up the Tcl/Tk environment on Windows has been replaced by a private function in the :module:`_tkinter` module which makes no permanent changes to environment variables. (Contributed by Zachary Ware in :issue:`20035`.) @@ -1012,7 +1028,6 @@ program depends on patching the module level variable to capture the debug output, you will need to update it to capture sys.stderr instead. - Changes in the C API -------------------- diff --git a/Include/modsupport.h b/Include/modsupport.h --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -12,13 +12,13 @@ /* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier to mean Py_ssize_t */ #ifdef PY_SSIZE_T_CLEAN -#define PyArg_Parse _PyArg_Parse_SizeT -#define PyArg_ParseTuple _PyArg_ParseTuple_SizeT -#define PyArg_ParseTupleAndKeywords _PyArg_ParseTupleAndKeywords_SizeT -#define PyArg_VaParse _PyArg_VaParse_SizeT -#define PyArg_VaParseTupleAndKeywords _PyArg_VaParseTupleAndKeywords_SizeT -#define Py_BuildValue _Py_BuildValue_SizeT -#define Py_VaBuildValue _Py_VaBuildValue_SizeT +#define PyArg_Parse _PyArg_Parse_SizeT +#define PyArg_ParseTuple _PyArg_ParseTuple_SizeT +#define PyArg_ParseTupleAndKeywords _PyArg_ParseTupleAndKeywords_SizeT +#define PyArg_VaParse _PyArg_VaParse_SizeT +#define PyArg_VaParseTupleAndKeywords _PyArg_VaParseTupleAndKeywords_SizeT +#define Py_BuildValue _Py_BuildValue_SizeT +#define Py_VaBuildValue _Py_VaBuildValue_SizeT #else PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list); #endif @@ -49,6 +49,9 @@ PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *); #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) #define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) +PyAPI_FUNC(int) PyModule_SetDocString(PyObject *, const char *); +PyAPI_FUNC(int) PyModule_AddFunctions(PyObject *, PyMethodDef *); +PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def); #define Py_CLEANUP_SUPPORTED 0x20000 @@ -67,35 +70,35 @@ Please add a line or two to the top of this log for each API version change: - 22-Feb-2006 MvL 1013 PEP 353 - long indices for sequence lengths + 22-Feb-2006 MvL 1013 PEP 353 - long indices for sequence lengths - 19-Aug-2002 GvR 1012 Changes to string object struct for - interning changes, saving 3 bytes. + 19-Aug-2002 GvR 1012 Changes to string object struct for + interning changes, saving 3 bytes. - 17-Jul-2001 GvR 1011 Descr-branch, just to be on the safe side + 17-Jul-2001 GvR 1011 Descr-branch, just to be on the safe side 25-Jan-2001 FLD 1010 Parameters added to PyCode_New() and PyFrame_New(); Python 2.1a2 14-Mar-2000 GvR 1009 Unicode API added - 3-Jan-1999 GvR 1007 Decided to change back! (Don't reuse 1008!) + 3-Jan-1999 GvR 1007 Decided to change back! (Don't reuse 1008!) - 3-Dec-1998 GvR 1008 Python 1.5.2b1 + 3-Dec-1998 GvR 1008 Python 1.5.2b1 - 18-Jan-1997 GvR 1007 string interning and other speedups + 18-Jan-1997 GvR 1007 string interning and other speedups - 11-Oct-1996 GvR renamed Py_Ellipses to Py_Ellipsis :-( + 11-Oct-1996 GvR renamed Py_Ellipses to Py_Ellipsis :-( - 30-Jul-1996 GvR Slice and ellipses syntax added + 30-Jul-1996 GvR Slice and ellipses syntax added - 23-Jul-1996 GvR For 1.4 -- better safe than sorry this time :-) + 23-Jul-1996 GvR For 1.4 -- better safe than sorry this time :-) - 7-Nov-1995 GvR Keyword arguments (should've been done at 1.3 :-( ) + 7-Nov-1995 GvR Keyword arguments (should've been done at 1.3 :-( ) - 10-Jan-1995 GvR Renamed globals to new naming scheme + 10-Jan-1995 GvR Renamed globals to new naming scheme - 9-Jan-1995 GvR Initial version (incompatible with older API) + 9-Jan-1995 GvR Initial version (incompatible with older API) */ /* The PYTHON_ABI_VERSION is introduced in PEP 384. For the lifetime of @@ -105,10 +108,11 @@ #define PYTHON_ABI_STRING "3" #ifdef Py_TRACE_REFS - /* When we are tracing reference counts, rename PyModule_Create2 so + /* When we are tracing reference counts, rename module creation functions so modules compiled with incompatible settings will generate a link-time error. */ #define PyModule_Create2 PyModule_Create2TraceRefs + #define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs #endif PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*, @@ -116,10 +120,22 @@ #ifdef Py_LIMITED_API #define PyModule_Create(module) \ - PyModule_Create2(module, PYTHON_ABI_VERSION) + PyModule_Create2(module, PYTHON_ABI_VERSION) #else #define PyModule_Create(module) \ - PyModule_Create2(module, PYTHON_API_VERSION) + PyModule_Create2(module, PYTHON_API_VERSION) +#endif + +PyAPI_FUNC(PyObject *) PyModule_FromDefAndSpec2(PyModuleDef *def, + PyObject *spec, + int module_api_version); + +#ifdef Py_LIMITED_API +#define PyModule_FromDefAndSpec(module, spec) \ + PyModule_FromDefAndSpec2(module, spec, PYTHON_ABI_VERSION) +#else +#define PyModule_FromDefAndSpec(module, spec) \ + PyModule_FromDefAndSpec2(module, spec, PYTHON_API_VERSION) #endif #ifndef Py_LIMITED_API diff --git a/Include/moduleobject.h b/Include/moduleobject.h --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -30,6 +30,9 @@ PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); PyAPI_FUNC(void*) PyModule_GetState(PyObject*); +PyAPI_FUNC(PyObject *) PyModuleDef_Init(struct PyModuleDef*); +PyTypeObject PyModuleDef_Type; + typedef struct PyModuleDef_Base { PyObject_HEAD PyObject* (*m_init)(void); @@ -44,18 +47,29 @@ NULL, /* m_copy */ \ } +typedef struct PyModuleDef_Slot{ + int slot; + void *value; +} PyModuleDef_Slot; + typedef struct PyModuleDef{ PyModuleDef_Base m_base; const char* m_name; const char* m_doc; Py_ssize_t m_size; PyMethodDef *m_methods; - inquiry m_reload; + PyModuleDef_Slot* m_slots; traverseproc m_traverse; inquiry m_clear; freefunc m_free; }PyModuleDef; +#define Py_mod_create 1 +#define Py_mod_exec 2 + +#ifndef Py_LIMITED_API +#define _Py_mod_LAST_SLOT 2 +#endif #ifdef __cplusplus } diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -8,15 +8,15 @@ # (Probably) need to stay in _imp from _imp import (lock_held, acquire_lock, release_lock, get_frozen_object, is_frozen_package, - init_builtin, init_frozen, is_builtin, is_frozen, + init_frozen, is_builtin, is_frozen, _fix_co_filename) try: - from _imp import load_dynamic + from _imp import create_dynamic except ImportError: # Platform doesn't support dynamic loading. - load_dynamic = None + create_dynamic = None -from importlib._bootstrap import _ERR_MSG, _exec, _load +from importlib._bootstrap import _ERR_MSG, _exec, _load, _builtin_from_name from importlib._bootstrap_external import SourcelessFileLoader from importlib import machinery @@ -312,3 +312,28 @@ """ return importlib.reload(module) + + +def init_builtin(name): + """**DEPRECATED** + + Load and return a built-in module by name, or None is such module doesn't + exist + """ + try: + return _builtin_from_name(name) + except ImportError: + return None + + +if create_dynamic: + def load_dynamic(name, path, file=None): + """**DEPRECATED** + + Load an extension module. + """ + import importlib.machinery + loader = importlib.machinery.ExtensionFileLoader(name, path) + return loader.load_module() +else: + load_dynamic = None diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -735,16 +735,17 @@ return spec.loader if spec is not None else None @classmethod - @_requires_builtin - def load_module(cls, fullname): - """Load a built-in module.""" - # Once an exec_module() implementation is added we can also - # add a deprecation warning here. - with _ManageReload(fullname): - module = _call_with_frames_removed(_imp.init_builtin, fullname) - module.__loader__ = cls - module.__package__ = '' - return module + def create_module(self, spec): + """Create a built-in module""" + if spec.name not in sys.builtin_module_names: + raise ImportError('{!r} is not a built-in module'.format(spec.name), + name=spec.name) + return _call_with_frames_removed(_imp.create_builtin, spec) + + @classmethod + def exec_module(self, module): + """Exec a built-in module""" + _call_with_frames_removed(_imp.exec_dynamic, module) @classmethod @_requires_builtin @@ -764,6 +765,8 @@ """Return False as built-in modules are never packages.""" return False + load_module = classmethod(_load_module_shim) + class FrozenImporter: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -378,7 +378,8 @@ if name is None: name = self.name elif self.name != name: - raise ImportError('loader cannot handle %s' % name, name=name) + raise ImportError('loader for %s cannot handle %s' % + (self.name, name), name=name) return method(self, name, *args, **kwargs) try: _wrap = _bootstrap._wrap @@ -875,7 +876,7 @@ EXTENSION_SUFFIXES = [] -class ExtensionFileLoader: +class ExtensionFileLoader(FileLoader, _LoaderBasics): """Loader for extension modules. @@ -894,24 +895,20 @@ def __hash__(self): return hash(self.name) ^ hash(self.path) - @_check_name - def load_module(self, fullname): - """Load an extension module.""" - # Once an exec_module() implementation is added we can also - # add a deprecation warning here. - with _bootstrap._ManageReload(fullname): - module = _bootstrap._call_with_frames_removed(_imp.load_dynamic, - fullname, self.path) - _verbose_message('extension module loaded from {!r}', self.path) - is_package = self.is_package(fullname) - if is_package and not hasattr(module, '__path__'): - module.__path__ = [_path_split(self.path)[0]] - module.__loader__ = self - module.__package__ = module.__name__ - if not is_package: - module.__package__ = module.__package__.rpartition('.')[0] + def create_module(self, spec): + """Create an unitialized extension module""" + module = _bootstrap._call_with_frames_removed( + _imp.create_dynamic, spec) + _verbose_message('extension module {!r} loaded from {!r}', + spec.name, self.path) return module + def exec_module(self, module): + """Initialize an extension module""" + _bootstrap._call_with_frames_removed(_imp.exec_dynamic, module) + _verbose_message('extension module {!r} executed from {!r}', + self.name, self.path) + def is_package(self, fullname): """Return True if the extension module is a package.""" file_name = _path_split(self.path)[1] diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -7,6 +7,8 @@ import sys import types import unittest +import importlib.util +import importlib class LoaderTests(abc.LoaderTests): @@ -80,6 +82,171 @@ Source_LoaderTests ) = util.test_both(LoaderTests, machinery=machinery) +class MultiPhaseExtensionModuleTests(abc.LoaderTests): + """Test loading extension modules with multi-phase initialization (PEP 489) + """ + + def setUp(self): + self.name = '_testmultiphase' + finder = self.machinery.FileFinder(None) + self.spec = importlib.util.find_spec(self.name) + assert self.spec + self.loader = self.machinery.ExtensionFileLoader( + self.name, self.spec.origin) + + # No extension module as __init__ available for testing. + test_package = None + + # No extension module in a package available for testing. + test_lacking_parent = None + + # Handling failure on reload is the up to the module. + test_state_after_failure = None + + def test_module(self): + '''Test loading an extension module''' + with util.uncache(self.name): + module = self.load_module() + for attr, value in [('__name__', self.name), + ('__file__', self.spec.origin), + ('__package__', '')]: + self.assertEqual(getattr(module, attr), value) + with self.assertRaises(AttributeError): + module.__path__ + self.assertIs(module, sys.modules[self.name]) + self.assertIsInstance(module.__loader__, + self.machinery.ExtensionFileLoader) + + def test_functionality(self): + '''Test basic functionality of stuff defined in an extension module''' + with util.uncache(self.name): + module = self.load_module() + self.assertIsInstance(module, types.ModuleType) + ex = module.Example() + self.assertEqual(ex.demo('abcd'), 'abcd') + self.assertEqual(ex.demo(), None) + with self.assertRaises(AttributeError): + ex.abc + ex.abc = 0 + self.assertEqual(ex.abc, 0) + self.assertEqual(module.foo(9, 9), 18) + self.assertIsInstance(module.Str(), str) + self.assertEqual(module.Str(1) + '23', '123') + with self.assertRaises(module.error): + raise module.error() + self.assertEqual(module.int_const, 1969) + self.assertEqual(module.str_const, 'something different') + + def test_reload(self): + '''Test that reload didn't re-set the module's attributes''' + with util.uncache(self.name): + module = self.load_module() + ex_class = module.Example + importlib.reload(module) + self.assertIs(ex_class, module.Example) + + def test_try_registration(self): + '''Assert that the PyState_{Find,Add,Remove}Module C API doesn't work''' + module = self.load_module() + with self.subTest('PyState_FindModule'): + self.assertEqual(module.call_state_registration_func(0), None) + with self.subTest('PyState_AddModule'): + with self.assertRaises(SystemError): + module.call_state_registration_func(1) + with self.subTest('PyState_RemoveModule'): + with self.assertRaises(SystemError): + module.call_state_registration_func(2) + + def load_module(self): + '''Load the module from the test extension''' + return self.loader.load_module(self.name) + + def load_module_by_name(self, fullname): + '''Load a module from the test extension by name''' + origin = self.spec.origin + loader = self.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) + return module + + def test_load_twice(self): + '''Test that 2 loads result in 2 module objects''' + module1 = self.load_module_by_name(self.name) + module2 = self.load_module_by_name(self.name) + self.assertIsNot(module1, module2) + + def test_unloadable(self): + '''Test nonexistent module''' + name = 'asdfjkl;' + with self.assertRaises(ImportError) as cm: + self.load_module_by_name(name) + self.assertEqual(cm.exception.name, name) + + def test_unloadable_nonascii(self): + '''Test behavior with nonexistent module with non-ASCII name''' + name = 'fo\xf3' + with self.assertRaises(ImportError) as cm: + self.load_module_by_name(name) + self.assertEqual(cm.exception.name, name) + + def test_nonmodule(self): + '''Test returning a non-module object from create works''' + name = self.name + '_nonmodule' + mod = self.load_module_by_name(name) + self.assertNotEqual(type(mod), type(unittest)) + self.assertEqual(mod.three, 3) + + def test_null_slots(self): + '''Test that NULL slots aren't a problem''' + name = self.name + '_null_slots' + module = self.load_module_by_name(name) + self.assertIsInstance(module, types.ModuleType) + assert module.__name__ == name + + def test_bad_modules(self): + '''Test SystemError is raised for misbehaving extensions''' + for name_base in [ + 'bad_slot_large', + 'bad_slot_negative', + 'create_int_with_state', + 'negative_size', + 'export_null', + 'export_uninitialized', + 'export_raise', + 'export_unreported_exception', + 'create_null', + 'create_raise', + 'create_unreported_exception', + 'nonmodule_with_exec_slots', + 'exec_err', + 'exec_raise', + 'exec_unreported_exception', + ]: + with self.subTest(name_base): + name = self.name + '_' + name_base + with self.assertRaises(SystemError): + self.load_module_by_name(name) + + def test_nonascii(self): + '''Test that modules with non-ASCII names can be loaded''' + # punycode behaves slightly differently in some-ASCII and no-ASCII + # cases, so test both + cases = [ + (self.name + '_zkou\u0161ka_na\u010dten\xed', 'Czech'), + ('\uff3f\u30a4\u30f3\u30dd\u30fc\u30c8\u30c6\u30b9\u30c8', + 'Japanese'), + ] + for name, lang in cases: + with self.subTest(name): + module = self.load_module_by_name(name) + self.assertEqual(module.__name__, name) + self.assertEqual(module.__doc__, "Module named in %s" % lang) + + +(Frozen_MultiPhaseExtensionModuleTests, + Source_MultiPhaseExtensionModuleTests + ) = util.test_both(MultiPhaseExtensionModuleTests, machinery=machinery) if __name__ == '__main__': diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1458,6 +1458,7 @@ Jaap Vermeulen Nikita Vetoshkin Al Vezza +Petr Victorin Jacques A. Vidrine John Viega Dino Viehland diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24268: PEP 489: Multi-phase extension module initialization + - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4048,6 +4048,9 @@ NULL }; +/* Per PEP 489, this module will not be converted to multi-phase initialization + */ + PyMODINIT_FUNC PyInit__testcapi(void) { diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c new file mode 100644 --- /dev/null +++ b/Modules/_testmultiphase.c @@ -0,0 +1,567 @@ + +/* Testing module for multi-phase initialization of extension modules (PEP 489) + */ + +#include "Python.h" + +/* Example objects */ +typedef struct { + PyObject_HEAD + PyObject *x_attr; /* Attributes dictionary */ +} ExampleObject; + +/* Example methods */ + +static void +Example_dealloc(ExampleObject *self) +{ + Py_XDECREF(self->x_attr); + PyObject_Del(self); +} + +static PyObject * +Example_demo(ExampleObject *self, PyObject *args) +{ + PyObject *o = NULL; + if (!PyArg_ParseTuple(args, "|O:demo", &o)) + return NULL; + if (o != NULL && PyUnicode_Check(o)) { + Py_INCREF(o); + return o; + } + Py_INCREF(Py_None); + return Py_None; +} + + +static PyMethodDef Example_methods[] = { + {"demo", (PyCFunction)Example_demo, METH_VARARGS, + PyDoc_STR("demo() -> None")}, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +Example_getattro(ExampleObject *self, PyObject *name) +{ + if (self->x_attr != NULL) { + PyObject *v = PyDict_GetItem(self->x_attr, name); + if (v != NULL) { + Py_INCREF(v); + return v; + } + } + return PyObject_GenericGetAttr((PyObject *)self, name); +} + +static int +Example_setattr(ExampleObject *self, char *name, PyObject *v) +{ + if (self->x_attr == NULL) { + self->x_attr = PyDict_New(); + if (self->x_attr == NULL) + return -1; + } + if (v == NULL) { + int rv = PyDict_DelItemString(self->x_attr, name); + if (rv < 0) + PyErr_SetString(PyExc_AttributeError, + "delete non-existing Example attribute"); + return rv; + } + else + return PyDict_SetItemString(self->x_attr, name, v); +} + +static PyType_Slot Example_Type_slots[] = { + {Py_tp_doc, "The Example type"}, + {Py_tp_dealloc, Example_dealloc}, + {Py_tp_getattro, Example_getattro}, + {Py_tp_setattr, Example_setattr}, + {Py_tp_methods, Example_methods}, + {0, 0}, +}; + +static PyType_Spec Example_Type_spec = { + "_testimportexec.Example", + sizeof(ExampleObject), + 0, + Py_TPFLAGS_DEFAULT, + Example_Type_slots +}; + +/* Function of two integers returning integer */ + +PyDoc_STRVAR(testexport_foo_doc, +"foo(i,j)\n\ +\n\ +Return the sum of i and j."); + +static PyObject * +testexport_foo(PyObject *self, PyObject *args) +{ + long i, j; + long res; + if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) + return NULL; + res = i + j; + return PyLong_FromLong(res); +} + +/* Test that PyState registration fails */ + +PyDoc_STRVAR(call_state_registration_func_doc, +"register_state(0): call PyState_FindModule()\n\ +register_state(1): call PyState_AddModule()\n\ +register_state(2): call PyState_RemoveModule()"); + +static PyObject * +call_state_registration_func(PyObject *mod, PyObject *args) +{ + int i, ret; + PyModuleDef *def = PyModule_GetDef(mod); + if (def == NULL) { + return NULL; + } + if (!PyArg_ParseTuple(args, "i:call_state_registration_func", &i)) + return NULL; + switch (i) { + case 0: + mod = PyState_FindModule(def); + if (mod == NULL) { + Py_RETURN_NONE; + } + return mod; + case 1: + ret = PyState_AddModule(mod, def); + if (ret != 0) { + return NULL; + } + break; + case 2: + ret = PyState_RemoveModule(def); + if (ret != 0) { + return NULL; + } + break; + } + Py_RETURN_NONE; +} + + +static PyType_Slot Str_Type_slots[] = { + {Py_tp_base, NULL}, /* filled out in module exec function */ + {0, 0}, +}; + +static PyType_Spec Str_Type_spec = { + "_testimportexec.Str", + 0, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Str_Type_slots +}; + +static PyMethodDef testexport_methods[] = { + {"foo", testexport_foo, METH_VARARGS, + testexport_foo_doc}, + {"call_state_registration_func", call_state_registration_func, + METH_VARARGS, call_state_registration_func_doc}, + {NULL, NULL} /* sentinel */ +}; + +static int execfunc(PyObject *m) +{ + PyObject *temp = NULL; + + /* Due to cross platform compiler issues the slots must be filled + * here. It's required for portability to Windows without requiring + * C++. */ + Str_Type_slots[0].pfunc = &PyUnicode_Type; + + /* Add a custom type */ + temp = PyType_FromSpec(&Example_Type_spec); + if (temp == NULL) + goto fail; + if (PyModule_AddObject(m, "Example", temp) != 0) + goto fail; + + /* Add an exception type */ + temp = PyErr_NewException("_testimportexec.error", NULL, NULL); + if (temp == NULL) + goto fail; + if (PyModule_AddObject(m, "error", temp) != 0) + goto fail; + + /* Add Str */ + temp = PyType_FromSpec(&Str_Type_spec); + if (temp == NULL) + goto fail; + if (PyModule_AddObject(m, "Str", temp) != 0) + goto fail; + + if (PyModule_AddIntConstant(m, "int_const", 1969) != 0) + goto fail; + + if (PyModule_AddStringConstant(m, "str_const", "something different") != 0) + goto fail; + + return 0; + fail: + return -1; +} + +/* Helper for module definitions; there'll be a lot of them */ +#define TEST_MODULE_DEF(name, slots, methods) { \ + PyModuleDef_HEAD_INIT, /* m_base */ \ + name, /* m_name */ \ + PyDoc_STR("Test module " name), /* m_doc */ \ + 0, /* m_size */ \ + methods, /* m_methods */ \ + slots, /* m_slots */ \ + NULL, /* m_traverse */ \ + NULL, /* m_clear */ \ + NULL, /* m_free */ \ +} + +PyModuleDef_Slot main_slots[] = { + {Py_mod_exec, execfunc}, + {0, NULL}, +}; + +static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods); + +PyMODINIT_FUNC +PyInit__testmultiphase(PyObject *spec) +{ + return PyModuleDef_Init(&main_def); +} + + +/**** Importing a non-module object ****/ + +static PyModuleDef def_nonmodule; + +/* Create a SimpleNamespace(three=3) */ +static PyObject* +createfunc_nonmodule(PyObject *spec, PyModuleDef *def) +{ + PyObject *dct, *ns, *three; + + if (def != &def_nonmodule) { + PyErr_SetString(PyExc_SystemError, "def does not match"); + return NULL; + } + + dct = PyDict_New(); + if (dct == NULL) + return NULL; + + three = PyLong_FromLong(3); + if (three == NULL) { + Py_DECREF(dct); + return NULL; + } + PyDict_SetItemString(dct, "three", three); + + ns = _PyNamespace_New(dct); + Py_DECREF(dct); + return ns; +} + +static PyModuleDef_Slot slots_create_nonmodule[] = { + {Py_mod_create, createfunc_nonmodule}, + {0, NULL}, +}; + +static PyModuleDef def_nonmodule = TEST_MODULE_DEF( + "_testmultiphase_nonmodule", slots_create_nonmodule, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_nonmodule(PyObject *spec) +{ + return PyModuleDef_Init(&def_nonmodule); +} + +/**** Non-ASCII-named modules ****/ + +static PyModuleDef def_nonascii_latin = { \ + PyModuleDef_HEAD_INIT, /* m_base */ + "_testmultiphase_nonascii_latin", /* m_name */ + PyDoc_STR("Module named in Czech"), /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject *spec) +{ + return PyModuleDef_Init(&def_nonascii_latin); +} + +static PyModuleDef def_nonascii_kana = { \ + PyModuleDef_HEAD_INIT, /* m_base */ + "_testmultiphase_nonascii_kana", /* m_name */ + PyDoc_STR("Module named in Japanese"), /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec) +{ + return PyModuleDef_Init(&def_nonascii_kana); +} + +/**** Testing NULL slots ****/ + +static PyModuleDef null_slots_def = TEST_MODULE_DEF( + "_testmultiphase_null_slots", NULL, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_null_slots(PyObject *spec) +{ + return PyModuleDef_Init(&null_slots_def); +} + +/**** Problematic modules ****/ + +static PyModuleDef_Slot slots_bad_large[] = { + {_Py_mod_LAST_SLOT + 1, NULL}, + {0, NULL}, +}; + +static PyModuleDef def_bad_large = TEST_MODULE_DEF( + "_testmultiphase_bad_slot_large", slots_bad_large, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_bad_slot_large(PyObject *spec) +{ + return PyModuleDef_Init(&def_bad_large); +} + +static PyModuleDef_Slot slots_bad_negative[] = { + {-1, NULL}, + {0, NULL}, +}; + +static PyModuleDef def_bad_negative = TEST_MODULE_DEF( + "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_bad_slot_negative(PyObject *spec) +{ + return PyModuleDef_Init(&def_bad_negative); +} + +static PyModuleDef def_create_int_with_state = { \ + PyModuleDef_HEAD_INIT, /* m_base */ + "create_with_state", /* m_name */ + PyDoc_STR("Not a PyModuleObject object, but requests per-module state"), + 10, /* m_size */ + NULL, /* m_methods */ + slots_create_nonmodule, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInit__testmultiphase_create_int_with_state(PyObject *spec) +{ + return PyModuleDef_Init(&def_create_int_with_state); +} + + +static PyModuleDef def_negative_size = { \ + PyModuleDef_HEAD_INIT, /* m_base */ + "negative_size", /* m_name */ + PyDoc_STR("PyModuleDef with negative m_size"), + -1, /* m_size */ + NULL, /* m_methods */ + slots_create_nonmodule, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInit__testmultiphase_negative_size(PyObject *spec) +{ + return PyModuleDef_Init(&def_negative_size); +} + + +static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods); + +PyMODINIT_FUNC +PyInit__testmultiphase_export_uninitialized(PyObject *spec) +{ + return (PyObject*) &uninitialized_def; +} + +PyMODINIT_FUNC +PyInit__testmultiphase_export_null(PyObject *spec) +{ + return NULL; +} + +PyMODINIT_FUNC +PyInit__testmultiphase_export_raise(PyObject *spec) +{ + PyErr_SetString(PyExc_SystemError, "bad export function"); + return NULL; +} + +PyMODINIT_FUNC +PyInit__testmultiphase_export_unreported_exception(PyObject *spec) +{ + PyErr_SetString(PyExc_SystemError, "bad export function"); + return PyModuleDef_Init(&main_def); +} + +static PyObject* +createfunc_null(PyObject *spec, PyModuleDef *def) +{ + return NULL; +} + +PyModuleDef_Slot slots_create_null[] = { + {Py_mod_create, createfunc_null}, + {0, NULL}, +}; + +static PyModuleDef def_create_null = TEST_MODULE_DEF( + "_testmultiphase_create_null", slots_create_null, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_create_null(PyObject *spec) +{ + return PyModuleDef_Init(&def_create_null); +} + +static PyObject* +createfunc_raise(PyObject *spec, PyModuleDef *def) +{ + PyErr_SetString(PyExc_SystemError, "bad create function"); + return NULL; +} + +static PyModuleDef_Slot slots_create_raise[] = { + {Py_mod_create, createfunc_raise}, + {0, NULL}, +}; + +static PyModuleDef def_create_raise = TEST_MODULE_DEF( + "_testmultiphase_create_null", slots_create_raise, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_create_raise(PyObject *spec) +{ + return PyModuleDef_Init(&def_create_raise); +} + +static PyObject* +createfunc_unreported_exception(PyObject *spec, PyModuleDef *def) +{ + PyErr_SetString(PyExc_SystemError, "bad create function"); + return PyModule_New("foo"); +} + +static PyModuleDef_Slot slots_create_unreported_exception[] = { + {Py_mod_create, createfunc_unreported_exception}, + {0, NULL}, +}; + +static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF( + "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_create_unreported_exception(PyObject *spec) +{ + return PyModuleDef_Init(&def_create_unreported_exception); +} + +static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = { + {Py_mod_create, createfunc_nonmodule}, + {Py_mod_exec, execfunc}, + {0, NULL}, +}; + +static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF( + "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec) +{ + return PyModuleDef_Init(&def_nonmodule_with_exec_slots); +} + +static int +execfunc_err(PyObject *mod) +{ + return -1; +} + +static PyModuleDef_Slot slots_exec_err[] = { + {Py_mod_exec, execfunc_err}, + {0, NULL}, +}; + +static PyModuleDef def_exec_err = TEST_MODULE_DEF( + "_testmultiphase_exec_err", slots_exec_err, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_exec_err(PyObject *spec) +{ + return PyModuleDef_Init(&def_exec_err); +} + +static int +execfunc_raise(PyObject *spec) +{ + PyErr_SetString(PyExc_SystemError, "bad exec function"); + return -1; +} + +static PyModuleDef_Slot slots_exec_raise[] = { + {Py_mod_exec, execfunc_raise}, + {0, NULL}, +}; + +static PyModuleDef def_exec_raise = TEST_MODULE_DEF( + "_testmultiphase_exec_raise", slots_exec_raise, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_exec_raise(PyObject *mod) +{ + return PyModuleDef_Init(&def_exec_raise); +} + +static int +execfunc_unreported_exception(PyObject *mod) +{ + PyErr_SetString(PyExc_SystemError, "bad exec function"); + return 0; +} + +static PyModuleDef_Slot slots_exec_unreported_exception[] = { + {Py_mod_exec, execfunc_unreported_exception}, + {0, NULL}, +}; + +static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF( + "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL); + +PyMODINIT_FUNC +PyInit__testmultiphase_exec_unreported_exception(PyObject *spec) +{ + return PyModuleDef_Init(&def_exec_unreported_exception); +} diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2981,34 +2981,17 @@ {NULL, NULL, 0, NULL} /* Sentinel */ }; -static struct PyModuleDef arraymodule = { - PyModuleDef_HEAD_INIT, - "array", - module_doc, - -1, - a_methods, - NULL, - NULL, - NULL, - NULL -}; - - -PyMODINIT_FUNC -PyInit_array(void) +static int +array_modexec(PyObject *m) { - PyObject *m; char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; Py_ssize_t size = 0; struct arraydescr *descr; if (PyType_Ready(&Arraytype) < 0) - return NULL; + return -1; Py_TYPE(&PyArrayIter_Type) = &PyType_Type; - m = PyModule_Create(&arraymodule); - if (m == NULL) - return NULL; Py_INCREF((PyObject *)&Arraytype); PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype); @@ -3031,5 +3014,30 @@ Py_DECREF(m); m = NULL; } - return m; + return 0; } + +static PyModuleDef_Slot arrayslots[] = { + {Py_mod_exec, array_modexec}, + {0, NULL} +}; + + +static struct PyModuleDef arraymodule = { + PyModuleDef_HEAD_INIT, + "array", + module_doc, + 0, + a_methods, + arrayslots, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit_array(void) +{ + return PyModuleDef_Init(&arraymodule); +} diff --git a/Modules/config.c.in b/Modules/config.c.in --- a/Modules/config.c.in +++ b/Modules/config.c.in @@ -13,7 +13,7 @@ /* !!! !!! !!! This file is edited by the makesetup script !!! !!! !!! */ /* This file contains the table of built-in modules. - See init_builtin() in import.c. */ + See create_builtin() in import.c. */ #include "Python.h" diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -222,25 +222,9 @@ PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); -/* Initialization function for the module (*must* be called PyInit_xx) */ - - -static struct PyModuleDef xxmodule = { - PyModuleDef_HEAD_INIT, - "xxlimited", - module_doc, - -1, - xx_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_xxlimited(void) +static int +xx_modexec(PyObject *m) { - PyObject *m = NULL; PyObject *o; /* Due to cross platform compiler issues the slots must be filled @@ -254,11 +238,6 @@ if (Xxo_Type == NULL) goto fail; - /* Create the module and add the functions */ - m = PyModule_Create(&xxmodule); - if (m == NULL) - goto fail; - /* Add some symbolic constants to the module */ if (ErrorObject == NULL) { ErrorObject = PyErr_NewException("xxlimited.error", NULL, NULL); @@ -279,8 +258,34 @@ if (o == NULL) goto fail; PyModule_AddObject(m, "Null", o); - return m; + return 0; fail: Py_XDECREF(m); - return NULL; + return -1; } + + +static PyModuleDef_Slot xx_slots[] = { + {Py_mod_exec, xx_modexec}, + {0, NULL} +}; + +static struct PyModuleDef xxmodule = { + PyModuleDef_HEAD_INIT, + "xxlimited", + module_doc, + 0, + xx_methods, + xx_slots, + NULL, + NULL, + NULL +}; + +/* Export function for the module (*must* be called PyInit_xx) */ + +PyMODINIT_FUNC +PyInit_xxlimited(void) +{ + return PyModuleDef_Init(&xxmodule); +} diff --git a/Modules/xxmodule.c b/Modules/xxmodule.c --- a/Modules/xxmodule.c +++ b/Modules/xxmodule.c @@ -334,26 +334,10 @@ PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); -/* Initialization function for the module (*must* be called PyInit_xx) */ - -static struct PyModuleDef xxmodule = { - PyModuleDef_HEAD_INIT, - "xx", - module_doc, - -1, - xx_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_xx(void) +static int +xx_exec(PyObject *m) { - PyObject *m = NULL; - /* Due to cross platform compiler issues the slots must be filled * here. It's required for portability to Windows without requiring * C++. */ @@ -366,11 +350,6 @@ if (PyType_Ready(&Xxo_Type) < 0) goto fail; - /* Create the module and add the functions */ - m = PyModule_Create(&xxmodule); - if (m == NULL) - goto fail; - /* Add some symbolic constants to the module */ if (ErrorObject == NULL) { ErrorObject = PyErr_NewException("xx.error", NULL, NULL); @@ -389,8 +368,33 @@ if (PyType_Ready(&Null_Type) < 0) goto fail; PyModule_AddObject(m, "Null", (PyObject *)&Null_Type); - return m; + return 0; fail: Py_XDECREF(m); - return NULL; + return -1; } + +static struct PyModuleDef_Slot xx_slots[] = { + {Py_mod_exec, xx_exec}, + {0, NULL}, +}; + +static struct PyModuleDef xxmodule = { + PyModuleDef_HEAD_INIT, + "xx", + module_doc, + 0, + xx_methods, + xx_slots, + NULL, + NULL, + NULL +}; + +/* Export function for the module (*must* be called PyInit_xx) */ + +PyMODINIT_FUNC +PyInit_xx(void) +{ + return PyModuleDef_Init(&xxmodule); +} diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -257,53 +257,58 @@ {NULL, NULL} /* sentinel */ }; -static struct PyModuleDef xxsubtypemodule = { - PyModuleDef_HEAD_INIT, - "xxsubtype", - xxsubtype__doc__, - -1, - xxsubtype_functions, - NULL, - NULL, - NULL, - NULL -}; - - -PyMODINIT_FUNC -PyInit_xxsubtype(void) +static int +xxsubtype_exec(PyObject* m) { - PyObject *m; - /* Fill in deferred data addresses. This must be done before PyType_Ready() is called. Note that PyType_Ready() automatically initializes the ob.ob_type field to &PyType_Type if it's NULL, so it's not necessary to fill in ob_type first. */ spamdict_type.tp_base = &PyDict_Type; if (PyType_Ready(&spamdict_type) < 0) - return NULL; + return -1; spamlist_type.tp_base = &PyList_Type; if (PyType_Ready(&spamlist_type) < 0) - return NULL; - - m = PyModule_Create(&xxsubtypemodule); - if (m == NULL) - return NULL; + return -1; if (PyType_Ready(&spamlist_type) < 0) - return NULL; + return -1; if (PyType_Ready(&spamdict_type) < 0) - return NULL; + return -1; Py_INCREF(&spamlist_type); if (PyModule_AddObject(m, "spamlist", (PyObject *) &spamlist_type) < 0) - return NULL; + return -1; Py_INCREF(&spamdict_type); if (PyModule_AddObject(m, "spamdict", (PyObject *) &spamdict_type) < 0) - return NULL; - return m; + return -1; + return 0; } + +static struct PyModuleDef_Slot xxsubtype_slots[] = { + {Py_mod_exec, xxsubtype_exec}, + {0, NULL}, +}; + +static struct PyModuleDef xxsubtypemodule = { + PyModuleDef_HEAD_INIT, + "xxsubtype", + xxsubtype__doc__, + 0, + xxsubtype_functions, + xxsubtype_slots, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit_xxsubtype(void) +{ + return PyModuleDef_Init(&xxsubtypemodule); +} diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -20,7 +20,7 @@ {0} }; -static PyTypeObject moduledef_type = { +PyTypeObject PyModuleDef_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "moduledef", /* tp_name */ sizeof(struct PyModuleDef), /* tp_size */ @@ -28,6 +28,20 @@ }; +PyObject* +PyModuleDef_Init(struct PyModuleDef* def) +{ + if (PyType_Ready(&PyModuleDef_Type) < 0) + return NULL; + if (def->m_base.m_index == 0) { + max_module_number++; + Py_REFCNT(def) = 1; + Py_TYPE(def) = &PyModuleDef_Type; + def->m_base.m_index = max_module_number; + } + return (PyObject*)def; +} + static int module_init_dict(PyModuleObject *mod, PyObject *md_dict, PyObject *name, PyObject *doc) @@ -97,26 +111,13 @@ return module; } - -PyObject * -PyModule_Create2(struct PyModuleDef* module, int module_api_version) +/* Check API/ABI version + * Issues a warning on mismatch, which is usually not fatal. + * Returns 0 if an exception is raised. + */ +static int +check_api_version(const char *name, int module_api_version) { - PyObject *d, *v, *n; - PyMethodDef *ml; - const char* name; - PyModuleObject *m; - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules == NULL) - Py_FatalError("Python import machinery not initialized"); - if (PyType_Ready(&moduledef_type) < 0) - return NULL; - if (module->m_base.m_index == 0) { - max_module_number++; - Py_REFCNT(module) = 1; - Py_TYPE(module) = &moduledef_type; - module->m_base.m_index = max_module_number; - } - name = module->m_name; if (module_api_version != PYTHON_API_VERSION && module_api_version != PYTHON_ABI_VERSION) { int err; err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, @@ -125,7 +126,30 @@ name, PYTHON_API_VERSION, name, module_api_version); if (err) - return NULL; + return 0; + } + return 1; +} + +PyObject * +PyModule_Create2(struct PyModuleDef* module, int module_api_version) +{ + const char* name; + PyModuleObject *m; + PyInterpreterState *interp = PyThreadState_Get()->interp; + if (interp->modules == NULL) + Py_FatalError("Python import machinery not initialized"); + if (!PyModuleDef_Init(module)) + return NULL; + name = module->m_name; + if (!check_api_version(name, module_api_version)) { + return NULL; + } + if (module->m_slots) { + PyErr_Format( + PyExc_SystemError, + "module %s: PyModule_Create is incompatible with m_slots", name); + return NULL; } /* Make sure name is fully qualified. @@ -156,53 +180,260 @@ memset(m->md_state, 0, module->m_size); } - d = PyModule_GetDict((PyObject*)m); if (module->m_methods != NULL) { - n = PyUnicode_FromString(name); - if (n == NULL) { + if (PyModule_AddFunctions((PyObject *) m, module->m_methods) != 0) { Py_DECREF(m); return NULL; } - for (ml = module->m_methods; ml->ml_name != NULL; ml++) { - if ((ml->ml_flags & METH_CLASS) || - (ml->ml_flags & METH_STATIC)) { - PyErr_SetString(PyExc_ValueError, - "module functions cannot set" - " METH_CLASS or METH_STATIC"); - Py_DECREF(n); - Py_DECREF(m); - return NULL; - } - v = PyCFunction_NewEx(ml, (PyObject*)m, n); - if (v == NULL) { - Py_DECREF(n); - Py_DECREF(m); - return NULL; - } - if (PyDict_SetItemString(d, ml->ml_name, v) != 0) { - Py_DECREF(v); - Py_DECREF(n); - Py_DECREF(m); - return NULL; - } - Py_DECREF(v); - } - Py_DECREF(n); } if (module->m_doc != NULL) { - _Py_IDENTIFIER(__doc__); - v = PyUnicode_FromString(module->m_doc); - if (v == NULL || _PyDict_SetItemId(d, &PyId___doc__, v) != 0) { - Py_XDECREF(v); + if (PyModule_SetDocString((PyObject *) m, module->m_doc) != 0) { Py_DECREF(m); return NULL; } - Py_DECREF(v); } m->md_def = module; return (PyObject*)m; } +PyObject * +PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api_version) +{ + PyModuleDef_Slot* cur_slot; + PyObject *(*create)(PyObject *, PyModuleDef*) = NULL; + PyObject *nameobj; + PyObject *m = NULL; + int has_execution_slots = 0; + char *name; + int ret; + + PyModuleDef_Init(def); + + nameobj = PyObject_GetAttrString(spec, "name"); + if (nameobj == NULL) { + return NULL; + } + name = PyUnicode_AsUTF8(nameobj); + if (name == NULL) { + goto error; + } + + if (!check_api_version(name, module_api_version)) { + goto error; + } + + if (def->m_size < 0) { + PyErr_Format( + PyExc_SystemError, + "module %s: m_size may not be negative for multi-phase initialization", + name); + goto error; + } + + for (cur_slot = def->m_slots; cur_slot && cur_slot->slot; cur_slot++) { + if (cur_slot->slot == Py_mod_create) { + if (create) { + PyErr_Format( + PyExc_SystemError, + "module %s has multiple create slots", + name); + goto error; + } + create = cur_slot->value; + } else if (cur_slot->slot < 0 || cur_slot->slot > _Py_mod_LAST_SLOT) { + PyErr_Format( + PyExc_SystemError, + "module %s uses unknown slot ID %i", + name, cur_slot->slot); + goto error; + } else { + has_execution_slots = 1; + } + } + + if (create) { + m = create(spec, def); + if (m == NULL) { + if (!PyErr_Occurred()) { + PyErr_Format( + PyExc_SystemError, + "creation of module %s failed without setting an exception", + name); + } + goto error; + } else { + if (PyErr_Occurred()) { + PyErr_Format(PyExc_SystemError, + "creation of module %s raised unreported exception", + name); + goto error; + } + } + } else { + m = PyModule_New(name); + if (m == NULL) { + goto error; + } + } + + if (PyModule_Check(m)) { + ((PyModuleObject*)m)->md_state = NULL; + ((PyModuleObject*)m)->md_def = def; + } else { + if (def->m_size > 0 || def->m_traverse || def->m_clear || def->m_free) { + PyErr_Format( + PyExc_SystemError, + "module %s is not a module object, but requests module state", + name); + goto error; + } + if (has_execution_slots) { + PyErr_Format( + PyExc_SystemError, + "module %s specifies execution slots, but did not create " + "a ModuleType instance", + name); + goto error; + } + } + + if (def->m_methods != NULL) { + ret = PyModule_AddFunctions(m, def->m_methods); + if (ret != 0) { + goto error; + } + } + + if (def->m_doc != NULL) { + ret = PyModule_SetDocString(m, def->m_doc); + if (ret != 0) { + goto error; + } + } + + return m; + +error: + Py_DECREF(nameobj); + Py_XDECREF(m); + return NULL; +} + +int +PyModule_ExecDef(PyObject *module, PyModuleDef *def) +{ + PyModuleDef_Slot *cur_slot; + const char *name; + int ret; + + name = PyModule_GetName(module); + if (name == NULL) { + return -1; + } + + if (PyModule_Check(module) && def->m_size >= 0) { + PyModuleObject *md = (PyModuleObject*)module; + if (md->md_state == NULL) { + /* Always set a state pointer; this serves as a marker to skip + * multiple initialization (importlib.reload() is no-op) */ + md->md_state = PyMem_MALLOC(def->m_size); + if (!md->md_state) { + PyErr_NoMemory(); + return -1; + } + memset(md->md_state, 0, def->m_size); + } + } + + if (def->m_slots == NULL) { + return 0; + } + + for (cur_slot = def->m_slots; cur_slot && cur_slot->slot; cur_slot++) { + switch (cur_slot->slot) { + case Py_mod_create: + /* handled in PyModule_CreateFromSlots */ + break; + case Py_mod_exec: + ret = ((int (*)(PyObject *))cur_slot->value)(module); + if (ret != 0) { + if (!PyErr_Occurred()) { + PyErr_Format( + PyExc_SystemError, + "execution of module %s failed without setting an exception", + name); + } + return -1; + } + if (PyErr_Occurred()) { + PyErr_Format( + PyExc_SystemError, + "execution of module %s raised unreported exception", + name); + return -1; + } + break; + default: + PyErr_Format( + PyExc_SystemError, + "module %s initialized with unknown slot %i", + name, cur_slot->slot); + return -1; + } + } + return 0; +} + +int +PyModule_AddFunctions(PyObject *m, PyMethodDef *functions) +{ + PyObject *name, *func; + PyMethodDef *fdef; + + name = PyModule_GetNameObject(m); + if (name == NULL) { + return -1; + } + + for (fdef = functions; fdef->ml_name != NULL; fdef++) { + if ((fdef->ml_flags & METH_CLASS) || + (fdef->ml_flags & METH_STATIC)) { + PyErr_SetString(PyExc_ValueError, + "module functions cannot set" + " METH_CLASS or METH_STATIC"); + Py_DECREF(name); + return -1; + } + func = PyCFunction_NewEx(fdef, (PyObject*)m, name); + if (func == NULL) { + Py_DECREF(name); + return -1; + } + if (PyObject_SetAttrString(m, fdef->ml_name, func) != 0) { + Py_DECREF(func); + Py_DECREF(name); + return -1; + } + Py_DECREF(func); + } + Py_DECREF(name); + return 0; +} + +int +PyModule_SetDocString(PyObject *m, const char *doc) +{ + PyObject *v; + _Py_IDENTIFIER(__doc__); + + v = PyUnicode_FromString(doc); + if (v == NULL || _PyObject_SetAttrId(m, &PyId___doc__, v) != 0) { + Py_XDECREF(v); + return -1; + } + Py_DECREF(v); + return 0; +} PyObject * PyModule_GetDict(PyObject *m) diff --git a/PC/config.c b/PC/config.c --- a/PC/config.c +++ b/PC/config.c @@ -1,7 +1,7 @@ /* Module configuration */ /* This file contains the table of built-in modules. - See init_builtin() in import.c. */ + See create_builtin() in import.c. */ #include "Python.h" diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -97,6 +97,15 @@ return return_value; } +PyDoc_STRVAR(_imp_create_builtin__doc__, +"create_builtin($module, spec, /)\n" +"--\n" +"\n" +"Create an extension module."); + +#define _IMP_CREATE_BUILTIN_METHODDEF \ + {"create_builtin", (PyCFunction)_imp_create_builtin, METH_O, _imp_create_builtin__doc__}, + PyDoc_STRVAR(_imp_extension_suffixes__doc__, "extension_suffixes($module, /)\n" "--\n" @@ -115,32 +124,6 @@ return _imp_extension_suffixes_impl(module); } -PyDoc_STRVAR(_imp_init_builtin__doc__, -"init_builtin($module, name, /)\n" -"--\n" -"\n" -"Initializes a built-in module."); - -#define _IMP_INIT_BUILTIN_METHODDEF \ - {"init_builtin", (PyCFunction)_imp_init_builtin, METH_O, _imp_init_builtin__doc__}, - -static PyObject * -_imp_init_builtin_impl(PyModuleDef *module, PyObject *name); - -static PyObject * -_imp_init_builtin(PyModuleDef *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *name; - - if (!PyArg_Parse(arg, "U:init_builtin", &name)) - goto exit; - return_value = _imp_init_builtin_impl(module, name); - -exit: - return return_value; -} - PyDoc_STRVAR(_imp_init_frozen__doc__, "init_frozen($module, name, /)\n" "--\n" @@ -273,31 +256,30 @@ #if defined(HAVE_DYNAMIC_LOADING) -PyDoc_STRVAR(_imp_load_dynamic__doc__, -"load_dynamic($module, name, path, file=None, /)\n" +PyDoc_STRVAR(_imp_create_dynamic__doc__, +"create_dynamic($module, spec, file=None, /)\n" "--\n" "\n" -"Loads an extension module."); +"Create an extension module."); -#define _IMP_LOAD_DYNAMIC_METHODDEF \ - {"load_dynamic", (PyCFunction)_imp_load_dynamic, METH_VARARGS, _imp_load_dynamic__doc__}, +#define _IMP_CREATE_DYNAMIC_METHODDEF \ + {"create_dynamic", (PyCFunction)_imp_create_dynamic, METH_VARARGS, _imp_create_dynamic__doc__}, static PyObject * -_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, - PyObject *file); +_imp_create_dynamic_impl(PyModuleDef *module, PyObject *spec, PyObject *file); static PyObject * -_imp_load_dynamic(PyModuleDef *module, PyObject *args) +_imp_create_dynamic(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; - PyObject *name; - PyObject *path; + PyObject *spec; PyObject *file = NULL; - if (!PyArg_ParseTuple(args, "UO&|O:load_dynamic", - &name, PyUnicode_FSDecoder, &path, &file)) + if (!PyArg_UnpackTuple(args, "create_dynamic", + 1, 2, + &spec, &file)) goto exit; - return_value = _imp_load_dynamic_impl(module, name, path, file); + return_value = _imp_create_dynamic_impl(module, spec, file); exit: return return_value; @@ -305,7 +287,42 @@ #endif /* defined(HAVE_DYNAMIC_LOADING) */ -#ifndef _IMP_LOAD_DYNAMIC_METHODDEF - #define _IMP_LOAD_DYNAMIC_METHODDEF -#endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=6d75cece35863874 input=a9049054013a1b77]*/ +#if defined(HAVE_DYNAMIC_LOADING) + +PyDoc_STRVAR(_imp_exec_dynamic__doc__, +"exec_dynamic($module, mod, /)\n" +"--\n" +"\n" +"Initialize an extension module."); + +#define _IMP_EXEC_DYNAMIC_METHODDEF \ + {"exec_dynamic", (PyCFunction)_imp_exec_dynamic, METH_O, _imp_exec_dynamic__doc__}, + +static int +_imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod); + +static PyObject * +_imp_exec_dynamic(PyModuleDef *module, PyObject *mod) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _imp_exec_dynamic_impl(module, mod); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DYNAMIC_LOADING) */ + +#ifndef _IMP_CREATE_DYNAMIC_METHODDEF + #define _IMP_CREATE_DYNAMIC_METHODDEF +#endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ + +#ifndef _IMP_EXEC_DYNAMIC_METHODDEF + #define _IMP_EXEC_DYNAMIC_METHODDEF +#endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ +/*[clinic end generated code: output=0f1059766dd58f88 input=a9049054013a1b77]*/ diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -154,8 +154,9 @@ } -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c --- a/Python/dynload_dl.c +++ b/Python/dynload_dl.c @@ -12,11 +12,12 @@ const char *_PyImport_DynLoadFiletab[] = {".o", NULL}; -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp) { char funcname[258]; - PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); + PyOS_snprintf(funcname, sizeof(funcname), "%20s_%.200s", prefix, shortname); return dl_loadmod(Py_GetProgramName(), pathname, funcname); } diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -8,15 +8,16 @@ #include "importdl.h" #if defined(__hp9000s300) -#define FUNCNAME_PATTERN "_PyInit_%.200s" +#define FUNCNAME_PATTERN "_%20s_%.200s" #else -#define FUNCNAME_PATTERN "PyInit_%.200s" +#define FUNCNAME_PATTERN "%20s_%.200s" #endif const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL}; -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp) { dl_funcptr p; shl_t lib; @@ -50,7 +51,8 @@ Py_DECREF(pathname_ob); return NULL; } - PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname); + PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, + prefix, shortname); if (Py_VerboseFlag) printf("shl_findsym %s\n", funcname); if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) { diff --git a/Python/dynload_next.c b/Python/dynload_next.c --- a/Python/dynload_next.c +++ b/Python/dynload_next.c @@ -27,8 +27,9 @@ #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE #endif -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp) { dl_funcptr p = NULL; char funcname[258]; @@ -39,7 +40,7 @@ const char *errString; char errBuf[512]; - PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname); + PyOS_snprintf(funcname, sizeof(funcname), "_%20s_%.200s", prefix, shortname); #ifdef USE_DYLD_GLOBAL_NAMESPACE if (NSIsSymbolNameDefined(funcname)) { diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -51,8 +51,10 @@ static int nhandles = 0; -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr +_PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp) { dl_funcptr p; void *handle; @@ -67,7 +69,7 @@ } PyOS_snprintf(funcname, sizeof(funcname), - LEAD_UNDERSCORE "PyInit_%.200s", shortname); + LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname); if (fp != NULL) { int i; diff --git a/Python/dynload_win.c b/Python/dynload_win.c --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -186,8 +186,9 @@ return NULL; } -dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, - PyObject *pathname, FILE *fp) +dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, + const char *shortname, + PyObject *pathname, FILE *fp) { dl_funcptr p; char funcname[258], *import_python; @@ -201,7 +202,7 @@ if (wpathname == NULL) return NULL; - PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); + PyOS_snprintf(funcname, sizeof(funcname), "%20_%.200s", prefix, shortname); { HINSTANCE hDLL = NULL; diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1026,50 +1026,74 @@ return importer; } +/*[clinic input] +_imp.create_builtin -static int init_builtin(PyObject *); /* Forward */ + spec: object + / -/* Initialize a built-in module. - Return 1 for success, 0 if the module is not found, and -1 with - an exception set if the initialization failed. */ +Create an extension module. +[clinic start generated code]*/ -static int -init_builtin(PyObject *name) +static PyObject * +_imp_create_builtin(PyModuleDef *module, PyObject *spec) +/*[clinic end generated code: output=5038f467617226bd input=37f966f890384e47]*/ { struct _inittab *p; + PyObject *name; + char *namestr; PyObject *mod; + name = PyObject_GetAttrString(spec, "name"); + if (name == NULL) { + return NULL; + } + mod = _PyImport_FindExtensionObject(name, name); - if (PyErr_Occurred()) - return -1; - if (mod != NULL) - return 1; + if (mod || PyErr_Occurred()) { + Py_DECREF(name); + Py_INCREF(mod); + return mod; + } + + namestr = PyUnicode_AsUTF8(name); + if (namestr == NULL) { + Py_DECREF(name); + return NULL; + } for (p = PyImport_Inittab; p->name != NULL; p++) { - PyObject *mod; PyModuleDef *def; if (PyUnicode_CompareWithASCIIString(name, p->name) == 0) { if (p->initfunc == NULL) { - PyErr_Format(PyExc_ImportError, - "Cannot re-init internal module %R", - name); - return -1; + /* Cannot re-init internal module ("sys" or "builtins") */ + mod = PyImport_AddModule(namestr); + Py_DECREF(name); + return mod; } mod = (*p->initfunc)(); - if (mod == 0) - return -1; - /* Remember pointer to module init function. */ - def = PyModule_GetDef(mod); - def->m_base.m_init = p->initfunc; - if (_PyImport_FixupExtensionObject(mod, name, name) < 0) - return -1; - /* FixupExtension has put the module into sys.modules, - so we can release our own reference. */ - Py_DECREF(mod); - return 1; + if (mod == NULL) { + Py_DECREF(name); + return NULL; + } + if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { + Py_DECREF(name); + return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); + } else { + /* Remember pointer to module init function. */ + def = PyModule_GetDef(mod); + def->m_base.m_init = p->initfunc; + if (_PyImport_FixupExtensionObject(mod, name, name) < 0) { + Py_DECREF(name); + return NULL; + } + Py_DECREF(name); + return mod; + } } } - return 0; + Py_DECREF(name); + Py_RETURN_NONE; } @@ -1821,34 +1845,6 @@ } /*[clinic input] -_imp.init_builtin - - name: unicode - / - -Initializes a built-in module. -[clinic start generated code]*/ - -static PyObject * -_imp_init_builtin_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=1868f473685f6d67 input=f934d2231ec52a2e]*/ -{ - int ret; - PyObject *m; - - ret = init_builtin(name); - if (ret < 0) - return NULL; - if (ret == 0) { - Py_INCREF(Py_None); - return Py_None; - } - m = PyImport_AddModuleObject(name); - Py_XINCREF(m); - return m; -} - -/*[clinic input] _imp.init_frozen name: unicode @@ -1946,40 +1942,100 @@ #ifdef HAVE_DYNAMIC_LOADING /*[clinic input] -_imp.load_dynamic +_imp.create_dynamic - name: unicode - path: fs_unicode + spec: object file: object = NULL / -Loads an extension module. +Create an extension module. [clinic start generated code]*/ static PyObject * -_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, - PyObject *file) -/*[clinic end generated code: output=e84e5f7f0f39bc54 input=af64f06e4bad3526]*/ +_imp_create_dynamic_impl(PyModuleDef *module, PyObject *spec, PyObject *file) +/*[clinic end generated code: output=935cde5b3872d56d input=c31b954f4cf4e09d]*/ { - PyObject *mod; + PyObject *mod, *name, *path; FILE *fp; + name = PyObject_GetAttrString(spec, "name"); + if (name == NULL) { + return NULL; + } + + path = PyObject_GetAttrString(spec, "origin"); + if (path == NULL) { + Py_DECREF(name); + return NULL; + } + + mod = _PyImport_FindExtensionObject(name, path); + if (mod != NULL) { + Py_DECREF(name); + Py_DECREF(path); + Py_INCREF(mod); + return mod; + } + if (file != NULL) { fp = _Py_fopen_obj(path, "r"); if (fp == NULL) { + Py_DECREF(name); Py_DECREF(path); return NULL; } } else fp = NULL; - mod = _PyImport_LoadDynamicModule(name, path, fp); + + mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp); + + Py_DECREF(name); Py_DECREF(path); if (fp) fclose(fp); return mod; } +/*[clinic input] +_imp.exec_dynamic -> int + + mod: object + / + +Initialize an extension module. +[clinic start generated code]*/ + +static int +_imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod) +/*[clinic end generated code: output=4b84f1301b22d4bd input=9fdbfcb250280d3a]*/ +{ + PyModuleDef *def; + void *state; + + if (!PyModule_Check(mod)) { + return 0; + } + + def = PyModule_GetDef(mod); + if (def == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + state = PyModule_GetState(mod); + if (PyErr_Occurred()) { + return -1; + } + if (state) { + /* Already initialized; skip reload */ + return 0; + } + return PyModule_ExecDef(mod, def); +} + + #endif /* HAVE_DYNAMIC_LOADING */ /*[clinic input] @@ -1998,11 +2054,12 @@ _IMP_RELEASE_LOCK_METHODDEF _IMP_GET_FROZEN_OBJECT_METHODDEF _IMP_IS_FROZEN_PACKAGE_METHODDEF - _IMP_INIT_BUILTIN_METHODDEF + _IMP_CREATE_BUILTIN_METHODDEF _IMP_INIT_FROZEN_METHODDEF _IMP_IS_BUILTIN_METHODDEF _IMP_IS_FROZEN_METHODDEF - _IMP_LOAD_DYNAMIC_METHODDEF + _IMP_CREATE_DYNAMIC_METHODDEF + _IMP_EXEC_DYNAMIC_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -13,87 +13,186 @@ #include "importdl.h" #ifdef MS_WINDOWS -extern dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, - PyObject *pathname, FILE *fp); +extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, + const char *shortname, + PyObject *pathname, + FILE *fp); #else -extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp); +extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, + const char *shortname, + const char *pathname, FILE *fp); #endif -PyObject * -_PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) -{ - PyObject *m = NULL; -#ifndef MS_WINDOWS - PyObject *pathbytes; -#endif - PyObject *nameascii; - char *namestr, *lastdot, *shortname, *packagecontext, *oldcontext; - dl_funcptr p0; - PyObject* (*p)(void); - struct PyModuleDef *def; +static const char *ascii_only_prefix = "PyInit"; +static const char *nonascii_prefix = "PyInitU"; - m = _PyImport_FindExtensionObject(name, path); - if (m != NULL) { - Py_INCREF(m); - return m; +/* Get the variable part of a module's export symbol name. + * Returns a bytes instance. For non-ASCII-named modules, the name is + * encoded as per PEP 489. + * The hook_prefix pointer is set to either ascii_only_prefix or + * nonascii_prefix, as appropriate. + */ +static PyObject * +get_encoded_name(PyObject *name, const char **hook_prefix) { + char *buf; + PyObject *tmp; + PyObject *encoded = NULL; + Py_ssize_t name_len, lastdot, i; + + /* Get the short name (substring after last dot) */ + name_len = PyUnicode_GetLength(name); + lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1); + if (lastdot < -1) { + return NULL; + } else if (lastdot >= 0) { + tmp = PyUnicode_Substring(name, lastdot, name_len); + if (tmp == NULL) + return NULL; + name = tmp; + /* "name" now holds a new reference to the substring */ + } else { + Py_INCREF(name); } - /* name must be encodable to ASCII because dynamic module must have a - function called "PyInit_NAME", they are written in C, and the C language - doesn't accept non-ASCII identifiers. */ - nameascii = PyUnicode_AsEncodedString(name, "ascii", NULL); - if (nameascii == NULL) + /* Encode to ASCII or Punycode, as needed */ + encoded = PyUnicode_AsEncodedString(name, "ascii", NULL); + if (encoded != NULL) { + *hook_prefix = ascii_only_prefix; + } else { + if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { + PyErr_Clear(); + encoded = PyUnicode_AsEncodedString(name, "punycode", NULL); + if (encoded == NULL) { + goto error; + } + *hook_prefix = nonascii_prefix; + } else { + goto error; + } + } + + buf = PyBytes_AS_STRING(encoded); + assert(Py_REFCNT(encoded) == 1); + for (i = 0; i < PyBytes_GET_SIZE(encoded) + 1; i++) { + if (buf[i] == '-') { + buf[i] = '_'; + } + } + + Py_DECREF(name); + return encoded; +error: + Py_DECREF(name); + Py_XDECREF(encoded); + return NULL; +} + +PyObject * +_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) +{ +#ifndef MS_WINDOWS + PyObject *pathbytes = NULL; +#endif + PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL; + const char *name_buf, *hook_prefix; + char *oldcontext; + dl_funcptr exportfunc; + PyModuleDef *def; + PyObject *(*p0)(void); + + name_unicode = PyObject_GetAttrString(spec, "name"); + if (name_unicode == NULL) { return NULL; + } - namestr = PyBytes_AS_STRING(nameascii); - if (namestr == NULL) + name = get_encoded_name(name_unicode, &hook_prefix); + if (name == NULL) { + goto error; + } + name_buf = PyBytes_AS_STRING(name); + + path = PyObject_GetAttrString(spec, "origin"); + if (path == NULL) goto error; - lastdot = strrchr(namestr, '.'); - if (lastdot == NULL) { - packagecontext = NULL; - shortname = namestr; - } - else { - packagecontext = namestr; - shortname = lastdot+1; - } - #ifdef MS_WINDOWS - p0 = _PyImport_GetDynLoadWindows(shortname, path, fp); + exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf, + path, fp); #else pathbytes = PyUnicode_EncodeFSDefault(path); if (pathbytes == NULL) goto error; - p0 = _PyImport_GetDynLoadFunc(shortname, - PyBytes_AS_STRING(pathbytes), fp); + exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf, + PyBytes_AS_STRING(pathbytes), + fp); Py_DECREF(pathbytes); #endif - p = (PyObject*(*)(void))p0; - if (PyErr_Occurred()) - goto error; - if (p == NULL) { - PyObject *msg = PyUnicode_FromFormat("dynamic module does not define " - "init function (PyInit_%s)", - shortname); - if (msg == NULL) - goto error; - PyErr_SetImportError(msg, name, path); - Py_DECREF(msg); + + if (exportfunc == NULL) { + if (!PyErr_Occurred()) { + PyObject *msg; + msg = PyUnicode_FromFormat( + "dynamic module does not define " + "module export function (%s_%s)", + hook_prefix, name_buf); + if (msg == NULL) + goto error; + PyErr_SetImportError(msg, name_unicode, path); + Py_DECREF(msg); + } goto error; } + + p0 = (PyObject *(*)(void))exportfunc; + + /* Package context is needed for single-phase init */ oldcontext = _Py_PackageContext; - _Py_PackageContext = packagecontext; - m = (*p)(); + _Py_PackageContext = PyUnicode_AsUTF8(name_unicode); + m = p0(); _Py_PackageContext = oldcontext; - if (m == NULL) + + if (m == NULL) { + if (!PyErr_Occurred()) { + PyErr_Format( + PyExc_SystemError, + "initialization of %s failed without raising an exception", + name_buf); + } goto error; + } else if (PyErr_Occurred()) { + PyErr_Clear(); + PyErr_Format( + PyExc_SystemError, + "initialization of %s raised unreported exception", + name_buf); + m = NULL; + goto error; + } + if (Py_TYPE(m) == NULL) { + /* This can happen when a PyModuleDef is returned without calling + * PyModuleDef_Init on it + */ + PyErr_Format(PyExc_SystemError, + "init function of %s returned uninitialized object", + name_buf); + m = NULL; /* prevent segfault in DECREF */ + goto error; + } + if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { + Py_DECREF(name_unicode); + Py_DECREF(name); + Py_DECREF(path); + return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); + } - if (PyErr_Occurred()) { - PyErr_Format(PyExc_SystemError, - "initialization of %s raised unreported exception", - shortname); + /* Fall back to single-phase init mechanism */ + + if (hook_prefix == nonascii_prefix) { + /* don't allow legacy init for non-ASCII module names */ + PyErr_Format( + PyExc_SystemError, + "initialization of * did not return PyModuleDef", + name_buf); goto error; } @@ -102,10 +201,10 @@ if (def == NULL) { PyErr_Format(PyExc_SystemError, "initialization of %s did not return an extension " - "module", shortname); + "module", name_buf); goto error; } - def->m_base.m_init = p; + def->m_base.m_init = p0; /* Remember the filename as the __file__ attribute */ if (PyModule_AddObject(m, "__file__", path) < 0) @@ -113,13 +212,19 @@ else Py_INCREF(path); - if (_PyImport_FixupExtensionObject(m, name, path) < 0) + if (_PyImport_FixupExtensionObject(m, name_unicode, path) < 0) goto error; - Py_DECREF(nameascii); + + Py_DECREF(name_unicode); + Py_DECREF(name); + Py_DECREF(path); + return m; error: - Py_DECREF(nameascii); + Py_DECREF(name_unicode); + Py_XDECREF(name); + Py_XDECREF(path); Py_XDECREF(m); return NULL; } diff --git a/Python/importdl.h b/Python/importdl.h --- a/Python/importdl.h +++ b/Python/importdl.h @@ -8,8 +8,7 @@ extern const char *_PyImport_DynLoadFiletab[]; -extern PyObject *_PyImport_LoadDynamicModule(PyObject *name, PyObject *pathname, - FILE *); +extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *); /* Max length of module suffix searched for -- accommodates "module.slb" */ #define MAXSUFFIXSIZE 12 diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1,7 +1,7 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__importlib_external[] = { 99,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, - 0,64,0,0,0,115,222,2,0,0,100,0,0,90,0,0, + 0,64,0,0,0,115,228,2,0,0,100,0,0,90,0,0, 100,96,0,90,1,0,100,4,0,100,5,0,132,0,0,90, 2,0,100,6,0,100,7,0,132,0,0,90,3,0,100,8, 0,100,9,0,132,0,0,90,4,0,100,10,0,100,11,0, @@ -38,1103 +38,1128 @@ 0,132,0,0,100,75,0,101,44,0,101,43,0,131,4,0, 90,45,0,71,100,76,0,100,77,0,132,0,0,100,77,0, 101,44,0,101,42,0,131,4,0,90,46,0,103,0,0,90, - 47,0,71,100,78,0,100,79,0,132,0,0,100,79,0,131, - 2,0,90,48,0,71,100,80,0,100,81,0,132,0,0,100, - 81,0,131,2,0,90,49,0,71,100,82,0,100,83,0,132, - 0,0,100,83,0,131,2,0,90,50,0,71,100,84,0,100, - 85,0,132,0,0,100,85,0,131,2,0,90,51,0,71,100, - 86,0,100,87,0,132,0,0,100,87,0,131,2,0,90,52, - 0,100,33,0,100,88,0,100,89,0,132,1,0,90,53,0, - 100,90,0,100,91,0,132,0,0,90,54,0,100,92,0,100, - 93,0,132,0,0,90,55,0,100,94,0,100,95,0,132,0, - 0,90,56,0,100,33,0,83,41,97,97,94,1,0,0,67, - 111,114,101,32,105,109,112,108,101,109,101,110,116,97,116,105, - 111,110,32,111,102,32,112,97,116,104,45,98,97,115,101,100, - 32,105,109,112,111,114,116,46,10,10,84,104,105,115,32,109, - 111,100,117,108,101,32,105,115,32,78,79,84,32,109,101,97, - 110,116,32,116,111,32,98,101,32,100,105,114,101,99,116,108, - 121,32,105,109,112,111,114,116,101,100,33,32,73,116,32,104, - 97,115,32,98,101,101,110,32,100,101,115,105,103,110,101,100, - 32,115,117,99,104,10,116,104,97,116,32,105,116,32,99,97, - 110,32,98,101,32,98,111,111,116,115,116,114,97,112,112,101, - 100,32,105,110,116,111,32,80,121,116,104,111,110,32,97,115, - 32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116, - 105,111,110,32,111,102,32,105,109,112,111,114,116,46,32,65, - 115,10,115,117,99,104,32,105,116,32,114,101,113,117,105,114, - 101,115,32,116,104,101,32,105,110,106,101,99,116,105,111,110, - 32,111,102,32,115,112,101,99,105,102,105,99,32,109,111,100, - 117,108,101,115,32,97,110,100,32,97,116,116,114,105,98,117, - 116,101,115,32,105,110,32,111,114,100,101,114,32,116,111,10, - 119,111,114,107,46,32,79,110,101,32,115,104,111,117,108,100, - 32,117,115,101,32,105,109,112,111,114,116,108,105,98,32,97, - 115,32,116,104,101,32,112,117,98,108,105,99,45,102,97,99, - 105,110,103,32,118,101,114,115,105,111,110,32,111,102,32,116, - 104,105,115,32,109,111,100,117,108,101,46,10,10,218,3,119, - 105,110,218,6,99,121,103,119,105,110,218,6,100,97,114,119, - 105,110,99,0,0,0,0,0,0,0,0,1,0,0,0,2, - 0,0,0,67,0,0,0,115,49,0,0,0,116,0,0,106, - 1,0,106,2,0,116,3,0,131,1,0,114,33,0,100,1, - 0,100,2,0,132,0,0,125,0,0,110,12,0,100,3,0, - 100,2,0,132,0,0,125,0,0,124,0,0,83,41,4,78, - 99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,83,0,0,0,115,13,0,0,0,100,1,0,116,0,0, - 106,1,0,107,6,0,83,41,2,122,53,84,114,117,101,32, - 105,102,32,102,105,108,101,110,97,109,101,115,32,109,117,115, - 116,32,98,101,32,99,104,101,99,107,101,100,32,99,97,115, - 101,45,105,110,115,101,110,115,105,116,105,118,101,108,121,46, - 115,12,0,0,0,80,89,84,72,79,78,67,65,83,69,79, - 75,41,2,218,3,95,111,115,90,7,101,110,118,105,114,111, - 110,169,0,114,4,0,0,0,114,4,0,0,0,250,38,60, - 102,114,111,122,101,110,32,105,109,112,111,114,116,108,105,98, - 46,95,98,111,111,116,115,116,114,97,112,95,101,120,116,101, - 114,110,97,108,62,218,11,95,114,101,108,97,120,95,99,97, - 115,101,30,0,0,0,115,2,0,0,0,0,2,122,37,95, - 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, - 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, - 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, - 0,1,0,0,0,83,0,0,0,115,4,0,0,0,100,1, - 0,83,41,2,122,53,84,114,117,101,32,105,102,32,102,105, - 108,101,110,97,109,101,115,32,109,117,115,116,32,98,101,32, - 99,104,101,99,107,101,100,32,99,97,115,101,45,105,110,115, - 101,110,115,105,116,105,118,101,108,121,46,70,114,4,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,6,0,0,0,34,0,0,0,115,2, - 0,0,0,0,2,41,4,218,3,115,121,115,218,8,112,108, - 97,116,102,111,114,109,218,10,115,116,97,114,116,115,119,105, - 116,104,218,27,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,41, - 1,114,6,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,16,95,109,97,107,101,95,114,101,108, - 97,120,95,99,97,115,101,28,0,0,0,115,8,0,0,0, - 0,1,18,1,15,4,12,3,114,11,0,0,0,99,1,0, - 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, - 0,0,115,26,0,0,0,116,0,0,124,0,0,131,1,0, - 100,1,0,64,106,1,0,100,2,0,100,3,0,131,2,0, - 83,41,4,122,42,67,111,110,118,101,114,116,32,97,32,51, - 50,45,98,105,116,32,105,110,116,101,103,101,114,32,116,111, - 32,108,105,116,116,108,101,45,101,110,100,105,97,110,46,108, - 3,0,0,0,255,127,255,127,3,0,233,4,0,0,0,218, - 6,108,105,116,116,108,101,41,2,218,3,105,110,116,218,8, - 116,111,95,98,121,116,101,115,41,1,218,1,120,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,7,95,119, - 95,108,111,110,103,40,0,0,0,115,2,0,0,0,0,2, - 114,17,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,16,0,0,0,116, - 0,0,106,1,0,124,0,0,100,1,0,131,2,0,83,41, - 2,122,47,67,111,110,118,101,114,116,32,52,32,98,121,116, - 101,115,32,105,110,32,108,105,116,116,108,101,45,101,110,100, - 105,97,110,32,116,111,32,97,110,32,105,110,116,101,103,101, - 114,46,114,13,0,0,0,41,2,114,14,0,0,0,218,10, - 102,114,111,109,95,98,121,116,101,115,41,1,90,9,105,110, - 116,95,98,121,116,101,115,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,7,95,114,95,108,111,110,103,45, - 0,0,0,115,2,0,0,0,0,2,114,19,0,0,0,99, - 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 71,0,0,0,115,26,0,0,0,116,0,0,106,1,0,100, - 1,0,100,2,0,132,0,0,124,0,0,68,131,1,0,131, - 1,0,83,41,3,122,31,82,101,112,108,97,99,101,109,101, - 110,116,32,102,111,114,32,111,115,46,112,97,116,104,46,106, - 111,105,110,40,41,46,99,1,0,0,0,0,0,0,0,2, - 0,0,0,4,0,0,0,83,0,0,0,115,37,0,0,0, - 103,0,0,124,0,0,93,27,0,125,1,0,124,1,0,114, - 6,0,124,1,0,106,0,0,116,1,0,131,1,0,145,2, - 0,113,6,0,83,114,4,0,0,0,41,2,218,6,114,115, - 116,114,105,112,218,15,112,97,116,104,95,115,101,112,97,114, - 97,116,111,114,115,41,2,218,2,46,48,218,4,112,97,114, - 116,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 250,10,60,108,105,115,116,99,111,109,112,62,52,0,0,0, - 115,2,0,0,0,9,1,122,30,95,112,97,116,104,95,106, - 111,105,110,46,60,108,111,99,97,108,115,62,46,60,108,105, - 115,116,99,111,109,112,62,41,2,218,8,112,97,116,104,95, - 115,101,112,218,4,106,111,105,110,41,1,218,10,112,97,116, - 104,95,112,97,114,116,115,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,10,95,112,97,116,104,95,106,111, - 105,110,50,0,0,0,115,4,0,0,0,0,2,15,1,114, - 28,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, - 0,5,0,0,0,67,0,0,0,115,134,0,0,0,116,0, - 0,116,1,0,131,1,0,100,1,0,107,2,0,114,52,0, - 124,0,0,106,2,0,116,3,0,131,1,0,92,3,0,125, - 1,0,125,2,0,125,3,0,124,1,0,124,3,0,102,2, - 0,83,120,69,0,116,4,0,124,0,0,131,1,0,68,93, - 55,0,125,4,0,124,4,0,116,1,0,107,6,0,114,65, - 0,124,0,0,106,5,0,124,4,0,100,2,0,100,1,0, - 131,1,1,92,2,0,125,1,0,125,3,0,124,1,0,124, - 3,0,102,2,0,83,113,65,0,87,100,3,0,124,0,0, - 102,2,0,83,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,90,8,109, - 97,120,115,112,108,105,116,218,0,41,6,218,3,108,101,110, - 114,21,0,0,0,218,10,114,112,97,114,116,105,116,105,111, - 110,114,25,0,0,0,218,8,114,101,118,101,114,115,101,100, - 218,6,114,115,112,108,105,116,41,5,218,4,112,97,116,104, - 90,5,102,114,111,110,116,218,1,95,218,4,116,97,105,108, - 114,16,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,218,11,95,112,97,116,104,95,115,112,108,105, - 116,56,0,0,0,115,16,0,0,0,0,2,18,1,24,1, - 10,1,19,1,12,1,27,1,14,1,114,38,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,13,0,0,0,116,0,0,106,1,0,124, - 0,0,131,1,0,83,41,1,122,126,83,116,97,116,32,116, - 104,101,32,112,97,116,104,46,10,10,32,32,32,32,77,97, - 100,101,32,97,32,115,101,112,97,114,97,116,101,32,102,117, - 110,99,116,105,111,110,32,116,111,32,109,97,107,101,32,105, - 116,32,101,97,115,105,101,114,32,116,111,32,111,118,101,114, - 114,105,100,101,32,105,110,32,101,120,112,101,114,105,109,101, - 110,116,115,10,32,32,32,32,40,101,46,103,46,32,99,97, - 99,104,101,32,115,116,97,116,32,114,101,115,117,108,116,115, - 41,46,10,10,32,32,32,32,41,2,114,3,0,0,0,90, - 4,115,116,97,116,41,1,114,35,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,10,95,112,97, - 116,104,95,115,116,97,116,68,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,11,0,0,0,67,0,0,0,115,58,0,0, - 0,121,16,0,116,0,0,124,0,0,131,1,0,125,2,0, - 87,110,22,0,4,116,1,0,107,10,0,114,40,0,1,1, - 1,100,1,0,83,89,110,1,0,88,124,2,0,106,2,0, - 100,2,0,64,124,1,0,107,2,0,83,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,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,18,95,112,97,116,104,95,105,115, - 95,109,111,100,101,95,116,121,112,101,78,0,0,0,115,10, - 0,0,0,0,2,3,1,16,1,13,1,9,1,114,43,0, + 47,0,71,100,78,0,100,79,0,132,0,0,100,79,0,101, + 44,0,101,42,0,131,4,0,90,48,0,71,100,80,0,100, + 81,0,132,0,0,100,81,0,131,2,0,90,49,0,71,100, + 82,0,100,83,0,132,0,0,100,83,0,131,2,0,90,50, + 0,71,100,84,0,100,85,0,132,0,0,100,85,0,131,2, + 0,90,51,0,71,100,86,0,100,87,0,132,0,0,100,87, + 0,131,2,0,90,52,0,100,33,0,100,88,0,100,89,0, + 132,1,0,90,53,0,100,90,0,100,91,0,132,0,0,90, + 54,0,100,92,0,100,93,0,132,0,0,90,55,0,100,94, + 0,100,95,0,132,0,0,90,56,0,100,33,0,83,41,97, + 97,94,1,0,0,67,111,114,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,112,97,116,104, + 45,98,97,115,101,100,32,105,109,112,111,114,116,46,10,10, + 84,104,105,115,32,109,111,100,117,108,101,32,105,115,32,78, + 79,84,32,109,101,97,110,116,32,116,111,32,98,101,32,100, + 105,114,101,99,116,108,121,32,105,109,112,111,114,116,101,100, + 33,32,73,116,32,104,97,115,32,98,101,101,110,32,100,101, + 115,105,103,110,101,100,32,115,117,99,104,10,116,104,97,116, + 32,105,116,32,99,97,110,32,98,101,32,98,111,111,116,115, + 116,114,97,112,112,101,100,32,105,110,116,111,32,80,121,116, + 104,111,110,32,97,115,32,116,104,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,105,109,112, + 111,114,116,46,32,65,115,10,115,117,99,104,32,105,116,32, + 114,101,113,117,105,114,101,115,32,116,104,101,32,105,110,106, + 101,99,116,105,111,110,32,111,102,32,115,112,101,99,105,102, + 105,99,32,109,111,100,117,108,101,115,32,97,110,100,32,97, + 116,116,114,105,98,117,116,101,115,32,105,110,32,111,114,100, + 101,114,32,116,111,10,119,111,114,107,46,32,79,110,101,32, + 115,104,111,117,108,100,32,117,115,101,32,105,109,112,111,114, + 116,108,105,98,32,97,115,32,116,104,101,32,112,117,98,108, + 105,99,45,102,97,99,105,110,103,32,118,101,114,115,105,111, + 110,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101, + 46,10,10,218,3,119,105,110,218,6,99,121,103,119,105,110, + 218,6,100,97,114,119,105,110,99,0,0,0,0,0,0,0, + 0,1,0,0,0,2,0,0,0,67,0,0,0,115,49,0, + 0,0,116,0,0,106,1,0,106,2,0,116,3,0,131,1, + 0,114,33,0,100,1,0,100,2,0,132,0,0,125,0,0, + 110,12,0,100,3,0,100,2,0,132,0,0,125,0,0,124, + 0,0,83,41,4,78,99,0,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,83,0,0,0,115,13,0,0,0, + 100,1,0,116,0,0,106,1,0,107,6,0,83,41,2,122, + 53,84,114,117,101,32,105,102,32,102,105,108,101,110,97,109, + 101,115,32,109,117,115,116,32,98,101,32,99,104,101,99,107, + 101,100,32,99,97,115,101,45,105,110,115,101,110,115,105,116, + 105,118,101,108,121,46,115,12,0,0,0,80,89,84,72,79, + 78,67,65,83,69,79,75,41,2,218,3,95,111,115,90,7, + 101,110,118,105,114,111,110,169,0,114,4,0,0,0,114,4, + 0,0,0,250,38,60,102,114,111,122,101,110,32,105,109,112, + 111,114,116,108,105,98,46,95,98,111,111,116,115,116,114,97, + 112,95,101,120,116,101,114,110,97,108,62,218,11,95,114,101, + 108,97,120,95,99,97,115,101,30,0,0,0,115,2,0,0, + 0,0,2,122,37,95,109,97,107,101,95,114,101,108,97,120, + 95,99,97,115,101,46,60,108,111,99,97,108,115,62,46,95, + 114,101,108,97,120,95,99,97,115,101,99,0,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,83,0,0,0,115, + 4,0,0,0,100,1,0,83,41,2,122,53,84,114,117,101, + 32,105,102,32,102,105,108,101,110,97,109,101,115,32,109,117, + 115,116,32,98,101,32,99,104,101,99,107,101,100,32,99,97, + 115,101,45,105,110,115,101,110,115,105,116,105,118,101,108,121, + 46,70,114,4,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,6,0,0,0, + 34,0,0,0,115,2,0,0,0,0,2,41,4,218,3,115, + 121,115,218,8,112,108,97,116,102,111,114,109,218,10,115,116, + 97,114,116,115,119,105,116,104,218,27,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,41,1,114,6,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,218,16,95,109,97, + 107,101,95,114,101,108,97,120,95,99,97,115,101,28,0,0, + 0,115,8,0,0,0,0,1,18,1,15,4,12,3,114,11, + 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,26,0,0,0,116,0,0, + 124,0,0,131,1,0,100,1,0,64,106,1,0,100,2,0, + 100,3,0,131,2,0,83,41,4,122,42,67,111,110,118,101, + 114,116,32,97,32,51,50,45,98,105,116,32,105,110,116,101, + 103,101,114,32,116,111,32,108,105,116,116,108,101,45,101,110, + 100,105,97,110,46,108,3,0,0,0,255,127,255,127,3,0, + 233,4,0,0,0,218,6,108,105,116,116,108,101,41,2,218, + 3,105,110,116,218,8,116,111,95,98,121,116,101,115,41,1, + 218,1,120,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,218,7,95,119,95,108,111,110,103,40,0,0,0,115, + 2,0,0,0,0,2,114,17,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,16,0,0,0,116,0,0,106,1,0,124,0,0,100,1, + 0,131,2,0,83,41,2,122,47,67,111,110,118,101,114,116, + 32,52,32,98,121,116,101,115,32,105,110,32,108,105,116,116, + 108,101,45,101,110,100,105,97,110,32,116,111,32,97,110,32, + 105,110,116,101,103,101,114,46,114,13,0,0,0,41,2,114, + 14,0,0,0,218,10,102,114,111,109,95,98,121,116,101,115, + 41,1,90,9,105,110,116,95,98,121,116,101,115,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,7,95,114, + 95,108,111,110,103,45,0,0,0,115,2,0,0,0,0,2, + 114,19,0,0,0,99,0,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,71,0,0,0,115,26,0,0,0,116, + 0,0,106,1,0,100,1,0,100,2,0,132,0,0,124,0, + 0,68,131,1,0,131,1,0,83,41,3,122,31,82,101,112, + 108,97,99,101,109,101,110,116,32,102,111,114,32,111,115,46, + 112,97,116,104,46,106,111,105,110,40,41,46,99,1,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,83,0,0, + 0,115,37,0,0,0,103,0,0,124,0,0,93,27,0,125, + 1,0,124,1,0,114,6,0,124,1,0,106,0,0,116,1, + 0,131,1,0,145,2,0,113,6,0,83,114,4,0,0,0, + 41,2,218,6,114,115,116,114,105,112,218,15,112,97,116,104, + 95,115,101,112,97,114,97,116,111,114,115,41,2,218,2,46, + 48,218,4,112,97,114,116,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,250,10,60,108,105,115,116,99,111,109, + 112,62,52,0,0,0,115,2,0,0,0,9,1,122,30,95, + 112,97,116,104,95,106,111,105,110,46,60,108,111,99,97,108, + 115,62,46,60,108,105,115,116,99,111,109,112,62,41,2,218, + 8,112,97,116,104,95,115,101,112,218,4,106,111,105,110,41, + 1,218,10,112,97,116,104,95,112,97,114,116,115,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,112, + 97,116,104,95,106,111,105,110,50,0,0,0,115,4,0,0, + 0,0,2,15,1,114,28,0,0,0,99,1,0,0,0,0, + 0,0,0,5,0,0,0,5,0,0,0,67,0,0,0,115, + 134,0,0,0,116,0,0,116,1,0,131,1,0,100,1,0, + 107,2,0,114,52,0,124,0,0,106,2,0,116,3,0,131, + 1,0,92,3,0,125,1,0,125,2,0,125,3,0,124,1, + 0,124,3,0,102,2,0,83,120,69,0,116,4,0,124,0, + 0,131,1,0,68,93,55,0,125,4,0,124,4,0,116,1, + 0,107,6,0,114,65,0,124,0,0,106,5,0,124,4,0, + 100,2,0,100,1,0,131,1,1,92,2,0,125,1,0,125, + 3,0,124,1,0,124,3,0,102,2,0,83,113,65,0,87, + 100,3,0,124,0,0,102,2,0,83,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,90,8,109,97,120,115,112,108,105,116,218,0,41, + 6,218,3,108,101,110,114,21,0,0,0,218,10,114,112,97, + 114,116,105,116,105,111,110,114,25,0,0,0,218,8,114,101, + 118,101,114,115,101,100,218,6,114,115,112,108,105,116,41,5, + 218,4,112,97,116,104,90,5,102,114,111,110,116,218,1,95, + 218,4,116,97,105,108,114,16,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,11,95,112,97,116, + 104,95,115,112,108,105,116,56,0,0,0,115,16,0,0,0, + 0,2,18,1,24,1,10,1,19,1,12,1,27,1,14,1, + 114,38,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,13,0,0,0,116, + 0,0,106,1,0,124,0,0,131,1,0,83,41,1,122,126, + 83,116,97,116,32,116,104,101,32,112,97,116,104,46,10,10, + 32,32,32,32,77,97,100,101,32,97,32,115,101,112,97,114, + 97,116,101,32,102,117,110,99,116,105,111,110,32,116,111,32, + 109,97,107,101,32,105,116,32,101,97,115,105,101,114,32,116, + 111,32,111,118,101,114,114,105,100,101,32,105,110,32,101,120, + 112,101,114,105,109,101,110,116,115,10,32,32,32,32,40,101, + 46,103,46,32,99,97,99,104,101,32,115,116,97,116,32,114, + 101,115,117,108,116,115,41,46,10,10,32,32,32,32,41,2, + 114,3,0,0,0,90,4,115,116,97,116,41,1,114,35,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,10,95,112,97,116,104,95,115,116,97,116,68,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,11,0,0,0,67,0, + 0,0,115,58,0,0,0,121,16,0,116,0,0,124,0,0, + 131,1,0,125,2,0,87,110,22,0,4,116,1,0,107,10, + 0,114,40,0,1,1,1,100,1,0,83,89,110,1,0,88, + 124,2,0,106,2,0,100,2,0,64,124,1,0,107,2,0, + 83,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,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,18,95,112, + 97,116,104,95,105,115,95,109,111,100,101,95,116,121,112,101, + 78,0,0,0,115,10,0,0,0,0,2,3,1,16,1,13, + 1,9,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,13,0, + 0,0,116,0,0,124,0,0,100,1,0,131,2,0,83,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,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,12,95,112,97,116,104,95,105,115,102,105, + 108,101,87,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,13,0,0,0,116,0,0,124, - 0,0,100,1,0,131,2,0,83,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, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,12, - 95,112,97,116,104,95,105,115,102,105,108,101,87,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,31,0,0,0,124,0,0,115,18,0,116,0,0,106, - 1,0,131,0,0,125,0,0,116,2,0,124,0,0,100,1, - 0,131,2,0,83,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,3, - 0,0,0,218,6,103,101,116,99,119,100,114,43,0,0,0, - 41,1,114,35,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,11,95,112,97,116,104,95,105,115, - 100,105,114,92,0,0,0,115,6,0,0,0,0,2,6,1, - 12,1,114,46,0,0,0,105,182,1,0,0,99,3,0,0, - 0,0,0,0,0,6,0,0,0,17,0,0,0,67,0,0, - 0,115,193,0,0,0,100,1,0,106,0,0,124,0,0,116, - 1,0,124,0,0,131,1,0,131,2,0,125,3,0,116,2, - 0,106,3,0,124,3,0,116,2,0,106,4,0,116,2,0, - 106,5,0,66,116,2,0,106,6,0,66,124,2,0,100,2, - 0,64,131,3,0,125,4,0,121,61,0,116,7,0,106,8, - 0,124,4,0,100,3,0,131,2,0,143,20,0,125,5,0, - 124,5,0,106,9,0,124,1,0,131,1,0,1,87,100,4, - 0,81,82,88,116,2,0,106,10,0,124,3,0,124,0,0, - 131,2,0,1,87,110,59,0,4,116,11,0,107,10,0,114, - 188,0,1,1,1,121,17,0,116,2,0,106,12,0,124,3, - 0,131,1,0,1,87,110,18,0,4,116,11,0,107,10,0, - 114,180,0,1,1,1,89,110,1,0,88,130,0,0,89,110, - 1,0,88,100,4,0,83,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,3,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,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,13,95,119,114,105,116,101,95,97,116,111,109,105,99, - 99,0,0,0,115,26,0,0,0,0,5,24,1,9,1,33, - 1,3,3,21,1,20,1,20,1,13,1,3,1,17,1,13, - 1,5,1,114,55,0,0,0,105,2,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,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,87,1,0,0,124,1,0,100,1,0,107,9,0,114,76, - 0,116,0,0,106,1,0,100,2,0,116,2,0,131,2,0, - 1,124,2,0,100,1,0,107,9,0,114,58,0,100,3,0, - 125,3,0,116,3,0,124,3,0,131,1,0,130,1,0,124, - 1,0,114,70,0,100,4,0,110,3,0,100,5,0,125,2, - 0,116,4,0,124,0,0,131,1,0,92,2,0,125,4,0, - 125,5,0,124,5,0,106,5,0,100,6,0,131,1,0,92, - 3,0,125,6,0,125,7,0,125,8,0,116,6,0,106,7, - 0,106,8,0,125,9,0,124,9,0,100,1,0,107,8,0, - 114,154,0,116,9,0,100,7,0,131,1,0,130,1,0,100, - 4,0,106,10,0,124,6,0,114,172,0,124,6,0,110,3, - 0,124,8,0,124,7,0,124,9,0,103,3,0,131,1,0, - 125,10,0,124,2,0,100,1,0,107,8,0,114,241,0,116, - 6,0,106,11,0,106,12,0,100,8,0,107,2,0,114,229, - 0,100,4,0,125,2,0,110,12,0,116,6,0,106,11,0, - 106,12,0,125,2,0,116,13,0,124,2,0,131,1,0,125, - 2,0,124,2,0,100,4,0,107,3,0,114,63,1,124,2, - 0,106,14,0,131,0,0,115,42,1,116,15,0,100,9,0, - 106,16,0,124,2,0,131,1,0,131,1,0,130,1,0,100, - 10,0,106,16,0,124,10,0,116,17,0,124,2,0,131,3, - 0,125,10,0,116,18,0,124,4,0,116,19,0,124,10,0, - 116,20,0,100,8,0,25,23,131,3,0,83,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, + 0,0,0,67,0,0,0,115,31,0,0,0,124,0,0,115, + 18,0,116,0,0,106,1,0,131,0,0,125,0,0,116,2, + 0,124,0,0,100,1,0,131,2,0,83,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,3,0,0,0,218,6,103,101,116,99,119, + 100,114,43,0,0,0,41,1,114,35,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,11,95,112, + 97,116,104,95,105,115,100,105,114,92,0,0,0,115,6,0, + 0,0,0,2,6,1,12,1,114,46,0,0,0,105,182,1, + 0,0,99,3,0,0,0,0,0,0,0,6,0,0,0,17, + 0,0,0,67,0,0,0,115,193,0,0,0,100,1,0,106, + 0,0,124,0,0,116,1,0,124,0,0,131,1,0,131,2, + 0,125,3,0,116,2,0,106,3,0,124,3,0,116,2,0, + 106,4,0,116,2,0,106,5,0,66,116,2,0,106,6,0, + 66,124,2,0,100,2,0,64,131,3,0,125,4,0,121,61, + 0,116,7,0,106,8,0,124,4,0,100,3,0,131,2,0, + 143,20,0,125,5,0,124,5,0,106,9,0,124,1,0,131, + 1,0,1,87,100,4,0,81,82,88,116,2,0,106,10,0, + 124,3,0,124,0,0,131,2,0,1,87,110,59,0,4,116, + 11,0,107,10,0,114,188,0,1,1,1,121,17,0,116,2, + 0,106,12,0,124,3,0,131,1,0,1,87,110,18,0,4, + 116,11,0,107,10,0,114,180,0,1,1,1,89,110,1,0, + 88,130,0,0,89,110,1,0,88,100,4,0,83,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,3,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,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,13,95,119,114,105,116,101,95, + 97,116,111,109,105,99,99,0,0,0,115,26,0,0,0,0, + 5,24,1,9,1,33,1,3,3,21,1,20,1,20,1,13, + 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,2, + 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,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,87,1,0,0,124,1,0,100,1, + 0,107,9,0,114,76,0,116,0,0,106,1,0,100,2,0, + 116,2,0,131,2,0,1,124,2,0,100,1,0,107,9,0, + 114,58,0,100,3,0,125,3,0,116,3,0,124,3,0,131, + 1,0,130,1,0,124,1,0,114,70,0,100,4,0,110,3, + 0,100,5,0,125,2,0,116,4,0,124,0,0,131,1,0, + 92,2,0,125,4,0,125,5,0,124,5,0,106,5,0,100, + 6,0,131,1,0,92,3,0,125,6,0,125,7,0,125,8, + 0,116,6,0,106,7,0,106,8,0,125,9,0,124,9,0, + 100,1,0,107,8,0,114,154,0,116,9,0,100,7,0,131, + 1,0,130,1,0,100,4,0,106,10,0,124,6,0,114,172, + 0,124,6,0,110,3,0,124,8,0,124,7,0,124,9,0, + 103,3,0,131,1,0,125,10,0,124,2,0,100,1,0,107, + 8,0,114,241,0,116,6,0,106,11,0,106,12,0,100,8, + 0,107,2,0,114,229,0,100,4,0,125,2,0,110,12,0, + 116,6,0,106,11,0,106,12,0,125,2,0,116,13,0,124, + 2,0,131,1,0,125,2,0,124,2,0,100,4,0,107,3, + 0,114,63,1,124,2,0,106,14,0,131,0,0,115,42,1, + 116,15,0,100,9,0,106,16,0,124,2,0,131,1,0,131, + 1,0,130,1,0,100,10,0,106,16,0,124,10,0,116,17, + 0,124,2,0,131,3,0,125,10,0,116,18,0,124,4,0, + 116,19,0,124,10,0,116,20,0,100,8,0,25,23,131,3, + 0,83,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, + 21,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,38,0,0,0,114,32,0,0,0,114,7,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,47,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,57,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,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,17,99,97,99,104,101,95,102,114,111,109,95, + 115,111,117,114,99,101,241,0,0,0,115,46,0,0,0,0, + 18,12,1,9,1,7,1,12,1,6,1,12,1,18,1,18, + 1,24,1,12,1,12,1,12,1,36,1,12,1,18,1,9, + 2,12,1,12,1,12,1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106, + 1,0,106,2,0,100,1,0,107,8,0,114,30,0,116,3, + 0,100,2,0,131,1,0,130,1,0,116,4,0,124,0,0, + 131,1,0,92,2,0,125,1,0,125,2,0,116,4,0,124, + 1,0,131,1,0,92,2,0,125,1,0,125,3,0,124,3, + 0,116,5,0,107,3,0,114,102,0,116,6,0,100,3,0, + 106,7,0,116,5,0,124,0,0,131,2,0,131,1,0,130, + 1,0,124,2,0,106,8,0,100,4,0,131,1,0,125,4, + 0,124,4,0,100,11,0,107,7,0,114,153,0,116,6,0, + 100,7,0,106,7,0,124,2,0,131,1,0,131,1,0,130, + 1,0,110,125,0,124,4,0,100,6,0,107,2,0,114,22, + 1,124,2,0,106,9,0,100,4,0,100,5,0,131,2,0, + 100,12,0,25,125,5,0,124,5,0,106,10,0,116,11,0, + 131,1,0,115,223,0,116,6,0,100,8,0,106,7,0,116, + 11,0,131,1,0,131,1,0,130,1,0,124,5,0,116,12, + 0,116,11,0,131,1,0,100,1,0,133,2,0,25,125,6, + 0,124,6,0,106,13,0,131,0,0,115,22,1,116,6,0, + 100,9,0,106,7,0,124,5,0,131,1,0,131,1,0,130, + 1,0,124,2,0,106,14,0,100,4,0,131,1,0,100,10, + 0,25,125,7,0,116,15,0,124,1,0,124,7,0,116,16, + 0,100,10,0,25,23,131,2,0,83,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,99,32,102,105,108, - 101,46,10,10,32,32,32,32,84,104,101,32,46,112,121,32, + 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,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,21,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,38,0,0,0, - 114,32,0,0,0,114,7,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,47,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,57, - 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,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,17,99, - 97,99,104,101,95,102,114,111,109,95,115,111,117,114,99,101, - 241,0,0,0,115,46,0,0,0,0,18,12,1,9,1,7, - 1,12,1,6,1,12,1,18,1,18,1,24,1,12,1,12, - 1,12,1,36,1,12,1,18,1,9,2,12,1,12,1,12, - 1,12,1,21,1,21,1,114,79,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,62,1,0,0,116,0,0,106,1,0,106,2,0,100, - 1,0,107,8,0,114,30,0,116,3,0,100,2,0,131,1, - 0,130,1,0,116,4,0,124,0,0,131,1,0,92,2,0, - 125,1,0,125,2,0,116,4,0,124,1,0,131,1,0,92, - 2,0,125,1,0,125,3,0,124,3,0,116,5,0,107,3, - 0,114,102,0,116,6,0,100,3,0,106,7,0,116,5,0, - 124,0,0,131,2,0,131,1,0,130,1,0,124,2,0,106, - 8,0,100,4,0,131,1,0,125,4,0,124,4,0,100,11, - 0,107,7,0,114,153,0,116,6,0,100,7,0,106,7,0, - 124,2,0,131,1,0,131,1,0,130,1,0,110,125,0,124, - 4,0,100,6,0,107,2,0,114,22,1,124,2,0,106,9, - 0,100,4,0,100,5,0,131,2,0,100,12,0,25,125,5, - 0,124,5,0,106,10,0,116,11,0,131,1,0,115,223,0, - 116,6,0,100,8,0,106,7,0,116,11,0,131,1,0,131, - 1,0,130,1,0,124,5,0,116,12,0,116,11,0,131,1, - 0,100,1,0,133,2,0,25,125,6,0,124,6,0,106,13, - 0,131,0,0,115,22,1,116,6,0,100,9,0,106,7,0, - 124,5,0,131,1,0,131,1,0,130,1,0,124,2,0,106, - 14,0,100,4,0,131,1,0,100,10,0,25,125,7,0,116, - 15,0,124,1,0,124,7,0,116,16,0,100,10,0,25,23, - 131,2,0,83,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,58,0,0,0,114,56,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,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,59,0,0,0,62, - 2,0,0,0,114,56,0,0,0,114,80,0,0,0,233,254, - 255,255,255,41,17,114,7,0,0,0,114,64,0,0,0,114, - 65,0,0,0,114,66,0,0,0,114,38,0,0,0,114,73, - 0,0,0,114,71,0,0,0,114,47,0,0,0,218,5,99, - 111,117,110,116,114,34,0,0,0,114,9,0,0,0,114,72, - 0,0,0,114,31,0,0,0,114,70,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,76,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,57,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, + 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,58,0, + 0,0,114,56,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,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,59,0,0,0,62,2,0,0,0,114,56,0,0,0,114, + 80,0,0,0,233,254,255,255,255,41,17,114,7,0,0,0, + 114,64,0,0,0,114,65,0,0,0,114,66,0,0,0,114, + 38,0,0,0,114,73,0,0,0,114,71,0,0,0,114,47, + 0,0,0,218,5,99,111,117,110,116,114,34,0,0,0,114, + 9,0,0,0,114,72,0,0,0,114,31,0,0,0,114,70, + 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,76,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,57,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,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111, + 109,95,99,97,99,104,101,29,1,0,0,115,44,0,0,0, + 0,9,18,1,12,1,18,1,18,1,12,1,9,1,15,1, + 15,1,12,1,9,1,15,1,12,1,22,1,15,1,9,1, + 12,1,22,1,12,1,9,1,12,1,19,1,114,85,0,0, + 0,99,1,0,0,0,0,0,0,0,5,0,0,0,12,0, + 0,0,67,0,0,0,115,164,0,0,0,116,0,0,124,0, + 0,131,1,0,100,1,0,107,2,0,114,22,0,100,2,0, + 83,124,0,0,106,1,0,100,3,0,131,1,0,92,3,0, + 125,1,0,125,2,0,125,3,0,124,1,0,12,115,81,0, + 124,3,0,106,2,0,131,0,0,100,7,0,100,8,0,133, + 2,0,25,100,6,0,107,3,0,114,85,0,124,0,0,83, + 121,16,0,116,3,0,124,0,0,131,1,0,125,4,0,87, + 110,40,0,4,116,4,0,116,5,0,102,2,0,107,10,0, + 114,143,0,1,1,1,124,0,0,100,2,0,100,9,0,133, + 2,0,25,125,4,0,89,110,1,0,88,116,6,0,124,4, + 0,131,1,0,114,160,0,124,4,0,83,124,0,0,83,41, + 10,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, + 59,0,0,0,78,114,58,0,0,0,114,80,0,0,0,114, + 29,0,0,0,90,2,112,121,233,253,255,255,255,233,255,255, + 255,255,114,87,0,0,0,41,7,114,31,0,0,0,114,32, + 0,0,0,218,5,108,111,119,101,114,114,85,0,0,0,114, + 66,0,0,0,114,71,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, + 78,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,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108, + 101,62,1,0,0,115,20,0,0,0,0,7,18,1,4,1, + 24,1,35,1,4,1,3,1,16,1,19,1,21,1,114,91, + 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, + 11,0,0,0,67,0,0,0,115,92,0,0,0,124,0,0, + 106,0,0,116,1,0,116,2,0,131,1,0,131,1,0,114, + 59,0,121,14,0,116,3,0,124,0,0,131,1,0,83,87, + 113,88,0,4,116,4,0,107,10,0,114,55,0,1,1,1, + 89,113,88,0,88,110,29,0,124,0,0,106,0,0,116,1, + 0,116,5,0,131,1,0,131,1,0,114,84,0,124,0,0, + 83,100,0,0,83,100,0,0,83,41,1,78,41,6,218,8, + 101,110,100,115,119,105,116,104,218,5,116,117,112,108,101,114, + 84,0,0,0,114,79,0,0,0,114,66,0,0,0,114,74, + 0,0,0,41,1,218,8,102,105,108,101,110,97,109,101,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, + 95,103,101,116,95,99,97,99,104,101,100,81,1,0,0,115, + 16,0,0,0,0,1,21,1,3,1,14,1,13,1,8,1, + 21,1,4,2,114,95,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,60, + 0,0,0,121,19,0,116,0,0,124,0,0,131,1,0,106, + 1,0,125,1,0,87,110,24,0,4,116,2,0,107,10,0, + 114,45,0,1,1,1,100,1,0,125,1,0,89,110,1,0, + 88,124,1,0,100,2,0,79,125,1,0,124,1,0,83,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,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,99, + 97,108,99,95,109,111,100,101,93,1,0,0,115,12,0,0, + 0,0,2,3,1,19,1,13,1,11,3,10,1,114,97,0, + 0,0,218,9,118,101,114,98,111,115,105,116,121,114,29,0, + 0,0,99,1,0,0,0,1,0,0,0,3,0,0,0,4, + 0,0,0,71,0,0,0,115,75,0,0,0,116,0,0,106, + 1,0,106,2,0,124,1,0,107,5,0,114,71,0,124,0, + 0,106,3,0,100,6,0,131,1,0,115,43,0,100,3,0, + 124,0,0,23,125,0,0,116,4,0,124,0,0,106,5,0, + 124,2,0,140,0,0,100,4,0,116,0,0,106,6,0,131, + 1,1,1,100,5,0,83,41,7,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,250,1,35,250,7,105,109,112, + 111,114,116,32,122,2,35,32,114,54,0,0,0,78,41,2, + 114,99,0,0,0,114,100,0,0,0,41,7,114,7,0,0, + 0,114,67,0,0,0,218,7,118,101,114,98,111,115,101,114, + 9,0,0,0,218,5,112,114,105,110,116,114,47,0,0,0, + 218,6,115,116,100,101,114,114,41,3,114,75,0,0,0,114, + 98,0,0,0,218,4,97,114,103,115,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,218,16,95,118,101,114,98, + 111,115,101,95,109,101,115,115,97,103,101,105,1,0,0,115, + 8,0,0,0,0,2,18,1,15,1,10,1,114,105,0,0, + 0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0, + 0,0,3,0,0,0,115,84,0,0,0,100,1,0,135,0, + 0,102,1,0,100,2,0,100,3,0,134,1,0,125,1,0, + 121,13,0,116,0,0,106,1,0,125,2,0,87,110,30,0, + 4,116,2,0,107,10,0,114,66,0,1,1,1,100,4,0, + 100,5,0,132,0,0,125,2,0,89,110,1,0,88,124,2, + 0,124,1,0,136,0,0,131,2,0,1,124,1,0,83,41, + 6,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,5,0,0, + 0,31,0,0,0,115,89,0,0,0,124,1,0,100,0,0, + 107,8,0,114,24,0,124,0,0,106,0,0,125,1,0,110, + 46,0,124,0,0,106,0,0,124,1,0,107,3,0,114,70, + 0,116,1,0,100,1,0,124,0,0,106,0,0,124,1,0, + 102,2,0,22,100,2,0,124,1,0,131,1,1,130,1,0, + 136,0,0,124,0,0,124,1,0,124,2,0,124,3,0,142, + 2,0,83,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,218,4,110,97,109,101,41,2,114,106, + 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,106,0,0,0,114,104,0, + 0,0,90,6,107,119,97,114,103,115,41,1,218,6,109,101, + 116,104,111,100,114,4,0,0,0,114,5,0,0,0,218,19, + 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, + 112,101,114,121,1,0,0,115,12,0,0,0,0,1,12,1, + 12,1,15,1,6,1,25,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,92,0,0,0,120,66,0,100, + 1,0,100,2,0,100,3,0,100,4,0,103,4,0,68,93, + 46,0,125,2,0,116,0,0,124,1,0,124,2,0,131,2, + 0,114,19,0,116,1,0,124,0,0,124,2,0,116,2,0, + 124,1,0,124,2,0,131,2,0,131,3,0,1,113,19,0, + 87,124,0,0,106,3,0,106,4,0,124,1,0,106,3,0, + 131,1,0,1,100,0,0,83,41,5,78,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,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,114,52,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,5,95,119,114,97,112,132,1, + 0,0,115,8,0,0,0,0,1,25,1,15,1,29,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,3,218,10,95, + 98,111,111,116,115,116,114,97,112,114,120,0,0,0,218,9, + 78,97,109,101,69,114,114,111,114,41,3,114,109,0,0,0, + 114,110,0,0,0,114,120,0,0,0,114,4,0,0,0,41, + 1,114,109,0,0,0,114,5,0,0,0,218,11,95,99,104, + 101,99,107,95,110,97,109,101,113,1,0,0,115,14,0,0, + 0,0,8,21,7,3,1,13,1,13,2,17,5,13,1,114, + 123,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, + 0,4,0,0,0,67,0,0,0,115,84,0,0,0,124,0, + 0,106,0,0,124,1,0,131,1,0,92,2,0,125,2,0, + 125,3,0,124,2,0,100,1,0,107,8,0,114,80,0,116, + 1,0,124,3,0,131,1,0,114,80,0,100,2,0,125,4, + 0,116,2,0,106,3,0,124,4,0,106,4,0,124,3,0, + 100,3,0,25,131,1,0,116,5,0,131,2,0,1,124,2, + 0,83,41,4,122,155,84,114,121,32,116,111,32,102,105,110, + 100,32,97,32,108,111,97,100,101,114,32,102,111,114,32,116, + 104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100, + 117,108,101,32,98,121,32,100,101,108,101,103,97,116,105,110, + 103,32,116,111,10,32,32,32,32,115,101,108,102,46,102,105, + 110,100,95,108,111,97,100,101,114,40,41,46,10,10,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,32,105,110,32,102, + 97,118,111,114,32,111,102,32,102,105,110,100,101,114,46,102, + 105,110,100,95,115,112,101,99,40,41,46,10,10,32,32,32, + 32,78,122,44,78,111,116,32,105,109,112,111,114,116,105,110, + 103,32,100,105,114,101,99,116,111,114,121,32,123,125,58,32, + 109,105,115,115,105,110,103,32,95,95,105,110,105,116,95,95, + 114,59,0,0,0,41,6,218,11,102,105,110,100,95,108,111, + 97,100,101,114,114,31,0,0,0,114,60,0,0,0,114,61, + 0,0,0,114,47,0,0,0,218,13,73,109,112,111,114,116, + 87,97,114,110,105,110,103,41,5,114,108,0,0,0,218,8, + 102,117,108,108,110,97,109,101,218,6,108,111,97,100,101,114, + 218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17, - 115,111,117,114,99,101,95,102,114,111,109,95,99,97,99,104, - 101,29,1,0,0,115,44,0,0,0,0,9,18,1,12,1, - 18,1,18,1,12,1,9,1,15,1,15,1,12,1,9,1, - 15,1,12,1,22,1,15,1,9,1,12,1,22,1,12,1, - 9,1,12,1,19,1,114,85,0,0,0,99,1,0,0,0, - 0,0,0,0,5,0,0,0,12,0,0,0,67,0,0,0, - 115,164,0,0,0,116,0,0,124,0,0,131,1,0,100,1, - 0,107,2,0,114,22,0,100,2,0,83,124,0,0,106,1, - 0,100,3,0,131,1,0,92,3,0,125,1,0,125,2,0, - 125,3,0,124,1,0,12,115,81,0,124,3,0,106,2,0, - 131,0,0,100,7,0,100,8,0,133,2,0,25,100,6,0, - 107,3,0,114,85,0,124,0,0,83,121,16,0,116,3,0, - 124,0,0,131,1,0,125,4,0,87,110,40,0,4,116,4, - 0,116,5,0,102,2,0,107,10,0,114,143,0,1,1,1, - 124,0,0,100,2,0,100,9,0,133,2,0,25,125,4,0, - 89,110,1,0,88,116,6,0,124,4,0,131,1,0,114,160, - 0,124,4,0,83,124,0,0,83,41,10,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,59,0,0,0,78,114, - 58,0,0,0,114,80,0,0,0,114,29,0,0,0,90,2, - 112,121,233,253,255,255,255,233,255,255,255,255,114,87,0,0, - 0,41,7,114,31,0,0,0,114,32,0,0,0,218,5,108, - 111,119,101,114,114,85,0,0,0,114,66,0,0,0,114,71, - 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,78,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,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,218,15,95,103,101,116, - 95,115,111,117,114,99,101,102,105,108,101,62,1,0,0,115, - 20,0,0,0,0,7,18,1,4,1,24,1,35,1,4,1, - 3,1,16,1,19,1,21,1,114,91,0,0,0,99,1,0, - 0,0,0,0,0,0,1,0,0,0,11,0,0,0,67,0, - 0,0,115,92,0,0,0,124,0,0,106,0,0,116,1,0, - 116,2,0,131,1,0,131,1,0,114,59,0,121,14,0,116, - 3,0,124,0,0,131,1,0,83,87,113,88,0,4,116,4, - 0,107,10,0,114,55,0,1,1,1,89,113,88,0,88,110, - 29,0,124,0,0,106,0,0,116,1,0,116,5,0,131,1, - 0,131,1,0,114,84,0,124,0,0,83,100,0,0,83,100, - 0,0,83,41,1,78,41,6,218,8,101,110,100,115,119,105, - 116,104,218,5,116,117,112,108,101,114,84,0,0,0,114,79, - 0,0,0,114,66,0,0,0,114,74,0,0,0,41,1,218, - 8,102,105,108,101,110,97,109,101,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,11,95,103,101,116,95,99, - 97,99,104,101,100,81,1,0,0,115,16,0,0,0,0,1, - 21,1,3,1,14,1,13,1,8,1,21,1,4,2,114,95, - 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,60,0,0,0,121,19,0, - 116,0,0,124,0,0,131,1,0,106,1,0,125,1,0,87, - 110,24,0,4,116,2,0,107,10,0,114,45,0,1,1,1, - 100,1,0,125,1,0,89,110,1,0,88,124,1,0,100,2, - 0,79,125,1,0,124,1,0,83,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,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,10,95,99,97,108,99,95,109,111, - 100,101,93,1,0,0,115,12,0,0,0,0,2,3,1,19, - 1,13,1,11,3,10,1,114,97,0,0,0,218,9,118,101, - 114,98,111,115,105,116,121,114,29,0,0,0,99,1,0,0, - 0,1,0,0,0,3,0,0,0,4,0,0,0,71,0,0, - 0,115,75,0,0,0,116,0,0,106,1,0,106,2,0,124, - 1,0,107,5,0,114,71,0,124,0,0,106,3,0,100,6, - 0,131,1,0,115,43,0,100,3,0,124,0,0,23,125,0, - 0,116,4,0,124,0,0,106,5,0,124,2,0,140,0,0, - 100,4,0,116,0,0,106,6,0,131,1,1,1,100,5,0, - 83,41,7,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,250,1,35,250,7,105,109,112,111,114,116,32,122,2, - 35,32,114,54,0,0,0,78,41,2,114,99,0,0,0,114, - 100,0,0,0,41,7,114,7,0,0,0,114,67,0,0,0, - 218,7,118,101,114,98,111,115,101,114,9,0,0,0,218,5, - 112,114,105,110,116,114,47,0,0,0,218,6,115,116,100,101, - 114,114,41,3,114,75,0,0,0,114,98,0,0,0,218,4, - 97,114,103,115,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,218,16,95,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,105,1,0,0,115,8,0,0,0,0,2, - 18,1,15,1,10,1,114,105,0,0,0,99,1,0,0,0, - 0,0,0,0,3,0,0,0,11,0,0,0,3,0,0,0, - 115,84,0,0,0,100,1,0,135,0,0,102,1,0,100,2, - 0,100,3,0,134,1,0,125,1,0,121,13,0,116,0,0, - 106,1,0,125,2,0,87,110,30,0,4,116,2,0,107,10, - 0,114,66,0,1,1,1,100,4,0,100,5,0,132,0,0, - 125,2,0,89,110,1,0,88,124,2,0,124,1,0,136,0, - 0,131,2,0,1,124,1,0,83,41,6,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,5,0,0,0,31,0,0,0,115, - 80,0,0,0,124,1,0,100,0,0,107,8,0,114,24,0, - 124,0,0,106,0,0,125,1,0,110,37,0,124,0,0,106, - 0,0,124,1,0,107,3,0,114,61,0,116,1,0,100,1, - 0,124,1,0,22,100,2,0,124,1,0,131,1,1,130,1, - 0,136,0,0,124,0,0,124,1,0,124,2,0,124,3,0, - 142,2,0,83,41,3,78,122,23,108,111,97,100,101,114,32, - 99,97,110,110,111,116,32,104,97,110,100,108,101,32,37,115, - 218,4,110,97,109,101,41,2,114,106,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,106,0,0,0,114,104,0,0,0,90,6,107,119, - 97,114,103,115,41,1,218,6,109,101,116,104,111,100,114,4, - 0,0,0,114,5,0,0,0,218,19,95,99,104,101,99,107, - 95,110,97,109,101,95,119,114,97,112,112,101,114,121,1,0, - 0,115,10,0,0,0,0,1,12,1,12,1,15,1,22,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, - 92,0,0,0,120,66,0,100,1,0,100,2,0,100,3,0, - 100,4,0,103,4,0,68,93,46,0,125,2,0,116,0,0, - 124,1,0,124,2,0,131,2,0,114,19,0,116,1,0,124, - 0,0,124,2,0,116,2,0,124,1,0,124,2,0,131,2, - 0,131,3,0,1,113,19,0,87,124,0,0,106,3,0,106, - 4,0,124,1,0,106,3,0,131,1,0,1,100,0,0,83, - 41,5,78,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, - 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,114,52,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 5,95,119,114,97,112,131,1,0,0,115,8,0,0,0,0, - 1,25,1,15,1,29,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,3,218,10,95,98,111,111,116,115,116,114,97, - 112,114,120,0,0,0,218,9,78,97,109,101,69,114,114,111, - 114,41,3,114,109,0,0,0,114,110,0,0,0,114,120,0, - 0,0,114,4,0,0,0,41,1,114,109,0,0,0,114,5, - 0,0,0,218,11,95,99,104,101,99,107,95,110,97,109,101, - 113,1,0,0,115,14,0,0,0,0,8,21,6,3,1,13, - 1,13,2,17,5,13,1,114,123,0,0,0,99,2,0,0, - 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, - 0,115,84,0,0,0,124,0,0,106,0,0,124,1,0,131, - 1,0,92,2,0,125,2,0,125,3,0,124,2,0,100,1, - 0,107,8,0,114,80,0,116,1,0,124,3,0,131,1,0, - 114,80,0,100,2,0,125,4,0,116,2,0,106,3,0,124, - 4,0,106,4,0,124,3,0,100,3,0,25,131,1,0,116, - 5,0,131,2,0,1,124,2,0,83,41,4,122,155,84,114, - 121,32,116,111,32,102,105,110,100,32,97,32,108,111,97,100, - 101,114,32,102,111,114,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,32,109,111,100,117,108,101,32,98,121,32,100, - 101,108,101,103,97,116,105,110,103,32,116,111,10,32,32,32, - 32,115,101,108,102,46,102,105,110,100,95,108,111,97,100,101, - 114,40,41,46,10,10,32,32,32,32,84,104,105,115,32,109, - 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,32,105,110,32,102,97,118,111,114,32,111,102,32, - 102,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, - 40,41,46,10,10,32,32,32,32,78,122,44,78,111,116,32, - 105,109,112,111,114,116,105,110,103,32,100,105,114,101,99,116, - 111,114,121,32,123,125,58,32,109,105,115,115,105,110,103,32, - 95,95,105,110,105,116,95,95,114,59,0,0,0,41,6,218, - 11,102,105,110,100,95,108,111,97,100,101,114,114,31,0,0, - 0,114,60,0,0,0,114,61,0,0,0,114,47,0,0,0, - 218,13,73,109,112,111,114,116,87,97,114,110,105,110,103,41, - 5,114,108,0,0,0,218,8,102,117,108,108,110,97,109,101, - 218,6,108,111,97,100,101,114,218,8,112,111,114,116,105,111, - 110,115,218,3,109,115,103,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,17,95,102,105,110,100,95,109,111, - 100,117,108,101,95,115,104,105,109,140,1,0,0,115,10,0, - 0,0,0,10,21,1,24,1,6,1,29,1,114,130,0,0, - 0,99,4,0,0,0,0,0,0,0,11,0,0,0,19,0, - 0,0,67,0,0,0,115,228,1,0,0,105,0,0,125,4, - 0,124,2,0,100,1,0,107,9,0,114,31,0,124,2,0, - 124,4,0,100,2,0,60,110,6,0,100,3,0,125,2,0, - 124,3,0,100,1,0,107,9,0,114,59,0,124,3,0,124, - 4,0,100,4,0,60,124,0,0,100,1,0,100,5,0,133, - 2,0,25,125,5,0,124,0,0,100,5,0,100,6,0,133, - 2,0,25,125,6,0,124,0,0,100,6,0,100,7,0,133, - 2,0,25,125,7,0,124,5,0,116,0,0,107,3,0,114, - 165,0,100,8,0,106,1,0,124,2,0,124,5,0,131,2, - 0,125,8,0,116,2,0,124,8,0,131,1,0,1,116,3, - 0,124,8,0,124,4,0,141,1,0,130,1,0,110,113,0, - 116,4,0,124,6,0,131,1,0,100,5,0,107,3,0,114, - 223,0,100,9,0,106,1,0,124,2,0,131,1,0,125,8, - 0,116,2,0,124,8,0,131,1,0,1,116,5,0,124,8, - 0,131,1,0,130,1,0,110,55,0,116,4,0,124,7,0, - 131,1,0,100,5,0,107,3,0,114,22,1,100,10,0,106, - 1,0,124,2,0,131,1,0,125,8,0,116,2,0,124,8, - 0,131,1,0,1,116,5,0,124,8,0,131,1,0,130,1, - 0,124,1,0,100,1,0,107,9,0,114,214,1,121,20,0, - 116,6,0,124,1,0,100,11,0,25,131,1,0,125,9,0, - 87,110,18,0,4,116,7,0,107,10,0,114,74,1,1,1, - 1,89,110,59,0,88,116,8,0,124,6,0,131,1,0,124, - 9,0,107,3,0,114,133,1,100,12,0,106,1,0,124,2, - 0,131,1,0,125,8,0,116,2,0,124,8,0,131,1,0, - 1,116,3,0,124,8,0,124,4,0,141,1,0,130,1,0, - 121,18,0,124,1,0,100,13,0,25,100,14,0,64,125,10, - 0,87,110,18,0,4,116,7,0,107,10,0,114,171,1,1, - 1,1,89,110,43,0,88,116,8,0,124,7,0,131,1,0, - 124,10,0,107,3,0,114,214,1,116,3,0,100,12,0,106, - 1,0,124,2,0,131,1,0,124,4,0,141,1,0,130,1, - 0,124,0,0,100,7,0,100,1,0,133,2,0,25,83,41, - 15,97,122,1,0,0,86,97,108,105,100,97,116,101,32,116, - 104,101,32,104,101,97,100,101,114,32,111,102,32,116,104,101, - 32,112,97,115,115,101,100,45,105,110,32,98,121,116,101,99, - 111,100,101,32,97,103,97,105,110,115,116,32,115,111,117,114, - 99,101,95,115,116,97,116,115,32,40,105,102,10,32,32,32, - 32,103,105,118,101,110,41,32,97,110,100,32,114,101,116,117, - 114,110,105,110,103,32,116,104,101,32,98,121,116,101,99,111, - 100,101,32,116,104,97,116,32,99,97,110,32,98,101,32,99, - 111,109,112,105,108,101,100,32,98,121,32,99,111,109,112,105, - 108,101,40,41,46,10,10,32,32,32,32,65,108,108,32,111, - 116,104,101,114,32,97,114,103,117,109,101,110,116,115,32,97, - 114,101,32,117,115,101,100,32,116,111,32,101,110,104,97,110, - 99,101,32,101,114,114,111,114,32,114,101,112,111,114,116,105, - 110,103,46,10,10,32,32,32,32,73,109,112,111,114,116,69, - 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,119, - 104,101,110,32,116,104,101,32,109,97,103,105,99,32,110,117, - 109,98,101,114,32,105,115,32,105,110,99,111,114,114,101,99, - 116,32,111,114,32,116,104,101,32,98,121,116,101,99,111,100, - 101,32,105,115,10,32,32,32,32,102,111,117,110,100,32,116, - 111,32,98,101,32,115,116,97,108,101,46,32,69,79,70,69, - 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,119, - 104,101,110,32,116,104,101,32,100,97,116,97,32,105,115,32, - 102,111,117,110,100,32,116,111,32,98,101,10,32,32,32,32, - 116,114,117,110,99,97,116,101,100,46,10,10,32,32,32,32, - 78,114,106,0,0,0,122,10,60,98,121,116,101,99,111,100, - 101,62,114,35,0,0,0,114,12,0,0,0,233,8,0,0, - 0,233,12,0,0,0,122,30,98,97,100,32,109,97,103,105, - 99,32,110,117,109,98,101,114,32,105,110,32,123,33,114,125, - 58,32,123,33,114,125,122,43,114,101,97,99,104,101,100,32, - 69,79,70,32,119,104,105,108,101,32,114,101,97,100,105,110, - 103,32,116,105,109,101,115,116,97,109,112,32,105,110,32,123, - 33,114,125,122,48,114,101,97,99,104,101,100,32,69,79,70, - 32,119,104,105,108,101,32,114,101,97,100,105,110,103,32,115, - 105,122,101,32,111,102,32,115,111,117,114,99,101,32,105,110, - 32,123,33,114,125,218,5,109,116,105,109,101,122,26,98,121, - 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,32, - 102,111,114,32,123,33,114,125,218,4,115,105,122,101,108,3, - 0,0,0,255,127,255,127,3,0,41,9,218,12,77,65,71, - 73,67,95,78,85,77,66,69,82,114,47,0,0,0,114,105, - 0,0,0,114,107,0,0,0,114,31,0,0,0,218,8,69, - 79,70,69,114,114,111,114,114,14,0,0,0,218,8,75,101, - 121,69,114,114,111,114,114,19,0,0,0,41,11,114,53,0, - 0,0,218,12,115,111,117,114,99,101,95,115,116,97,116,115, - 114,106,0,0,0,114,35,0,0,0,90,11,101,120,99,95, - 100,101,116,97,105,108,115,90,5,109,97,103,105,99,90,13, - 114,97,119,95,116,105,109,101,115,116,97,109,112,90,8,114, - 97,119,95,115,105,122,101,114,75,0,0,0,218,12,115,111, - 117,114,99,101,95,109,116,105,109,101,218,11,115,111,117,114, - 99,101,95,115,105,122,101,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,25,95,118,97,108,105,100,97,116, - 101,95,98,121,116,101,99,111,100,101,95,104,101,97,100,101, - 114,157,1,0,0,115,76,0,0,0,0,11,6,1,12,1, - 13,3,6,1,12,1,10,1,16,1,16,1,16,1,12,1, - 18,1,10,1,18,1,18,1,15,1,10,1,15,1,18,1, - 15,1,10,1,12,1,12,1,3,1,20,1,13,1,5,2, - 18,1,15,1,10,1,15,1,3,1,18,1,13,1,5,2, - 18,1,15,1,9,1,114,141,0,0,0,99,4,0,0,0, - 0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,0, - 115,112,0,0,0,116,0,0,106,1,0,124,0,0,131,1, - 0,125,4,0,116,2,0,124,4,0,116,3,0,131,2,0, - 114,75,0,116,4,0,100,1,0,124,2,0,131,2,0,1, - 124,3,0,100,2,0,107,9,0,114,71,0,116,5,0,106, - 6,0,124,4,0,124,3,0,131,2,0,1,124,4,0,83, - 116,7,0,100,3,0,106,8,0,124,2,0,131,1,0,100, - 4,0,124,1,0,100,5,0,124,2,0,131,1,2,130,1, - 0,100,2,0,83,41,6,122,60,67,111,109,112,105,108,101, - 32,98,121,116,101,99,111,100,101,32,97,115,32,114,101,116, - 117,114,110,101,100,32,98,121,32,95,118,97,108,105,100,97, - 116,101,95,98,121,116,101,99,111,100,101,95,104,101,97,100, - 101,114,40,41,46,122,21,99,111,100,101,32,111,98,106,101, - 99,116,32,102,114,111,109,32,123,33,114,125,78,122,23,78, - 111,110,45,99,111,100,101,32,111,98,106,101,99,116,32,105, - 110,32,123,33,114,125,114,106,0,0,0,114,35,0,0,0, - 41,9,218,7,109,97,114,115,104,97,108,90,5,108,111,97, - 100,115,218,10,105,115,105,110,115,116,97,110,99,101,218,10, - 95,99,111,100,101,95,116,121,112,101,114,105,0,0,0,218, - 4,95,105,109,112,90,16,95,102,105,120,95,99,111,95,102, - 105,108,101,110,97,109,101,114,107,0,0,0,114,47,0,0, - 0,41,5,114,53,0,0,0,114,106,0,0,0,114,89,0, - 0,0,114,90,0,0,0,218,4,99,111,100,101,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,17,95,99, - 111,109,112,105,108,101,95,98,121,116,101,99,111,100,101,212, - 1,0,0,115,16,0,0,0,0,2,15,1,15,1,13,1, - 12,1,16,1,4,2,18,1,114,147,0,0,0,114,59,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,76,0,0,0,116,0,0,116, - 1,0,131,1,0,125,3,0,124,3,0,106,2,0,116,3, - 0,124,1,0,131,1,0,131,1,0,1,124,3,0,106,2, - 0,116,3,0,124,2,0,131,1,0,131,1,0,1,124,3, - 0,106,2,0,116,4,0,106,5,0,124,0,0,131,1,0, - 131,1,0,1,124,3,0,83,41,1,122,80,67,111,109,112, - 105,108,101,32,97,32,99,111,100,101,32,111,98,106,101,99, - 116,32,105,110,116,111,32,98,121,116,101,99,111,100,101,32, - 102,111,114,32,119,114,105,116,105,110,103,32,111,117,116,32, - 116,111,32,97,32,98,121,116,101,45,99,111,109,112,105,108, - 101,100,10,32,32,32,32,102,105,108,101,46,41,6,218,9, - 98,121,116,101,97,114,114,97,121,114,135,0,0,0,218,6, - 101,120,116,101,110,100,114,17,0,0,0,114,142,0,0,0, - 90,5,100,117,109,112,115,41,4,114,146,0,0,0,114,133, - 0,0,0,114,140,0,0,0,114,53,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,17,95,99, - 111,100,101,95,116,111,95,98,121,116,101,99,111,100,101,224, - 1,0,0,115,10,0,0,0,0,3,12,1,19,1,19,1, - 22,1,114,150,0,0,0,99,1,0,0,0,0,0,0,0, - 5,0,0,0,4,0,0,0,67,0,0,0,115,89,0,0, - 0,100,1,0,100,2,0,108,0,0,125,1,0,116,1,0, - 106,2,0,124,0,0,131,1,0,106,3,0,125,2,0,124, - 1,0,106,4,0,124,2,0,131,1,0,125,3,0,116,1, - 0,106,5,0,100,2,0,100,3,0,131,2,0,125,4,0, - 124,4,0,106,6,0,124,0,0,106,6,0,124,3,0,100, - 1,0,25,131,1,0,131,1,0,83,41,4,122,121,68,101, - 99,111,100,101,32,98,121,116,101,115,32,114,101,112,114,101, - 115,101,110,116,105,110,103,32,115,111,117,114,99,101,32,99, - 111,100,101,32,97,110,100,32,114,101,116,117,114,110,32,116, - 104,101,32,115,116,114,105,110,103,46,10,10,32,32,32,32, - 85,110,105,118,101,114,115,97,108,32,110,101,119,108,105,110, - 101,32,115,117,112,112,111,114,116,32,105,115,32,117,115,101, - 100,32,105,110,32,116,104,101,32,100,101,99,111,100,105,110, - 103,46,10,32,32,32,32,114,59,0,0,0,78,84,41,7, - 218,8,116,111,107,101,110,105,122,101,114,49,0,0,0,90, - 7,66,121,116,101,115,73,79,90,8,114,101,97,100,108,105, - 110,101,90,15,100,101,116,101,99,116,95,101,110,99,111,100, - 105,110,103,90,25,73,110,99,114,101,109,101,110,116,97,108, - 78,101,119,108,105,110,101,68,101,99,111,100,101,114,218,6, - 100,101,99,111,100,101,41,5,218,12,115,111,117,114,99,101, - 95,98,121,116,101,115,114,151,0,0,0,90,21,115,111,117, - 114,99,101,95,98,121,116,101,115,95,114,101,97,100,108,105, - 110,101,218,8,101,110,99,111,100,105,110,103,90,15,110,101, - 119,108,105,110,101,95,100,101,99,111,100,101,114,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,13,100,101, - 99,111,100,101,95,115,111,117,114,99,101,234,1,0,0,115, - 10,0,0,0,0,5,12,1,18,1,15,1,18,1,114,155, - 0,0,0,114,127,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,19,0,0,0,67,0,0,0,115,89,1,0,0,124,1, - 0,100,1,0,107,8,0,114,73,0,100,2,0,125,1,0, - 116,0,0,124,2,0,100,3,0,131,2,0,114,73,0,121, - 19,0,124,2,0,106,1,0,124,0,0,131,1,0,125,1, - 0,87,110,18,0,4,116,2,0,107,10,0,114,72,0,1, - 1,1,89,110,1,0,88,116,3,0,106,4,0,124,0,0, - 124,2,0,100,4,0,124,1,0,131,2,1,125,4,0,100, - 5,0,124,4,0,95,5,0,124,2,0,100,1,0,107,8, - 0,114,194,0,120,73,0,116,6,0,131,0,0,68,93,58, - 0,92,2,0,125,5,0,125,6,0,124,1,0,106,7,0, - 116,8,0,124,6,0,131,1,0,131,1,0,114,128,0,124, - 5,0,124,0,0,124,1,0,131,2,0,125,2,0,124,2, - 0,124,4,0,95,9,0,80,113,128,0,87,100,1,0,83, - 124,3,0,116,10,0,107,8,0,114,23,1,116,0,0,124, - 2,0,100,6,0,131,2,0,114,32,1,121,19,0,124,2, - 0,106,11,0,124,0,0,131,1,0,125,7,0,87,110,18, - 0,4,116,2,0,107,10,0,114,4,1,1,1,1,89,113, - 32,1,88,124,7,0,114,32,1,103,0,0,124,4,0,95, - 12,0,110,9,0,124,3,0,124,4,0,95,12,0,124,4, - 0,106,12,0,103,0,0,107,2,0,114,85,1,124,1,0, - 114,85,1,116,13,0,124,1,0,131,1,0,100,7,0,25, - 125,8,0,124,4,0,106,12,0,106,14,0,124,8,0,131, - 1,0,1,124,4,0,83,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,218,6,111,114,105,103,105,110,84,218,10, - 105,115,95,112,97,99,107,97,103,101,114,59,0,0,0,41, - 15,114,115,0,0,0,114,157,0,0,0,114,107,0,0,0, - 114,121,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,92,0, - 0,0,114,93,0,0,0,114,127,0,0,0,218,9,95,80, - 79,80,85,76,65,84,69,114,159,0,0,0,114,156,0,0, - 0,114,38,0,0,0,218,6,97,112,112,101,110,100,41,9, - 114,106,0,0,0,90,8,108,111,99,97,116,105,111,110,114, - 127,0,0,0,114,156,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,159,0,0,0,90,7,100,105, - 114,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114, - 5,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,251,1,0, - 0,115,60,0,0,0,0,12,12,4,6,1,15,2,3,1, - 19,1,13,1,5,8,24,1,9,3,12,1,22,1,21,1, - 15,1,9,1,5,2,4,3,12,2,15,1,3,1,19,1, - 13,1,5,2,6,1,12,2,9,1,15,1,6,1,16,1, - 16,2,114,167,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,5,0,0,0,64,0,0,0,115,121,0,0, - 0,101,0,0,90,1,0,100,0,0,90,2,0,100,1,0, - 90,3,0,100,2,0,90,4,0,100,3,0,90,5,0,100, - 4,0,90,6,0,101,7,0,100,5,0,100,6,0,132,0, - 0,131,1,0,90,8,0,101,7,0,100,7,0,100,8,0, - 132,0,0,131,1,0,90,9,0,101,7,0,100,9,0,100, - 9,0,100,10,0,100,11,0,132,2,0,131,1,0,90,10, - 0,101,7,0,100,9,0,100,12,0,100,13,0,132,1,0, - 131,1,0,90,11,0,100,9,0,83,41,14,218,21,87,105, - 110,100,111,119,115,82,101,103,105,115,116,114,121,70,105,110, - 100,101,114,122,62,77,101,116,97,32,112,97,116,104,32,102, - 105,110,100,101,114,32,102,111,114,32,109,111,100,117,108,101, - 115,32,100,101,99,108,97,114,101,100,32,105,110,32,116,104, - 101,32,87,105,110,100,111,119,115,32,114,101,103,105,115,116, - 114,121,46,122,59,83,111,102,116,119,97,114,101,92,80,121, - 116,104,111,110,92,80,121,116,104,111,110,67,111,114,101,92, - 123,115,121,115,95,118,101,114,115,105,111,110,125,92,77,111, - 100,117,108,101,115,92,123,102,117,108,108,110,97,109,101,125, - 122,65,83,111,102,116,119,97,114,101,92,80,121,116,104,111, - 110,92,80,121,116,104,111,110,67,111,114,101,92,123,115,121, - 115,95,118,101,114,115,105,111,110,125,92,77,111,100,117,108, - 101,115,92,123,102,117,108,108,110,97,109,101,125,92,68,101, - 98,117,103,70,99,2,0,0,0,0,0,0,0,2,0,0, - 0,11,0,0,0,67,0,0,0,115,67,0,0,0,121,23, - 0,116,0,0,106,1,0,116,0,0,106,2,0,124,1,0, - 131,2,0,83,87,110,37,0,4,116,3,0,107,10,0,114, - 62,0,1,1,1,116,0,0,106,1,0,116,0,0,106,4, - 0,124,1,0,131,2,0,83,89,110,1,0,88,100,0,0, - 83,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,218,3,107,101,121, - 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 14,95,111,112,101,110,95,114,101,103,105,115,116,114,121,73, - 2,0,0,115,8,0,0,0,0,2,3,1,23,1,13,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,16,0,0,0,67,0,0,0,115,143,0,0,0, - 124,0,0,106,0,0,114,21,0,124,0,0,106,1,0,125, - 2,0,110,9,0,124,0,0,106,2,0,125,2,0,124,2, - 0,106,3,0,100,1,0,124,1,0,100,2,0,116,4,0, - 106,5,0,100,0,0,100,3,0,133,2,0,25,131,0,2, - 125,3,0,121,47,0,124,0,0,106,6,0,124,3,0,131, - 1,0,143,25,0,125,4,0,116,7,0,106,8,0,124,4, - 0,100,4,0,131,2,0,125,5,0,87,100,0,0,81,82, - 88,87,110,22,0,4,116,9,0,107,10,0,114,138,0,1, - 1,1,100,0,0,83,89,110,1,0,88,124,5,0,83,41, - 5,78,114,126,0,0,0,90,11,115,121,115,95,118,101,114, - 115,105,111,110,114,80,0,0,0,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, - 47,0,0,0,114,7,0,0,0,218,7,118,101,114,115,105, - 111,110,114,172,0,0,0,114,169,0,0,0,90,10,81,117, - 101,114,121,86,97,108,117,101,114,40,0,0,0,41,6,114, - 170,0,0,0,114,126,0,0,0,90,12,114,101,103,105,115, - 116,114,121,95,107,101,121,114,171,0,0,0,90,4,104,107, - 101,121,218,8,102,105,108,101,112,97,116,104,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,218,16,95,115,101, - 97,114,99,104,95,114,101,103,105,115,116,114,121,80,2,0, - 0,115,22,0,0,0,0,2,9,1,12,2,9,1,15,1, - 22,1,3,1,18,1,29,1,13,1,9,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,14,0,0,0,67,0,0,0,115,158,0,0,0,124, - 0,0,106,0,0,124,1,0,131,1,0,125,4,0,124,4, - 0,100,0,0,107,8,0,114,31,0,100,0,0,83,121,14, - 0,116,1,0,124,4,0,131,1,0,1,87,110,22,0,4, - 116,2,0,107,10,0,114,69,0,1,1,1,100,0,0,83, - 89,110,1,0,88,120,81,0,116,3,0,131,0,0,68,93, - 70,0,92,2,0,125,5,0,125,6,0,124,4,0,106,4, - 0,116,5,0,124,6,0,131,1,0,131,1,0,114,80,0, - 116,6,0,106,7,0,124,1,0,124,5,0,124,1,0,124, - 4,0,131,2,0,100,1,0,124,4,0,131,2,1,125,7, - 0,124,7,0,83,113,80,0,87,100,0,0,83,41,2,78, - 114,158,0,0,0,41,8,114,178,0,0,0,114,39,0,0, - 0,114,40,0,0,0,114,161,0,0,0,114,92,0,0,0, - 114,93,0,0,0,114,121,0,0,0,218,16,115,112,101,99, - 95,102,114,111,109,95,108,111,97,100,101,114,41,8,114,170, - 0,0,0,114,126,0,0,0,114,35,0,0,0,218,6,116, - 97,114,103,101,116,114,177,0,0,0,114,127,0,0,0,114, - 166,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,218,9,102,105,110,100,95,115, - 112,101,99,95,2,0,0,115,26,0,0,0,0,2,15,1, - 12,1,4,1,3,1,14,1,13,1,9,1,22,1,21,1, - 9,1,15,1,9,1,122,31,87,105,110,100,111,119,115,82, + 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, + 109,141,1,0,0,115,10,0,0,0,0,10,21,1,24,1, + 6,1,29,1,114,130,0,0,0,99,4,0,0,0,0,0, + 0,0,11,0,0,0,19,0,0,0,67,0,0,0,115,228, + 1,0,0,105,0,0,125,4,0,124,2,0,100,1,0,107, + 9,0,114,31,0,124,2,0,124,4,0,100,2,0,60,110, + 6,0,100,3,0,125,2,0,124,3,0,100,1,0,107,9, + 0,114,59,0,124,3,0,124,4,0,100,4,0,60,124,0, + 0,100,1,0,100,5,0,133,2,0,25,125,5,0,124,0, + 0,100,5,0,100,6,0,133,2,0,25,125,6,0,124,0, + 0,100,6,0,100,7,0,133,2,0,25,125,7,0,124,5, + 0,116,0,0,107,3,0,114,165,0,100,8,0,106,1,0, + 124,2,0,124,5,0,131,2,0,125,8,0,116,2,0,124, + 8,0,131,1,0,1,116,3,0,124,8,0,124,4,0,141, + 1,0,130,1,0,110,113,0,116,4,0,124,6,0,131,1, + 0,100,5,0,107,3,0,114,223,0,100,9,0,106,1,0, + 124,2,0,131,1,0,125,8,0,116,2,0,124,8,0,131, + 1,0,1,116,5,0,124,8,0,131,1,0,130,1,0,110, + 55,0,116,4,0,124,7,0,131,1,0,100,5,0,107,3, + 0,114,22,1,100,10,0,106,1,0,124,2,0,131,1,0, + 125,8,0,116,2,0,124,8,0,131,1,0,1,116,5,0, + 124,8,0,131,1,0,130,1,0,124,1,0,100,1,0,107, + 9,0,114,214,1,121,20,0,116,6,0,124,1,0,100,11, + 0,25,131,1,0,125,9,0,87,110,18,0,4,116,7,0, + 107,10,0,114,74,1,1,1,1,89,110,59,0,88,116,8, + 0,124,6,0,131,1,0,124,9,0,107,3,0,114,133,1, + 100,12,0,106,1,0,124,2,0,131,1,0,125,8,0,116, + 2,0,124,8,0,131,1,0,1,116,3,0,124,8,0,124, + 4,0,141,1,0,130,1,0,121,18,0,124,1,0,100,13, + 0,25,100,14,0,64,125,10,0,87,110,18,0,4,116,7, + 0,107,10,0,114,171,1,1,1,1,89,110,43,0,88,116, + 8,0,124,7,0,131,1,0,124,10,0,107,3,0,114,214, + 1,116,3,0,100,12,0,106,1,0,124,2,0,131,1,0, + 124,4,0,141,1,0,130,1,0,124,0,0,100,7,0,100, + 1,0,133,2,0,25,83,41,15,97,122,1,0,0,86,97, + 108,105,100,97,116,101,32,116,104,101,32,104,101,97,100,101, + 114,32,111,102,32,116,104,101,32,112,97,115,115,101,100,45, + 105,110,32,98,121,116,101,99,111,100,101,32,97,103,97,105, + 110,115,116,32,115,111,117,114,99,101,95,115,116,97,116,115, + 32,40,105,102,10,32,32,32,32,103,105,118,101,110,41,32, + 97,110,100,32,114,101,116,117,114,110,105,110,103,32,116,104, + 101,32,98,121,116,101,99,111,100,101,32,116,104,97,116,32, + 99,97,110,32,98,101,32,99,111,109,112,105,108,101,100,32, + 98,121,32,99,111,109,112,105,108,101,40,41,46,10,10,32, + 32,32,32,65,108,108,32,111,116,104,101,114,32,97,114,103, + 117,109,101,110,116,115,32,97,114,101,32,117,115,101,100,32, + 116,111,32,101,110,104,97,110,99,101,32,101,114,114,111,114, + 32,114,101,112,111,114,116,105,110,103,46,10,10,32,32,32, + 32,73,109,112,111,114,116,69,114,114,111,114,32,105,115,32, + 114,97,105,115,101,100,32,119,104,101,110,32,116,104,101,32, + 109,97,103,105,99,32,110,117,109,98,101,114,32,105,115,32, + 105,110,99,111,114,114,101,99,116,32,111,114,32,116,104,101, + 32,98,121,116,101,99,111,100,101,32,105,115,10,32,32,32, + 32,102,111,117,110,100,32,116,111,32,98,101,32,115,116,97, + 108,101,46,32,69,79,70,69,114,114,111,114,32,105,115,32, + 114,97,105,115,101,100,32,119,104,101,110,32,116,104,101,32, + 100,97,116,97,32,105,115,32,102,111,117,110,100,32,116,111, + 32,98,101,10,32,32,32,32,116,114,117,110,99,97,116,101, + 100,46,10,10,32,32,32,32,78,114,106,0,0,0,122,10, + 60,98,121,116,101,99,111,100,101,62,114,35,0,0,0,114, + 12,0,0,0,233,8,0,0,0,233,12,0,0,0,122,30, + 98,97,100,32,109,97,103,105,99,32,110,117,109,98,101,114, + 32,105,110,32,123,33,114,125,58,32,123,33,114,125,122,43, + 114,101,97,99,104,101,100,32,69,79,70,32,119,104,105,108, + 101,32,114,101,97,100,105,110,103,32,116,105,109,101,115,116, + 97,109,112,32,105,110,32,123,33,114,125,122,48,114,101,97, + 99,104,101,100,32,69,79,70,32,119,104,105,108,101,32,114, + 101,97,100,105,110,103,32,115,105,122,101,32,111,102,32,115, + 111,117,114,99,101,32,105,110,32,123,33,114,125,218,5,109, + 116,105,109,101,122,26,98,121,116,101,99,111,100,101,32,105, + 115,32,115,116,97,108,101,32,102,111,114,32,123,33,114,125, + 218,4,115,105,122,101,108,3,0,0,0,255,127,255,127,3, + 0,41,9,218,12,77,65,71,73,67,95,78,85,77,66,69, + 82,114,47,0,0,0,114,105,0,0,0,114,107,0,0,0, + 114,31,0,0,0,218,8,69,79,70,69,114,114,111,114,114, + 14,0,0,0,218,8,75,101,121,69,114,114,111,114,114,19, + 0,0,0,41,11,114,53,0,0,0,218,12,115,111,117,114, + 99,101,95,115,116,97,116,115,114,106,0,0,0,114,35,0, + 0,0,90,11,101,120,99,95,100,101,116,97,105,108,115,90, + 5,109,97,103,105,99,90,13,114,97,119,95,116,105,109,101, + 115,116,97,109,112,90,8,114,97,119,95,115,105,122,101,114, + 75,0,0,0,218,12,115,111,117,114,99,101,95,109,116,105, + 109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,25, + 95,118,97,108,105,100,97,116,101,95,98,121,116,101,99,111, + 100,101,95,104,101,97,100,101,114,158,1,0,0,115,76,0, + 0,0,0,11,6,1,12,1,13,3,6,1,12,1,10,1, + 16,1,16,1,16,1,12,1,18,1,10,1,18,1,18,1, + 15,1,10,1,15,1,18,1,15,1,10,1,12,1,12,1, + 3,1,20,1,13,1,5,2,18,1,15,1,10,1,15,1, + 3,1,18,1,13,1,5,2,18,1,15,1,9,1,114,141, + 0,0,0,99,4,0,0,0,0,0,0,0,5,0,0,0, + 6,0,0,0,67,0,0,0,115,112,0,0,0,116,0,0, + 106,1,0,124,0,0,131,1,0,125,4,0,116,2,0,124, + 4,0,116,3,0,131,2,0,114,75,0,116,4,0,100,1, + 0,124,2,0,131,2,0,1,124,3,0,100,2,0,107,9, + 0,114,71,0,116,5,0,106,6,0,124,4,0,124,3,0, + 131,2,0,1,124,4,0,83,116,7,0,100,3,0,106,8, + 0,124,2,0,131,1,0,100,4,0,124,1,0,100,5,0, + 124,2,0,131,1,2,130,1,0,100,2,0,83,41,6,122, + 60,67,111,109,112,105,108,101,32,98,121,116,101,99,111,100, + 101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121, + 32,95,118,97,108,105,100,97,116,101,95,98,121,116,101,99, + 111,100,101,95,104,101,97,100,101,114,40,41,46,122,21,99, + 111,100,101,32,111,98,106,101,99,116,32,102,114,111,109,32, + 123,33,114,125,78,122,23,78,111,110,45,99,111,100,101,32, + 111,98,106,101,99,116,32,105,110,32,123,33,114,125,114,106, + 0,0,0,114,35,0,0,0,41,9,218,7,109,97,114,115, + 104,97,108,90,5,108,111,97,100,115,218,10,105,115,105,110, + 115,116,97,110,99,101,218,10,95,99,111,100,101,95,116,121, + 112,101,114,105,0,0,0,218,4,95,105,109,112,90,16,95, + 102,105,120,95,99,111,95,102,105,108,101,110,97,109,101,114, + 107,0,0,0,114,47,0,0,0,41,5,114,53,0,0,0, + 114,106,0,0,0,114,89,0,0,0,114,90,0,0,0,218, + 4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,17,95,99,111,109,112,105,108,101,95,98, + 121,116,101,99,111,100,101,213,1,0,0,115,16,0,0,0, + 0,2,15,1,15,1,13,1,12,1,16,1,4,2,18,1, + 114,147,0,0,0,114,59,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, + 76,0,0,0,116,0,0,116,1,0,131,1,0,125,3,0, + 124,3,0,106,2,0,116,3,0,124,1,0,131,1,0,131, + 1,0,1,124,3,0,106,2,0,116,3,0,124,2,0,131, + 1,0,131,1,0,1,124,3,0,106,2,0,116,4,0,106, + 5,0,124,0,0,131,1,0,131,1,0,1,124,3,0,83, + 41,1,122,80,67,111,109,112,105,108,101,32,97,32,99,111, + 100,101,32,111,98,106,101,99,116,32,105,110,116,111,32,98, + 121,116,101,99,111,100,101,32,102,111,114,32,119,114,105,116, + 105,110,103,32,111,117,116,32,116,111,32,97,32,98,121,116, + 101,45,99,111,109,112,105,108,101,100,10,32,32,32,32,102, + 105,108,101,46,41,6,218,9,98,121,116,101,97,114,114,97, + 121,114,135,0,0,0,218,6,101,120,116,101,110,100,114,17, + 0,0,0,114,142,0,0,0,90,5,100,117,109,112,115,41, + 4,114,146,0,0,0,114,133,0,0,0,114,140,0,0,0, + 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,17,95,99,111,100,101,95,116,111,95,98, + 121,116,101,99,111,100,101,225,1,0,0,115,10,0,0,0, + 0,3,12,1,19,1,19,1,22,1,114,150,0,0,0,99, + 1,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, + 67,0,0,0,115,89,0,0,0,100,1,0,100,2,0,108, + 0,0,125,1,0,116,1,0,106,2,0,124,0,0,131,1, + 0,106,3,0,125,2,0,124,1,0,106,4,0,124,2,0, + 131,1,0,125,3,0,116,1,0,106,5,0,100,2,0,100, + 3,0,131,2,0,125,4,0,124,4,0,106,6,0,124,0, + 0,106,6,0,124,3,0,100,1,0,25,131,1,0,131,1, + 0,83,41,4,122,121,68,101,99,111,100,101,32,98,121,116, + 101,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32, + 115,111,117,114,99,101,32,99,111,100,101,32,97,110,100,32, + 114,101,116,117,114,110,32,116,104,101,32,115,116,114,105,110, + 103,46,10,10,32,32,32,32,85,110,105,118,101,114,115,97, + 108,32,110,101,119,108,105,110,101,32,115,117,112,112,111,114, + 116,32,105,115,32,117,115,101,100,32,105,110,32,116,104,101, + 32,100,101,99,111,100,105,110,103,46,10,32,32,32,32,114, + 59,0,0,0,78,84,41,7,218,8,116,111,107,101,110,105, + 122,101,114,49,0,0,0,90,7,66,121,116,101,115,73,79, + 90,8,114,101,97,100,108,105,110,101,90,15,100,101,116,101, + 99,116,95,101,110,99,111,100,105,110,103,90,25,73,110,99, + 114,101,109,101,110,116,97,108,78,101,119,108,105,110,101,68, + 101,99,111,100,101,114,218,6,100,101,99,111,100,101,41,5, + 218,12,115,111,117,114,99,101,95,98,121,116,101,115,114,151, + 0,0,0,90,21,115,111,117,114,99,101,95,98,121,116,101, + 115,95,114,101,97,100,108,105,110,101,218,8,101,110,99,111, + 100,105,110,103,90,15,110,101,119,108,105,110,101,95,100,101, + 99,111,100,101,114,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,13,100,101,99,111,100,101,95,115,111,117, + 114,99,101,235,1,0,0,115,10,0,0,0,0,5,12,1, + 18,1,15,1,18,1,114,155,0,0,0,114,127,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,19,0,0,0,67,0,0, + 0,115,89,1,0,0,124,1,0,100,1,0,107,8,0,114, + 73,0,100,2,0,125,1,0,116,0,0,124,2,0,100,3, + 0,131,2,0,114,73,0,121,19,0,124,2,0,106,1,0, + 124,0,0,131,1,0,125,1,0,87,110,18,0,4,116,2, + 0,107,10,0,114,72,0,1,1,1,89,110,1,0,88,116, + 3,0,106,4,0,124,0,0,124,2,0,100,4,0,124,1, + 0,131,2,1,125,4,0,100,5,0,124,4,0,95,5,0, + 124,2,0,100,1,0,107,8,0,114,194,0,120,73,0,116, + 6,0,131,0,0,68,93,58,0,92,2,0,125,5,0,125, + 6,0,124,1,0,106,7,0,116,8,0,124,6,0,131,1, + 0,131,1,0,114,128,0,124,5,0,124,0,0,124,1,0, + 131,2,0,125,2,0,124,2,0,124,4,0,95,9,0,80, + 113,128,0,87,100,1,0,83,124,3,0,116,10,0,107,8, + 0,114,23,1,116,0,0,124,2,0,100,6,0,131,2,0, + 114,32,1,121,19,0,124,2,0,106,11,0,124,0,0,131, + 1,0,125,7,0,87,110,18,0,4,116,2,0,107,10,0, + 114,4,1,1,1,1,89,113,32,1,88,124,7,0,114,32, + 1,103,0,0,124,4,0,95,12,0,110,9,0,124,3,0, + 124,4,0,95,12,0,124,4,0,106,12,0,103,0,0,107, + 2,0,114,85,1,124,1,0,114,85,1,116,13,0,124,1, + 0,131,1,0,100,7,0,25,125,8,0,124,4,0,106,12, + 0,106,14,0,124,8,0,131,1,0,1,124,4,0,83,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,218,6,111, + 114,105,103,105,110,84,218,10,105,115,95,112,97,99,107,97, + 103,101,114,59,0,0,0,41,15,114,115,0,0,0,114,157, + 0,0,0,114,107,0,0,0,114,121,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,92,0,0,0,114,93,0,0,0,114, + 127,0,0,0,218,9,95,80,79,80,85,76,65,84,69,114, + 159,0,0,0,114,156,0,0,0,114,38,0,0,0,218,6, + 97,112,112,101,110,100,41,9,114,106,0,0,0,90,8,108, + 111,99,97,116,105,111,110,114,127,0,0,0,114,156,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, + 159,0,0,0,90,7,100,105,114,110,97,109,101,114,4,0, + 0,0,114,4,0,0,0,114,5,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,252,1,0,0,115,60,0,0,0,0,12, + 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, + 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, + 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, + 9,1,15,1,6,1,16,1,16,2,114,167,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 64,0,0,0,115,121,0,0,0,101,0,0,90,1,0,100, + 0,0,90,2,0,100,1,0,90,3,0,100,2,0,90,4, + 0,100,3,0,90,5,0,100,4,0,90,6,0,101,7,0, + 100,5,0,100,6,0,132,0,0,131,1,0,90,8,0,101, + 7,0,100,7,0,100,8,0,132,0,0,131,1,0,90,9, + 0,101,7,0,100,9,0,100,9,0,100,10,0,100,11,0, + 132,2,0,131,1,0,90,10,0,101,7,0,100,9,0,100, + 12,0,100,13,0,132,1,0,131,1,0,90,11,0,100,9, + 0,83,41,14,218,21,87,105,110,100,111,119,115,82,101,103, + 105,115,116,114,121,70,105,110,100,101,114,122,62,77,101,116, + 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, + 114,32,109,111,100,117,108,101,115,32,100,101,99,108,97,114, + 101,100,32,105,110,32,116,104,101,32,87,105,110,100,111,119, + 115,32,114,101,103,105,115,116,114,121,46,122,59,83,111,102, + 116,119,97,114,101,92,80,121,116,104,111,110,92,80,121,116, + 104,111,110,67,111,114,101,92,123,115,121,115,95,118,101,114, + 115,105,111,110,125,92,77,111,100,117,108,101,115,92,123,102, + 117,108,108,110,97,109,101,125,122,65,83,111,102,116,119,97, + 114,101,92,80,121,116,104,111,110,92,80,121,116,104,111,110, + 67,111,114,101,92,123,115,121,115,95,118,101,114,115,105,111, + 110,125,92,77,111,100,117,108,101,115,92,123,102,117,108,108, + 110,97,109,101,125,92,68,101,98,117,103,70,99,2,0,0, + 0,0,0,0,0,2,0,0,0,11,0,0,0,67,0,0, + 0,115,67,0,0,0,121,23,0,116,0,0,106,1,0,116, + 0,0,106,2,0,124,1,0,131,2,0,83,87,110,37,0, + 4,116,3,0,107,10,0,114,62,0,1,1,1,116,0,0, + 106,1,0,116,0,0,106,4,0,124,1,0,131,2,0,83, + 89,110,1,0,88,100,0,0,83,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,218,3,107,101,121,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, + 101,103,105,115,116,114,121,74,2,0,0,115,8,0,0,0, + 0,2,3,1,23,1,13,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,16,0,0,0,67, + 0,0,0,115,143,0,0,0,124,0,0,106,0,0,114,21, + 0,124,0,0,106,1,0,125,2,0,110,9,0,124,0,0, + 106,2,0,125,2,0,124,2,0,106,3,0,100,1,0,124, + 1,0,100,2,0,116,4,0,106,5,0,100,0,0,100,3, + 0,133,2,0,25,131,0,2,125,3,0,121,47,0,124,0, + 0,106,6,0,124,3,0,131,1,0,143,25,0,125,4,0, + 116,7,0,106,8,0,124,4,0,100,4,0,131,2,0,125, + 5,0,87,100,0,0,81,82,88,87,110,22,0,4,116,9, + 0,107,10,0,114,138,0,1,1,1,100,0,0,83,89,110, + 1,0,88,124,5,0,83,41,5,78,114,126,0,0,0,90, + 11,115,121,115,95,118,101,114,115,105,111,110,114,80,0,0, + 0,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,47,0,0,0,114,7,0,0, + 0,218,7,118,101,114,115,105,111,110,114,172,0,0,0,114, + 169,0,0,0,90,10,81,117,101,114,121,86,97,108,117,101, + 114,40,0,0,0,41,6,114,170,0,0,0,114,126,0,0, + 0,90,12,114,101,103,105,115,116,114,121,95,107,101,121,114, + 171,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101, + 112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103, + 105,115,116,114,121,81,2,0,0,115,22,0,0,0,0,2, + 9,1,12,2,9,1,15,1,22,1,3,1,18,1,29,1, + 13,1,9,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,14,0,0,0,67,0, + 0,0,115,158,0,0,0,124,0,0,106,0,0,124,1,0, + 131,1,0,125,4,0,124,4,0,100,0,0,107,8,0,114, + 31,0,100,0,0,83,121,14,0,116,1,0,124,4,0,131, + 1,0,1,87,110,22,0,4,116,2,0,107,10,0,114,69, + 0,1,1,1,100,0,0,83,89,110,1,0,88,120,81,0, + 116,3,0,131,0,0,68,93,70,0,92,2,0,125,5,0, + 125,6,0,124,4,0,106,4,0,116,5,0,124,6,0,131, + 1,0,131,1,0,114,80,0,116,6,0,106,7,0,124,1, + 0,124,5,0,124,1,0,124,4,0,131,2,0,100,1,0, + 124,4,0,131,2,1,125,7,0,124,7,0,83,113,80,0, + 87,100,0,0,83,41,2,78,114,158,0,0,0,41,8,114, + 178,0,0,0,114,39,0,0,0,114,40,0,0,0,114,161, + 0,0,0,114,92,0,0,0,114,93,0,0,0,114,121,0, + 0,0,218,16,115,112,101,99,95,102,114,111,109,95,108,111, + 97,100,101,114,41,8,114,170,0,0,0,114,126,0,0,0, + 114,35,0,0,0,218,6,116,97,114,103,101,116,114,177,0, + 0,0,114,127,0,0,0,114,166,0,0,0,114,164,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,9,102,105,110,100,95,115,112,101,99,96,2,0,0,115, + 26,0,0,0,0,2,15,1,12,1,4,1,3,1,14,1, + 13,1,9,1,22,1,21,1,9,1,15,1,9,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,3,0,0,0, + 67,0,0,0,115,45,0,0,0,124,0,0,106,0,0,124, + 1,0,124,2,0,131,2,0,125,3,0,124,3,0,100,1, + 0,107,9,0,114,37,0,124,3,0,106,1,0,83,100,1, + 0,83,100,1,0,83,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,181,0,0,0,114,127, + 0,0,0,41,4,114,170,0,0,0,114,126,0,0,0,114, + 35,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,5,0,0,0,218,11,102,105,110,100,95,109, + 111,100,117,108,101,112,2,0,0,115,8,0,0,0,0,7, + 18,1,12,1,7,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,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,45,0,0, - 0,124,0,0,106,0,0,124,1,0,124,2,0,131,2,0, - 125,3,0,124,3,0,100,1,0,107,9,0,114,37,0,124, - 3,0,106,1,0,83,100,1,0,83,100,1,0,83,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,181,0,0,0,114,127,0,0,0,41,4,114,170,0, - 0,0,114,126,0,0,0,114,35,0,0,0,114,164,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,11,102,105,110,100,95,109,111,100,117,108,101,111,2,0, - 0,115,8,0,0,0,0,7,18,1,12,1,7,2,122,33, - 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, - 105,110,100,101,114,46,102,105,110,100,95,109,111,100,117,108, - 101,41,12,114,112,0,0,0,114,111,0,0,0,114,113,0, - 0,0,114,114,0,0,0,114,175,0,0,0,114,174,0,0, - 0,114,173,0,0,0,218,11,99,108,97,115,115,109,101,116, - 104,111,100,114,172,0,0,0,114,178,0,0,0,114,181,0, - 0,0,114,182,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,168,0,0,0, - 61,2,0,0,115,20,0,0,0,12,2,6,3,6,3,6, - 2,6,2,18,7,18,15,3,1,21,15,3,1,114,168,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,70,0,0,0,101,0,0,90, - 1,0,100,0,0,90,2,0,100,1,0,90,3,0,100,2, - 0,100,3,0,132,0,0,90,4,0,100,4,0,100,5,0, - 132,0,0,90,5,0,100,6,0,100,7,0,132,0,0,90, - 6,0,100,8,0,100,9,0,132,0,0,90,7,0,100,10, - 0,83,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,3,0,0,0,67,0,0,0,115,88,0, - 0,0,116,0,0,124,0,0,106,1,0,124,1,0,131,1, - 0,131,1,0,100,1,0,25,125,2,0,124,2,0,106,2, - 0,100,2,0,100,1,0,131,2,0,100,3,0,25,125,3, - 0,124,1,0,106,3,0,100,2,0,131,1,0,100,4,0, - 25,125,4,0,124,3,0,100,5,0,107,2,0,111,87,0, - 124,4,0,100,5,0,107,3,0,83,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,58,0,0,0,114,59,0,0,0,114,56,0,0,0,218, - 8,95,95,105,110,105,116,95,95,41,4,114,38,0,0,0, - 114,157,0,0,0,114,34,0,0,0,114,32,0,0,0,41, - 5,114,108,0,0,0,114,126,0,0,0,114,94,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,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,159,0,0,0,130,2, - 0,0,115,8,0,0,0,0,3,25,1,22,1,19,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,0,83,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,4,0,0,0,41,2,114,108,0, - 0,0,114,164,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,13,99,114,101,97,116,101,95,109, - 111,100,117,108,101,138,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,4,0,0,0,67,0,0,0, - 115,80,0,0,0,124,0,0,106,0,0,124,1,0,106,1, - 0,131,1,0,125,2,0,124,2,0,100,1,0,107,8,0, - 114,54,0,116,2,0,100,2,0,106,3,0,124,1,0,106, - 1,0,131,1,0,131,1,0,130,1,0,116,4,0,106,5, - 0,116,6,0,124,2,0,124,1,0,106,7,0,131,3,0, - 1,100,1,0,83,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, - 112,0,0,0,114,107,0,0,0,114,47,0,0,0,114,121, - 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,118,0,0,0,41,3,114,108,0,0,0, - 218,6,109,111,100,117,108,101,114,146,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,11,101,120, - 101,99,95,109,111,100,117,108,101,141,2,0,0,115,10,0, - 0,0,0,2,18,1,12,1,9,1,15,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,3,0,0,0,67,0,0,0,115,16,0,0, - 0,116,0,0,106,1,0,124,0,0,124,1,0,131,2,0, - 83,41,1,78,41,2,114,121,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,11,108,111,97,100,95, - 109,111,100,117,108,101,149,2,0,0,115,2,0,0,0,0, - 1,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, - 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, - 0,0,0,114,159,0,0,0,114,186,0,0,0,114,191,0, - 0,0,114,193,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,184,0,0,0, - 125,2,0,0,115,10,0,0,0,12,3,6,2,12,8,12, - 3,12,8,114,184,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,106,0, - 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, - 0,100,2,0,132,0,0,90,3,0,100,3,0,100,4,0, - 132,0,0,90,4,0,100,5,0,100,6,0,132,0,0,90, - 5,0,100,7,0,100,8,0,132,0,0,90,6,0,100,9, - 0,100,10,0,132,0,0,90,7,0,100,11,0,100,18,0, - 100,13,0,100,14,0,132,0,1,90,8,0,100,15,0,100, - 16,0,132,0,0,90,9,0,100,17,0,83,41,19,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,10,0,0,0,116,0,0,130,1,0,100,1,0,83, - 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,73,79,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,218,7,73,79,69,114,114, - 111,114,41,2,114,108,0,0,0,114,35,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,112, - 97,116,104,95,109,116,105,109,101,155,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,3,0,0,0,67,0, - 0,0,115,19,0,0,0,124,0,0,106,0,0,124,1,0, - 131,1,0,100,1,0,105,1,0,83,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,73,79,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,133,0,0,0, - 41,1,114,196,0,0,0,41,2,114,108,0,0,0,114,35, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,10,112,97,116,104,95,115,116,97,116,115,163,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,3, - 0,0,0,67,0,0,0,115,16,0,0,0,124,0,0,106, - 0,0,124,2,0,124,3,0,131,2,0,83,41,1,122,228, + 110,100,95,109,111,100,117,108,101,41,12,114,112,0,0,0, + 114,111,0,0,0,114,113,0,0,0,114,114,0,0,0,114, + 175,0,0,0,114,174,0,0,0,114,173,0,0,0,218,11, + 99,108,97,115,115,109,101,116,104,111,100,114,172,0,0,0, + 114,178,0,0,0,114,181,0,0,0,114,182,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,168,0,0,0,62,2,0,0,115,20,0,0, + 0,12,2,6,3,6,3,6,2,6,2,18,7,18,15,3, + 1,21,15,3,1,114,168,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, + 70,0,0,0,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,100,2,0,100,3,0,132,0,0,90, + 4,0,100,4,0,100,5,0,132,0,0,90,5,0,100,6, + 0,100,7,0,132,0,0,90,6,0,100,8,0,100,9,0, + 132,0,0,90,7,0,100,10,0,83,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,3,0,0, + 0,67,0,0,0,115,88,0,0,0,116,0,0,124,0,0, + 106,1,0,124,1,0,131,1,0,131,1,0,100,1,0,25, + 125,2,0,124,2,0,106,2,0,100,2,0,100,1,0,131, + 2,0,100,3,0,25,125,3,0,124,1,0,106,3,0,100, + 2,0,131,1,0,100,4,0,25,125,4,0,124,3,0,100, + 5,0,107,2,0,111,87,0,124,4,0,100,5,0,107,3, + 0,83,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,58,0,0,0,114,59,0, + 0,0,114,56,0,0,0,218,8,95,95,105,110,105,116,95, + 95,41,4,114,38,0,0,0,114,157,0,0,0,114,34,0, + 0,0,114,32,0,0,0,41,5,114,108,0,0,0,114,126, + 0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,159,0,0,0,131,2,0,0,115,8,0,0,0,0, + 3,25,1,22,1,19,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,0,83,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,4, + 0,0,0,41,2,114,108,0,0,0,114,164,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,13, + 99,114,101,97,116,101,95,109,111,100,117,108,101,139,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, + 4,0,0,0,67,0,0,0,115,80,0,0,0,124,0,0, + 106,0,0,124,1,0,106,1,0,131,1,0,125,2,0,124, + 2,0,100,1,0,107,8,0,114,54,0,116,2,0,100,2, + 0,106,3,0,124,1,0,106,1,0,131,1,0,131,1,0, + 130,1,0,116,4,0,106,5,0,116,6,0,124,2,0,124, + 1,0,106,7,0,131,3,0,1,100,1,0,83,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,112,0,0,0,114,107,0,0, + 0,114,47,0,0,0,114,121,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,118,0,0, + 0,41,3,114,108,0,0,0,218,6,109,111,100,117,108,101, + 114,146,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, + 101,142,2,0,0,115,10,0,0,0,0,2,18,1,12,1, + 9,1,15,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,3,0,0,0, + 67,0,0,0,115,16,0,0,0,116,0,0,106,1,0,124, + 0,0,124,1,0,131,2,0,83,41,1,78,41,2,114,121, + 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,108,0,0,0,114,126,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,150,2, + 0,0,115,2,0,0,0,0,1,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,112,0,0,0,114,111,0,0, + 0,114,113,0,0,0,114,114,0,0,0,114,159,0,0,0, + 114,186,0,0,0,114,191,0,0,0,114,193,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,184,0,0,0,126,2,0,0,115,10,0,0, + 0,12,3,6,2,12,8,12,3,12,8,114,184,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,106,0,0,0,101,0,0,90,1,0, + 100,0,0,90,2,0,100,1,0,100,2,0,132,0,0,90, + 3,0,100,3,0,100,4,0,132,0,0,90,4,0,100,5, + 0,100,6,0,132,0,0,90,5,0,100,7,0,100,8,0, + 132,0,0,90,6,0,100,9,0,100,10,0,132,0,0,90, + 7,0,100,11,0,100,18,0,100,13,0,100,14,0,132,0, + 1,90,8,0,100,15,0,100,16,0,132,0,0,90,9,0, + 100,17,0,83,41,19,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,10,0,0,0,116,0, + 0,130,1,0,100,1,0,83,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,73,79,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,218,7,73,79,69,114,114,111,114,41,2,114,108,0,0, + 0,114,35,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,10,112,97,116,104,95,109,116,105,109, + 101,156,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,3,0,0,0,67,0,0,0,115,19,0,0,0,124, + 0,0,106,0,0,124,1,0,131,1,0,100,1,0,105,1, + 0,83,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,73,79,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,133,0,0,0,41,1,114,196,0,0,0,41, + 2,114,108,0,0,0,114,35,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,218,10,112,97,116,104, + 95,115,116,97,116,115,164,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,3,0,0,0,67,0,0,0,115, + 16,0,0,0,124,0,0,106,0,0,124,2,0,124,3,0, + 131,2,0,83,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,108,0,0,0,114, + 90,0,0,0,90,10,99,97,99,104,101,95,112,97,116,104, + 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,15,95,99,97,99,104,101,95,98,121,116, + 101,99,111,100,101,177,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,0,83,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, @@ -1143,568 +1168,549 @@ 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,108,0,0,0,114,90,0,0,0,90,10,99,97, - 99,104,101,95,112,97,116,104,114,53,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,218,15,95,99, - 97,99,104,101,95,98,121,116,101,99,111,100,101,176,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,0,83,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, - 4,0,0,0,41,3,114,108,0,0,0,114,35,0,0,0, - 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,198,0,0,0,186,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,16,0,0,0,67,0,0,0,115,105, - 0,0,0,124,0,0,106,0,0,124,1,0,131,1,0,125, - 2,0,121,19,0,124,0,0,106,1,0,124,2,0,131,1, - 0,125,3,0,87,110,58,0,4,116,2,0,107,10,0,114, - 94,0,1,125,4,0,1,122,26,0,116,3,0,100,1,0, - 100,2,0,124,1,0,131,1,1,124,4,0,130,2,0,87, - 89,100,3,0,100,3,0,125,4,0,126,4,0,88,110,1, - 0,88,116,4,0,124,3,0,131,1,0,83,41,4,122,52, - 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, - 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, - 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, - 103,104,32,103,101,116,95,100,97,116,97,40,41,114,106,0, - 0,0,78,41,5,114,157,0,0,0,218,8,103,101,116,95, - 100,97,116,97,114,40,0,0,0,114,107,0,0,0,114,155, - 0,0,0,41,5,114,108,0,0,0,114,126,0,0,0,114, - 35,0,0,0,114,153,0,0,0,218,3,101,120,99,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,10,103, - 101,116,95,115,111,117,114,99,101,193,2,0,0,115,14,0, - 0,0,0,2,15,1,3,1,19,1,18,1,9,1,31,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,218,9,95,111,112,116,105, - 109,105,122,101,114,29,0,0,0,99,3,0,0,0,1,0, - 0,0,4,0,0,0,9,0,0,0,67,0,0,0,115,34, - 0,0,0,116,0,0,106,1,0,116,2,0,124,1,0,124, - 2,0,100,1,0,100,2,0,100,3,0,100,4,0,124,3, - 0,131,4,2,83,41,5,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,189,0,0,0, - 218,12,100,111,110,116,95,105,110,104,101,114,105,116,84,114, - 68,0,0,0,41,3,114,121,0,0,0,114,188,0,0,0, - 218,7,99,111,109,112,105,108,101,41,4,114,108,0,0,0, - 114,53,0,0,0,114,35,0,0,0,114,203,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,14, - 115,111,117,114,99,101,95,116,111,95,99,111,100,101,203,2, - 0,0,115,4,0,0,0,0,5,21,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,10,0,0,0,43,0,0,0,67,0,0,0,115,174,1, - 0,0,124,0,0,106,0,0,124,1,0,131,1,0,125,2, - 0,100,1,0,125,3,0,121,16,0,116,1,0,124,2,0, - 131,1,0,125,4,0,87,110,24,0,4,116,2,0,107,10, - 0,114,63,0,1,1,1,100,1,0,125,4,0,89,110,202, - 0,88,121,19,0,124,0,0,106,3,0,124,2,0,131,1, - 0,125,5,0,87,110,18,0,4,116,4,0,107,10,0,114, - 103,0,1,1,1,89,110,162,0,88,116,5,0,124,5,0, - 100,2,0,25,131,1,0,125,3,0,121,19,0,124,0,0, - 106,6,0,124,4,0,131,1,0,125,6,0,87,110,18,0, - 4,116,7,0,107,10,0,114,159,0,1,1,1,89,110,106, - 0,88,121,34,0,116,8,0,124,6,0,100,3,0,124,5, - 0,100,4,0,124,1,0,100,5,0,124,4,0,131,1,3, - 125,7,0,87,110,24,0,4,116,9,0,116,10,0,102,2, - 0,107,10,0,114,220,0,1,1,1,89,110,45,0,88,116, - 11,0,100,6,0,124,4,0,124,2,0,131,3,0,1,116, - 12,0,124,7,0,100,4,0,124,1,0,100,7,0,124,4, - 0,100,8,0,124,2,0,131,1,3,83,124,0,0,106,6, - 0,124,2,0,131,1,0,125,8,0,124,0,0,106,13,0, - 124,8,0,124,2,0,131,2,0,125,9,0,116,11,0,100, - 9,0,124,2,0,131,2,0,1,116,14,0,106,15,0,12, - 114,170,1,124,4,0,100,1,0,107,9,0,114,170,1,124, - 3,0,100,1,0,107,9,0,114,170,1,116,16,0,124,9, - 0,124,3,0,116,17,0,124,8,0,131,1,0,131,3,0, - 125,6,0,121,36,0,124,0,0,106,18,0,124,2,0,124, - 4,0,124,6,0,131,3,0,1,116,11,0,100,10,0,124, - 4,0,131,2,0,1,87,110,18,0,4,116,2,0,107,10, - 0,114,169,1,1,1,1,89,110,1,0,88,124,9,0,83, - 41,11,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,114,133,0,0,0,114,138,0,0,0,114,106,0, - 0,0,114,35,0,0,0,122,13,123,125,32,109,97,116,99, - 104,101,115,32,123,125,114,89,0,0,0,114,90,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,19,114,157,0,0,0,114,79,0,0,0,114,66,0, - 0,0,114,197,0,0,0,114,195,0,0,0,114,14,0,0, - 0,114,200,0,0,0,114,40,0,0,0,114,141,0,0,0, - 114,107,0,0,0,114,136,0,0,0,114,105,0,0,0,114, - 147,0,0,0,114,206,0,0,0,114,7,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,150,0,0,0,114,31,0,0,0,114,199,0, - 0,0,41,10,114,108,0,0,0,114,126,0,0,0,114,90, - 0,0,0,114,139,0,0,0,114,89,0,0,0,218,2,115, - 116,114,53,0,0,0,218,10,98,121,116,101,115,95,100,97, - 116,97,114,153,0,0,0,90,11,99,111,100,101,95,111,98, - 106,101,99,116,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,187,0,0,0,211,2,0,0,115,78,0,0, - 0,0,7,15,1,6,1,3,1,16,1,13,1,11,2,3, - 1,19,1,13,1,5,2,16,1,3,1,19,1,13,1,5, - 2,3,1,9,1,12,1,13,1,19,1,5,2,9,1,7, - 1,15,1,6,1,7,1,15,1,18,1,13,1,22,1,12, - 1,9,1,15,1,3,1,19,1,17,1,13,1,5,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,114,87,0,0,0,41,10,114,112, - 0,0,0,114,111,0,0,0,114,113,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,187,0,0,0, + 116,101,99,111,100,101,32,102,105,108,101,115,46,10,32,32, + 32,32,32,32,32,32,78,114,4,0,0,0,41,3,114,108, + 0,0,0,114,35,0,0,0,114,53,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, + 0,187,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,16,0, + 0,0,67,0,0,0,115,105,0,0,0,124,0,0,106,0, + 0,124,1,0,131,1,0,125,2,0,121,19,0,124,0,0, + 106,1,0,124,2,0,131,1,0,125,3,0,87,110,58,0, + 4,116,2,0,107,10,0,114,94,0,1,125,4,0,1,122, + 26,0,116,3,0,100,1,0,100,2,0,124,1,0,131,1, + 1,124,4,0,130,2,0,87,89,100,3,0,100,3,0,125, + 4,0,126,4,0,88,110,1,0,88,116,4,0,124,3,0, + 131,1,0,83,41,4,122,52,67,111,110,99,114,101,116,101, + 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, + 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,46,122,39,115,111, + 117,114,99,101,32,110,111,116,32,97,118,97,105,108,97,98, + 108,101,32,116,104,114,111,117,103,104,32,103,101,116,95,100, + 97,116,97,40,41,114,106,0,0,0,78,41,5,114,157,0, + 0,0,218,8,103,101,116,95,100,97,116,97,114,40,0,0, + 0,114,107,0,0,0,114,155,0,0,0,41,5,114,108,0, + 0,0,114,126,0,0,0,114,35,0,0,0,114,153,0,0, + 0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,10,103,101,116,95,115,111,117,114,99, + 101,194,2,0,0,115,14,0,0,0,0,2,15,1,3,1, + 19,1,18,1,9,1,31,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,218,9,95,111,112,116,105,109,105,122,101,114,29,0,0, + 0,99,3,0,0,0,1,0,0,0,4,0,0,0,9,0, + 0,0,67,0,0,0,115,34,0,0,0,116,0,0,106,1, + 0,116,2,0,124,1,0,124,2,0,100,1,0,100,2,0, + 100,3,0,100,4,0,124,3,0,131,4,2,83,41,5,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,189,0,0,0,218,12,100,111,110,116,95,105, + 110,104,101,114,105,116,84,114,68,0,0,0,41,3,114,121, + 0,0,0,114,188,0,0,0,218,7,99,111,109,112,105,108, + 101,41,4,114,108,0,0,0,114,53,0,0,0,114,35,0, + 0,0,114,203,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,14,115,111,117,114,99,101,95,116, + 111,95,99,111,100,101,204,2,0,0,115,4,0,0,0,0, + 5,21,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,10,0,0,0,43,0,0, + 0,67,0,0,0,115,174,1,0,0,124,0,0,106,0,0, + 124,1,0,131,1,0,125,2,0,100,1,0,125,3,0,121, + 16,0,116,1,0,124,2,0,131,1,0,125,4,0,87,110, + 24,0,4,116,2,0,107,10,0,114,63,0,1,1,1,100, + 1,0,125,4,0,89,110,202,0,88,121,19,0,124,0,0, + 106,3,0,124,2,0,131,1,0,125,5,0,87,110,18,0, + 4,116,4,0,107,10,0,114,103,0,1,1,1,89,110,162, + 0,88,116,5,0,124,5,0,100,2,0,25,131,1,0,125, + 3,0,121,19,0,124,0,0,106,6,0,124,4,0,131,1, + 0,125,6,0,87,110,18,0,4,116,7,0,107,10,0,114, + 159,0,1,1,1,89,110,106,0,88,121,34,0,116,8,0, + 124,6,0,100,3,0,124,5,0,100,4,0,124,1,0,100, + 5,0,124,4,0,131,1,3,125,7,0,87,110,24,0,4, + 116,9,0,116,10,0,102,2,0,107,10,0,114,220,0,1, + 1,1,89,110,45,0,88,116,11,0,100,6,0,124,4,0, + 124,2,0,131,3,0,1,116,12,0,124,7,0,100,4,0, + 124,1,0,100,7,0,124,4,0,100,8,0,124,2,0,131, + 1,3,83,124,0,0,106,6,0,124,2,0,131,1,0,125, + 8,0,124,0,0,106,13,0,124,8,0,124,2,0,131,2, + 0,125,9,0,116,11,0,100,9,0,124,2,0,131,2,0, + 1,116,14,0,106,15,0,12,114,170,1,124,4,0,100,1, + 0,107,9,0,114,170,1,124,3,0,100,1,0,107,9,0, + 114,170,1,116,16,0,124,9,0,124,3,0,116,17,0,124, + 8,0,131,1,0,131,3,0,125,6,0,121,36,0,124,0, + 0,106,18,0,124,2,0,124,4,0,124,6,0,131,3,0, + 1,116,11,0,100,10,0,124,4,0,131,2,0,1,87,110, + 18,0,4,116,2,0,107,10,0,114,169,1,1,1,1,89, + 110,1,0,88,124,9,0,83,41,11,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,114,133,0,0,0, + 114,138,0,0,0,114,106,0,0,0,114,35,0,0,0,122, + 13,123,125,32,109,97,116,99,104,101,115,32,123,125,114,89, + 0,0,0,114,90,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,19,114,157,0,0,0, + 114,79,0,0,0,114,66,0,0,0,114,197,0,0,0,114, + 195,0,0,0,114,14,0,0,0,114,200,0,0,0,114,40, + 0,0,0,114,141,0,0,0,114,107,0,0,0,114,136,0, + 0,0,114,105,0,0,0,114,147,0,0,0,114,206,0,0, + 0,114,7,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,150,0,0,0, + 114,31,0,0,0,114,199,0,0,0,41,10,114,108,0,0, + 0,114,126,0,0,0,114,90,0,0,0,114,139,0,0,0, + 114,89,0,0,0,218,2,115,116,114,53,0,0,0,218,10, + 98,121,116,101,115,95,100,97,116,97,114,153,0,0,0,90, + 11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0, + 0,114,4,0,0,0,114,5,0,0,0,114,187,0,0,0, + 212,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, + 1,16,1,13,1,11,2,3,1,19,1,13,1,5,2,16, + 1,3,1,19,1,13,1,5,2,3,1,9,1,12,1,13, + 1,19,1,5,2,9,1,7,1,15,1,6,1,7,1,15, + 1,18,1,13,1,22,1,12,1,9,1,15,1,3,1,19, + 1,17,1,13,1,5,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,114, + 87,0,0,0,41,10,114,112,0,0,0,114,111,0,0,0, + 114,113,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,187,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, + 0,154,2,0,0,115,14,0,0,0,12,2,12,8,12,13, + 12,10,12,7,12,10,18,8,114,194,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,112,0,0,0,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, + 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, + 0,100,6,0,100,7,0,132,0,0,90,6,0,101,7,0, + 135,0,0,102,1,0,100,8,0,100,9,0,134,0,0,131, + 1,0,90,8,0,101,7,0,100,10,0,100,11,0,132,0, + 0,131,1,0,90,9,0,100,12,0,100,13,0,132,0,0, + 90,10,0,135,0,0,83,41,14,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,22,0,0,0,124,1,0,124,0,0,95,0, + 0,124,2,0,124,0,0,95,1,0,100,1,0,83,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,106,0,0,0,114,35,0,0,0,41,3,114,108,0,0, + 0,114,126,0,0,0,114,35,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,13, + 3,0,0,115,4,0,0,0,0,3,9,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,34,0,0,0,124,0,0,106,0, + 0,124,1,0,106,0,0,107,2,0,111,33,0,124,0,0, + 106,1,0,124,1,0,106,1,0,107,2,0,83,41,1,78, + 41,2,218,9,95,95,99,108,97,115,115,95,95,114,118,0, + 0,0,41,2,114,108,0,0,0,218,5,111,116,104,101,114, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, + 6,95,95,101,113,95,95,19,3,0,0,115,4,0,0,0, + 0,1,18,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,26,0,0, + 0,116,0,0,124,0,0,106,1,0,131,1,0,116,0,0, + 124,0,0,106,2,0,131,1,0,65,83,41,1,78,41,3, + 218,4,104,97,115,104,114,106,0,0,0,114,35,0,0,0, + 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,218,8,95,95,104,97,115,104,95,95, + 23,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,22,0,0,0,116,0,0,116,1,0, + 124,0,0,131,2,0,106,2,0,124,1,0,131,1,0,83, + 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,210,0,0,0,114,193,0,0,0,41,2,114,108,0, + 0,0,114,126,0,0,0,41,1,114,211,0,0,0,114,4, + 0,0,0,114,5,0,0,0,114,193,0,0,0,26,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,7,0,0,0,124,0,0,106,0,0, + 83,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,108,0,0,0,114,126,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, + 0,114,157,0,0,0,38,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, + 42,0,0,0,116,0,0,106,1,0,124,1,0,100,1,0, + 131,2,0,143,17,0,125,2,0,124,2,0,106,2,0,131, + 0,0,83,87,100,2,0,81,82,88,100,2,0,83,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, + 49,0,0,0,114,50,0,0,0,90,4,114,101,97,100,41, + 3,114,108,0,0,0,114,35,0,0,0,114,54,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 200,0,0,0,43,3,0,0,115,4,0,0,0,0,2,21, + 1,122,19,70,105,108,101,76,111,97,100,101,114,46,103,101, + 116,95,100,97,116,97,41,11,114,112,0,0,0,114,111,0, + 0,0,114,113,0,0,0,114,114,0,0,0,114,185,0,0, + 0,114,213,0,0,0,114,215,0,0,0,114,123,0,0,0, + 114,193,0,0,0,114,157,0,0,0,114,200,0,0,0,114, + 4,0,0,0,114,4,0,0,0,41,1,114,211,0,0,0, + 114,5,0,0,0,114,210,0,0,0,8,3,0,0,115,14, + 0,0,0,12,3,6,2,12,6,12,4,12,3,24,12,18, + 5,114,210,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,64,0,0,0, + 101,0,0,90,1,0,100,0,0,90,2,0,100,1,0,90, + 3,0,100,2,0,100,3,0,132,0,0,90,4,0,100,4, + 0,100,5,0,132,0,0,90,5,0,100,6,0,100,7,0, + 100,8,0,100,9,0,132,0,1,90,6,0,100,10,0,83, + 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,5,0,0,0,67,0,0,0,115,34,0,0,0,116,0, + 0,124,1,0,131,1,0,125,2,0,124,2,0,106,1,0, + 100,1,0,124,2,0,106,2,0,100,2,0,105,2,0,83, + 41,3,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,114,133,0,0,0,114,134,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,108,0,0,0, + 114,35,0,0,0,114,208,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,197,0,0,0,53,3, + 0,0,115,4,0,0,0,0,2,12,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,34,0, + 0,0,116,0,0,124,1,0,131,1,0,125,4,0,124,0, + 0,106,1,0,124,2,0,124,3,0,100,1,0,124,4,0, + 131,2,1,83,41,2,78,218,5,95,109,111,100,101,41,2, + 114,97,0,0,0,114,198,0,0,0,41,5,114,108,0,0, + 0,114,90,0,0,0,114,89,0,0,0,114,53,0,0,0, + 114,42,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,199,0,0,0,58,3,0,0,115,4,0, + 0,0,0,2,12,1,122,32,83,111,117,114,99,101,70,105, + 108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, + 98,121,116,101,99,111,100,101,114,220,0,0,0,105,182,1, + 0,0,99,3,0,0,0,1,0,0,0,9,0,0,0,17, + 0,0,0,67,0,0,0,115,53,1,0,0,116,0,0,124, + 1,0,131,1,0,92,2,0,125,4,0,125,5,0,103,0, + 0,125,6,0,120,54,0,124,4,0,114,80,0,116,1,0, + 124,4,0,131,1,0,12,114,80,0,116,0,0,124,4,0, + 131,1,0,92,2,0,125,4,0,125,7,0,124,6,0,106, + 2,0,124,7,0,131,1,0,1,113,27,0,87,120,132,0, + 116,3,0,124,6,0,131,1,0,68,93,118,0,125,7,0, + 116,4,0,124,4,0,124,7,0,131,2,0,125,4,0,121, + 17,0,116,5,0,106,6,0,124,4,0,131,1,0,1,87, + 113,94,0,4,116,7,0,107,10,0,114,155,0,1,1,1, + 119,94,0,89,113,94,0,4,116,8,0,107,10,0,114,211, + 0,1,125,8,0,1,122,25,0,116,9,0,100,1,0,124, + 4,0,124,8,0,131,3,0,1,100,2,0,83,87,89,100, + 2,0,100,2,0,125,8,0,126,8,0,88,113,94,0,88, + 113,94,0,87,121,33,0,116,10,0,124,1,0,124,2,0, + 124,3,0,131,3,0,1,116,9,0,100,3,0,124,1,0, + 131,2,0,1,87,110,53,0,4,116,8,0,107,10,0,114, + 48,1,1,125,8,0,1,122,21,0,116,9,0,100,1,0, + 124,1,0,124,8,0,131,3,0,1,87,89,100,2,0,100, + 2,0,125,8,0,126,8,0,88,110,1,0,88,100,2,0, + 83,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,11,114,38, + 0,0,0,114,46,0,0,0,114,163,0,0,0,114,33,0, + 0,0,114,28,0,0,0,114,3,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,105,0,0,0,114,55, + 0,0,0,41,9,114,108,0,0,0,114,35,0,0,0,114, + 53,0,0,0,114,220,0,0,0,218,6,112,97,114,101,110, + 116,114,94,0,0,0,114,27,0,0,0,114,23,0,0,0, + 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,198,0,0,0,63,3,0,0,115,38,0, + 0,0,0,2,18,1,6,2,22,1,18,1,17,2,19,1, + 15,1,3,1,17,1,13,2,7,1,18,3,16,1,27,1, + 3,1,16,1,17,1,18,2,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,112,0,0,0,114,111,0,0,0, + 114,113,0,0,0,114,114,0,0,0,114,197,0,0,0,114, + 199,0,0,0,114,198,0,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,218,0, + 0,0,49,3,0,0,115,8,0,0,0,12,2,6,2,12, + 5,12,5,114,218,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,46,0, + 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, + 0,90,3,0,100,2,0,100,3,0,132,0,0,90,4,0, + 100,4,0,100,5,0,132,0,0,90,5,0,100,6,0,83, + 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,6,0,0,0,67,0,0,0,115,76,0,0, + 0,124,0,0,106,0,0,124,1,0,131,1,0,125,2,0, + 124,0,0,106,1,0,124,2,0,131,1,0,125,3,0,116, + 2,0,124,3,0,100,1,0,124,1,0,100,2,0,124,2, + 0,131,1,2,125,4,0,116,3,0,124,4,0,100,1,0, + 124,1,0,100,3,0,124,2,0,131,1,2,83,41,4,78, + 114,106,0,0,0,114,35,0,0,0,114,89,0,0,0,41, + 4,114,157,0,0,0,114,200,0,0,0,114,141,0,0,0, + 114,147,0,0,0,41,5,114,108,0,0,0,114,126,0,0, + 0,114,35,0,0,0,114,53,0,0,0,114,209,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, + 187,0,0,0,96,3,0,0,115,8,0,0,0,0,1,15, + 1,15,1,24,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, + 0,83,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,4, + 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,202, + 0,0,0,102,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,112,0,0,0,114,111,0,0,0,114,113,0,0, + 0,114,114,0,0,0,114,187,0,0,0,114,202,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,194,0,0,0,153,2,0,0,115,14,0, - 0,0,12,2,12,8,12,13,12,10,12,7,12,10,18,8, - 114,194,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,112,0,0,0,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, - 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, - 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, - 0,0,90,6,0,101,7,0,135,0,0,102,1,0,100,8, - 0,100,9,0,134,0,0,131,1,0,90,8,0,101,7,0, - 100,10,0,100,11,0,132,0,0,131,1,0,90,9,0,100, - 12,0,100,13,0,132,0,0,90,10,0,135,0,0,83,41, - 14,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,22,0,0,0, - 124,1,0,124,0,0,95,0,0,124,2,0,124,0,0,95, - 1,0,100,1,0,83,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,106,0,0,0,114,35,0, - 0,0,41,3,114,108,0,0,0,114,126,0,0,0,114,35, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,185,0,0,0,12,3,0,0,115,4,0,0,0, - 0,3,9,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,34, - 0,0,0,124,0,0,106,0,0,124,1,0,106,0,0,107, - 2,0,111,33,0,124,0,0,106,1,0,124,1,0,106,1, - 0,107,2,0,83,41,1,78,41,2,218,9,95,95,99,108, - 97,115,115,95,95,114,118,0,0,0,41,2,114,108,0,0, - 0,218,5,111,116,104,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,6,95,95,101,113,95,95,18, - 3,0,0,115,4,0,0,0,0,1,18,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,26,0,0,0,116,0,0,124,0,0,106, - 1,0,131,1,0,116,0,0,124,0,0,106,2,0,131,1, - 0,65,83,41,1,78,41,3,218,4,104,97,115,104,114,106, - 0,0,0,114,35,0,0,0,41,1,114,108,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,8, - 95,95,104,97,115,104,95,95,22,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,22,0, - 0,0,116,0,0,116,1,0,124,0,0,131,2,0,106,2, - 0,124,1,0,131,1,0,83,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,210,0,0,0,114,193, - 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,41, - 1,114,211,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,193,0,0,0,25,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,7,0, - 0,0,124,0,0,106,0,0,83,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,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,157,0,0,0,37,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,42,0,0,0,116,0,0,106, - 1,0,124,1,0,100,1,0,131,2,0,143,17,0,125,2, - 0,124,2,0,106,2,0,131,0,0,83,87,100,2,0,81, - 82,88,100,2,0,83,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,49,0,0,0,114,50,0,0, - 0,90,4,114,101,97,100,41,3,114,108,0,0,0,114,35, - 0,0,0,114,54,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,200,0,0,0,42,3,0,0, - 115,4,0,0,0,0,2,21,1,122,19,70,105,108,101,76, - 111,97,100,101,114,46,103,101,116,95,100,97,116,97,41,11, - 114,112,0,0,0,114,111,0,0,0,114,113,0,0,0,114, - 114,0,0,0,114,185,0,0,0,114,213,0,0,0,114,215, - 0,0,0,114,123,0,0,0,114,193,0,0,0,114,157,0, - 0,0,114,200,0,0,0,114,4,0,0,0,114,4,0,0, - 0,41,1,114,211,0,0,0,114,5,0,0,0,114,210,0, - 0,0,7,3,0,0,115,14,0,0,0,12,3,6,2,12, - 6,12,4,12,3,24,12,18,5,114,210,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,64,0,0,0,101,0,0,90,1,0,100,0, - 0,90,2,0,100,1,0,90,3,0,100,2,0,100,3,0, - 132,0,0,90,4,0,100,4,0,100,5,0,132,0,0,90, - 5,0,100,6,0,100,7,0,100,8,0,100,9,0,132,0, - 1,90,6,0,100,10,0,83,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,5,0,0,0,67,0,0, - 0,115,34,0,0,0,116,0,0,124,1,0,131,1,0,125, - 2,0,124,2,0,106,1,0,100,1,0,124,2,0,106,2, - 0,100,2,0,105,2,0,83,41,3,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,114,133,0, - 0,0,114,134,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,108,0,0,0,114,35,0,0,0,114,208,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,197,0,0,0,52,3,0,0,115,4,0,0,0,0, - 2,12,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,34,0,0,0,116,0,0,124,1,0, - 131,1,0,125,4,0,124,0,0,106,1,0,124,2,0,124, - 3,0,100,1,0,124,4,0,131,2,1,83,41,2,78,218, - 5,95,109,111,100,101,41,2,114,97,0,0,0,114,198,0, - 0,0,41,5,114,108,0,0,0,114,90,0,0,0,114,89, - 0,0,0,114,53,0,0,0,114,42,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,199,0,0, - 0,57,3,0,0,115,4,0,0,0,0,2,12,1,122,32, - 83,111,117,114,99,101,70,105,108,101,76,111,97,100,101,114, - 46,95,99,97,99,104,101,95,98,121,116,101,99,111,100,101, - 114,220,0,0,0,105,182,1,0,0,99,3,0,0,0,1, - 0,0,0,9,0,0,0,17,0,0,0,67,0,0,0,115, - 53,1,0,0,116,0,0,124,1,0,131,1,0,92,2,0, - 125,4,0,125,5,0,103,0,0,125,6,0,120,54,0,124, - 4,0,114,80,0,116,1,0,124,4,0,131,1,0,12,114, - 80,0,116,0,0,124,4,0,131,1,0,92,2,0,125,4, - 0,125,7,0,124,6,0,106,2,0,124,7,0,131,1,0, - 1,113,27,0,87,120,132,0,116,3,0,124,6,0,131,1, - 0,68,93,118,0,125,7,0,116,4,0,124,4,0,124,7, - 0,131,2,0,125,4,0,121,17,0,116,5,0,106,6,0, - 124,4,0,131,1,0,1,87,113,94,0,4,116,7,0,107, - 10,0,114,155,0,1,1,1,119,94,0,89,113,94,0,4, - 116,8,0,107,10,0,114,211,0,1,125,8,0,1,122,25, - 0,116,9,0,100,1,0,124,4,0,124,8,0,131,3,0, - 1,100,2,0,83,87,89,100,2,0,100,2,0,125,8,0, - 126,8,0,88,113,94,0,88,113,94,0,87,121,33,0,116, - 10,0,124,1,0,124,2,0,124,3,0,131,3,0,1,116, - 9,0,100,3,0,124,1,0,131,2,0,1,87,110,53,0, - 4,116,8,0,107,10,0,114,48,1,1,125,8,0,1,122, - 21,0,116,9,0,100,1,0,124,1,0,124,8,0,131,3, - 0,1,87,89,100,2,0,100,2,0,125,8,0,126,8,0, - 88,110,1,0,88,100,2,0,83,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,11,114,38,0,0,0,114,46,0,0,0, - 114,163,0,0,0,114,33,0,0,0,114,28,0,0,0,114, - 3,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,105,0,0,0,114,55,0,0,0,41,9,114,108,0, - 0,0,114,35,0,0,0,114,53,0,0,0,114,220,0,0, - 0,218,6,112,97,114,101,110,116,114,94,0,0,0,114,27, - 0,0,0,114,23,0,0,0,114,201,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, - 0,62,3,0,0,115,38,0,0,0,0,2,18,1,6,2, - 22,1,18,1,17,2,19,1,15,1,3,1,17,1,13,2, - 7,1,18,3,16,1,27,1,3,1,16,1,17,1,18,2, - 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,112, - 0,0,0,114,111,0,0,0,114,113,0,0,0,114,114,0, - 0,0,114,197,0,0,0,114,199,0,0,0,114,198,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,114,218,0,0,0,48,3,0,0,115,8, - 0,0,0,12,2,6,2,12,5,12,5,114,218,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,46,0,0,0,101,0,0,90,1,0, - 100,0,0,90,2,0,100,1,0,90,3,0,100,2,0,100, - 3,0,132,0,0,90,4,0,100,4,0,100,5,0,132,0, - 0,90,5,0,100,6,0,83,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,6,0,0,0, - 67,0,0,0,115,76,0,0,0,124,0,0,106,0,0,124, - 1,0,131,1,0,125,2,0,124,0,0,106,1,0,124,2, - 0,131,1,0,125,3,0,116,2,0,124,3,0,100,1,0, - 124,1,0,100,2,0,124,2,0,131,1,2,125,4,0,116, - 3,0,124,4,0,100,1,0,124,1,0,100,3,0,124,2, - 0,131,1,2,83,41,4,78,114,106,0,0,0,114,35,0, - 0,0,114,89,0,0,0,41,4,114,157,0,0,0,114,200, - 0,0,0,114,141,0,0,0,114,147,0,0,0,41,5,114, - 108,0,0,0,114,126,0,0,0,114,35,0,0,0,114,53, - 0,0,0,114,209,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,187,0,0,0,95,3,0,0, - 115,8,0,0,0,0,1,15,1,15,1,24,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,0,83,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,4,0,0,0,41,2,114,108,0, - 0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,202,0,0,0,101,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,112,0,0,0,114, - 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,187, - 0,0,0,114,202,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,223,0,0, - 0,91,3,0,0,115,6,0,0,0,12,2,6,2,12,6, - 114,223,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,130,0,0,0,101, - 0,0,90,1,0,100,0,0,90,2,0,100,1,0,90,3, - 0,100,2,0,100,3,0,132,0,0,90,4,0,100,4,0, - 100,5,0,132,0,0,90,5,0,100,6,0,100,7,0,132, - 0,0,90,6,0,101,7,0,100,8,0,100,9,0,132,0, - 0,131,1,0,90,8,0,100,10,0,100,11,0,132,0,0, - 90,9,0,100,12,0,100,13,0,132,0,0,90,10,0,100, - 14,0,100,15,0,132,0,0,90,11,0,101,7,0,100,16, - 0,100,17,0,132,0,0,131,1,0,90,12,0,100,18,0, - 83,41,19,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,22,0,0, - 0,124,1,0,124,0,0,95,0,0,124,2,0,124,0,0, - 95,1,0,100,0,0,83,41,1,78,41,2,114,106,0,0, - 0,114,35,0,0,0,41,3,114,108,0,0,0,114,106,0, - 0,0,114,35,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,185,0,0,0,118,3,0,0,115, - 4,0,0,0,0,1,9,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,34,0,0,0, - 124,0,0,106,0,0,124,1,0,106,0,0,107,2,0,111, - 33,0,124,0,0,106,1,0,124,1,0,106,1,0,107,2, - 0,83,41,1,78,41,2,114,211,0,0,0,114,118,0,0, - 0,41,2,114,108,0,0,0,114,212,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,5,0,0,0,114,213,0,0, - 0,122,3,0,0,115,4,0,0,0,0,1,18,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, - 26,0,0,0,116,0,0,124,0,0,106,1,0,131,1,0, - 116,0,0,124,0,0,106,2,0,131,1,0,65,83,41,1, - 78,41,3,114,214,0,0,0,114,106,0,0,0,114,35,0, - 0,0,41,1,114,108,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,215,0,0,0,126,3,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,4, - 0,0,0,11,0,0,0,67,0,0,0,115,184,0,0,0, - 116,0,0,106,1,0,124,1,0,131,1,0,143,32,0,1, - 116,0,0,106,2,0,116,3,0,106,4,0,124,1,0,124, - 0,0,106,5,0,131,3,0,125,2,0,87,100,1,0,81, - 82,88,116,6,0,100,2,0,124,0,0,106,5,0,131,2, - 0,1,124,0,0,106,7,0,124,1,0,131,1,0,125,3, - 0,124,3,0,114,128,0,116,8,0,124,2,0,100,3,0, - 131,2,0,12,114,128,0,116,9,0,124,0,0,106,5,0, - 131,1,0,100,4,0,25,103,1,0,124,2,0,95,10,0, - 124,0,0,124,2,0,95,11,0,124,2,0,106,12,0,124, - 2,0,95,13,0,124,3,0,115,180,0,124,2,0,106,13, - 0,106,14,0,100,5,0,131,1,0,100,4,0,25,124,2, - 0,95,13,0,124,2,0,83,41,6,122,25,76,111,97,100, - 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,46,78,122,33,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,32,108,111,97,100,101,100,32, - 102,114,111,109,32,123,33,114,125,218,8,95,95,112,97,116, - 104,95,95,114,59,0,0,0,114,58,0,0,0,41,15,114, - 121,0,0,0,90,13,95,77,97,110,97,103,101,82,101,108, - 111,97,100,114,188,0,0,0,114,145,0,0,0,90,12,108, - 111,97,100,95,100,121,110,97,109,105,99,114,35,0,0,0, - 114,105,0,0,0,114,159,0,0,0,114,115,0,0,0,114, - 38,0,0,0,114,225,0,0,0,218,10,95,95,108,111,97, - 100,101,114,95,95,114,112,0,0,0,218,11,95,95,112,97, - 99,107,97,103,101,95,95,114,32,0,0,0,41,4,114,108, - 0,0,0,114,126,0,0,0,114,190,0,0,0,114,159,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,193,0,0,0,129,3,0,0,115,24,0,0,0,0, - 5,16,1,12,1,22,1,16,1,15,1,22,1,25,1,9, - 1,12,1,6,1,25,1,122,31,69,120,116,101,110,115,105, - 111,110,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,4,0,0,0,3,0,0,0,115,48,0, - 0,0,116,0,0,124,0,0,106,1,0,131,1,0,100,1, - 0,25,137,0,0,116,2,0,135,0,0,102,1,0,100,2, - 0,100,3,0,134,0,0,116,3,0,68,131,1,0,131,1, - 0,83,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,31,0,0,0,124,0,0,93,21,0,125,1,0,136, - 0,0,100,0,0,124,1,0,23,107,2,0,86,1,113,3, - 0,100,1,0,83,41,2,114,185,0,0,0,78,114,4,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,4, - 0,0,0,114,5,0,0,0,250,9,60,103,101,110,101,120, - 112,114,62,150,3,0,0,115,2,0,0,0,6,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,108,0,0,0,114,126,0, - 0,0,114,4,0,0,0,41,1,114,229,0,0,0,114,5, - 0,0,0,114,159,0,0,0,147,3,0,0,115,6,0,0, - 0,0,2,19,1,18,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,0,83,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,4,0,0,0,41,2, - 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,187,0,0,0,153,3, - 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,0,83,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, - 4,0,0,0,41,2,114,108,0,0,0,114,126,0,0,0, + 5,0,0,0,114,223,0,0,0,92,3,0,0,115,6,0, + 0,0,12,2,6,2,12,6,114,223,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,136,0,0,0,101,0,0,90,1,0,100,0,0, + 90,2,0,100,1,0,90,3,0,100,2,0,100,3,0,132, + 0,0,90,4,0,100,4,0,100,5,0,132,0,0,90,5, + 0,100,6,0,100,7,0,132,0,0,90,6,0,100,8,0, + 100,9,0,132,0,0,90,7,0,100,10,0,100,11,0,132, + 0,0,90,8,0,100,12,0,100,13,0,132,0,0,90,9, + 0,100,14,0,100,15,0,132,0,0,90,10,0,100,16,0, + 100,17,0,132,0,0,90,11,0,101,12,0,100,18,0,100, + 19,0,132,0,0,131,1,0,90,13,0,100,20,0,83,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,22,0,0,0,124, + 1,0,124,0,0,95,0,0,124,2,0,124,0,0,95,1, + 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, + 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, + 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,185,0,0,0,119,3,0,0,115,4,0, + 0,0,0,1,9,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,34,0,0,0,124,0, + 0,106,0,0,124,1,0,106,0,0,107,2,0,111,33,0, + 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, + 41,1,78,41,2,114,211,0,0,0,114,118,0,0,0,41, + 2,114,108,0,0,0,114,212,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,123, + 3,0,0,115,4,0,0,0,0,1,18,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,26,0, + 0,0,116,0,0,124,0,0,106,1,0,131,1,0,116,0, + 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, + 3,114,214,0,0,0,114,106,0,0,0,114,35,0,0,0, + 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,5,0,0,0,114,215,0,0,0,127,3,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,4,0,0,0,67,0,0,0,115,47,0,0,0,116,0, + 0,106,1,0,116,2,0,106,3,0,124,1,0,131,2,0, + 125,2,0,116,4,0,100,1,0,124,1,0,106,5,0,124, + 0,0,106,6,0,131,3,0,1,124,2,0,83,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,121,0,0,0,114,188,0,0,0,114,145,0,0,0, + 90,14,99,114,101,97,116,101,95,100,121,110,97,109,105,99, + 114,105,0,0,0,114,106,0,0,0,114,35,0,0,0,41, + 3,114,108,0,0,0,114,164,0,0,0,114,190,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 202,0,0,0,157,3,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,7,0,0,0,124,0,0,106,0,0,83, - 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,108,0,0,0,114,126,0,0, - 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,157,0,0,0,161,3,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,13,114,112,0,0,0,114,111,0,0,0,114, - 113,0,0,0,114,114,0,0,0,114,185,0,0,0,114,213, - 0,0,0,114,215,0,0,0,114,123,0,0,0,114,193,0, - 0,0,114,159,0,0,0,114,187,0,0,0,114,202,0,0, - 0,114,157,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,224,0,0,0,110, - 3,0,0,115,18,0,0,0,12,6,6,2,12,4,12,4, - 12,3,18,18,12,6,12,4,12,4,114,224,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,130,0,0,0,101,0,0,90,1,0,100, - 0,0,90,2,0,100,1,0,90,3,0,100,2,0,100,3, - 0,132,0,0,90,4,0,100,4,0,100,5,0,132,0,0, - 90,5,0,100,6,0,100,7,0,132,0,0,90,6,0,100, - 8,0,100,9,0,132,0,0,90,7,0,100,10,0,100,11, - 0,132,0,0,90,8,0,100,12,0,100,13,0,132,0,0, - 90,9,0,100,14,0,100,15,0,132,0,0,90,10,0,100, - 16,0,100,17,0,132,0,0,90,11,0,100,18,0,100,19, - 0,132,0,0,90,12,0,100,20,0,83,41,21,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,2,0,0,0,67,0,0,0,115,52,0, - 0,0,124,1,0,124,0,0,95,0,0,124,2,0,124,0, - 0,95,1,0,116,2,0,124,0,0,106,3,0,131,0,0, - 131,1,0,124,0,0,95,4,0,124,3,0,124,0,0,95, - 5,0,100,0,0,83,41,1,78,41,6,218,5,95,110,97, - 109,101,218,5,95,112,97,116,104,114,93,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,108,0,0,0,114,106,0,0,0,114,35,0, - 0,0,218,11,112,97,116,104,95,102,105,110,100,101,114,114, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,185, - 0,0,0,174,3,0,0,115,8,0,0,0,0,1,9,1, - 9,1,21,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,53,0,0,0,124,0,0,106,0,0,106,1,0, - 100,1,0,131,1,0,92,3,0,125,1,0,125,2,0,125, - 3,0,124,2,0,100,2,0,107,2,0,114,43,0,100,6, - 0,83,124,1,0,100,5,0,102,2,0,83,41,7,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,58, - 0,0,0,114,30,0,0,0,114,7,0,0,0,114,35,0, - 0,0,114,225,0,0,0,41,2,122,3,115,121,115,122,4, - 112,97,116,104,41,2,114,234,0,0,0,114,32,0,0,0, + 186,0,0,0,130,3,0,0,115,10,0,0,0,0,2,6, + 1,15,1,6,1,16,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,4,0,0,0,67,0,0,0,115, + 45,0,0,0,116,0,0,106,1,0,116,2,0,106,3,0, + 124,1,0,131,2,0,1,116,4,0,100,1,0,124,0,0, + 106,5,0,124,0,0,106,6,0,131,3,0,1,100,2,0, + 83,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,121,0,0,0,114,188,0,0,0,114,145,0,0,0,90, + 12,101,120,101,99,95,100,121,110,97,109,105,99,114,105,0, + 0,0,114,106,0,0,0,114,35,0,0,0,41,2,114,108, + 0,0,0,114,190,0,0,0,114,4,0,0,0,114,4,0, + 0,0,114,5,0,0,0,114,191,0,0,0,138,3,0,0, + 115,6,0,0,0,0,2,19,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,48,0,0,0,116,0,0,124,0,0,106,1,0,131, + 1,0,100,1,0,25,137,0,0,116,2,0,135,0,0,102, + 1,0,100,2,0,100,3,0,134,0,0,116,3,0,68,131, + 1,0,131,1,0,83,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,31,0,0,0,124,0,0,93,21,0, + 125,1,0,136,0,0,100,0,0,124,1,0,23,107,2,0, + 86,1,113,3,0,100,1,0,83,41,2,114,185,0,0,0, + 78,114,4,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,4,0,0,0,114,5,0,0,0,250,9,60,103, + 101,110,101,120,112,114,62,147,3,0,0,115,2,0,0,0, + 6,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,108,0,0, + 0,114,126,0,0,0,114,4,0,0,0,41,1,114,226,0, + 0,0,114,5,0,0,0,114,159,0,0,0,144,3,0,0, + 115,6,0,0,0,0,2,19,1,18,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,0,83,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,4,0, + 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,187,0, + 0,0,150,3,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,0,83,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,4,0,0,0,41,2,114,108,0,0,0,114, + 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,202,0,0,0,154,3,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,7,0,0,0,124,0,0, + 106,0,0,83,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,108,0,0,0, + 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,157,0,0,0,158,3,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,112,0,0,0,114,111, + 0,0,0,114,113,0,0,0,114,114,0,0,0,114,185,0, + 0,0,114,213,0,0,0,114,215,0,0,0,114,186,0,0, + 0,114,191,0,0,0,114,159,0,0,0,114,187,0,0,0, + 114,202,0,0,0,114,123,0,0,0,114,157,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,224,0,0,0,111,3,0,0,115,20,0,0, + 0,12,6,6,2,12,4,12,4,12,3,12,8,12,6,12, + 6,12,4,12,4,114,224,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, + 130,0,0,0,101,0,0,90,1,0,100,0,0,90,2,0, + 100,1,0,90,3,0,100,2,0,100,3,0,132,0,0,90, + 4,0,100,4,0,100,5,0,132,0,0,90,5,0,100,6, + 0,100,7,0,132,0,0,90,6,0,100,8,0,100,9,0, + 132,0,0,90,7,0,100,10,0,100,11,0,132,0,0,90, + 8,0,100,12,0,100,13,0,132,0,0,90,9,0,100,14, + 0,100,15,0,132,0,0,90,10,0,100,16,0,100,17,0, + 132,0,0,90,11,0,100,18,0,100,19,0,132,0,0,90, + 12,0,100,20,0,83,41,21,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, + 2,0,0,0,67,0,0,0,115,52,0,0,0,124,1,0, + 124,0,0,95,0,0,124,2,0,124,0,0,95,1,0,116, + 2,0,124,0,0,106,3,0,131,0,0,131,1,0,124,0, + 0,95,4,0,124,3,0,124,0,0,95,5,0,100,0,0, + 83,41,1,78,41,6,218,5,95,110,97,109,101,218,5,95, + 112,97,116,104,114,93,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,108, + 0,0,0,114,106,0,0,0,114,35,0,0,0,218,11,112, + 97,116,104,95,102,105,110,100,101,114,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,185,0,0,0,171,3, + 0,0,115,8,0,0,0,0,1,9,1,9,1,21,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,53,0, + 0,0,124,0,0,106,0,0,106,1,0,100,1,0,131,1, + 0,92,3,0,125,1,0,125,2,0,125,3,0,124,2,0, + 100,2,0,107,2,0,114,43,0,100,6,0,83,124,1,0, + 100,5,0,102,2,0,83,41,7,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,58,0,0,0,114,30, + 0,0,0,114,7,0,0,0,114,35,0,0,0,90,8,95, + 95,112,97,116,104,95,95,41,2,122,3,115,121,115,122,4, + 112,97,116,104,41,2,114,231,0,0,0,114,32,0,0,0, 41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111, 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,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,180,3,0, + 110,116,95,112,97,116,104,95,110,97,109,101,115,177,3,0, 0,115,8,0,0,0,0,2,27,1,12,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, @@ -1712,13 +1718,13 @@ 0,0,0,3,0,0,0,67,0,0,0,115,38,0,0,0, 124,0,0,106,0,0,131,0,0,92,2,0,125,1,0,125, 2,0,116,1,0,116,2,0,106,3,0,124,1,0,25,124, - 2,0,131,2,0,83,41,1,78,41,4,114,241,0,0,0, + 2,0,131,2,0,83,41,1,78,41,4,114,238,0,0,0, 114,117,0,0,0,114,7,0,0,0,218,7,109,111,100,117, 108,101,115,41,3,114,108,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,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,236,0, - 0,0,190,3,0,0,115,4,0,0,0,0,1,18,1,122, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,233,0, + 0,0,187,3,0,0,115,4,0,0,0,0,1,18,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,3,0,0, @@ -1730,65 +1736,65 @@ 5,0,100,0,0,107,8,0,114,102,0,124,2,0,106,6, 0,114,102,0,124,2,0,106,6,0,124,0,0,95,7,0, 124,1,0,124,0,0,95,2,0,124,0,0,106,7,0,83, - 41,1,78,41,8,114,93,0,0,0,114,236,0,0,0,114, - 237,0,0,0,114,238,0,0,0,114,234,0,0,0,114,127, - 0,0,0,114,156,0,0,0,114,235,0,0,0,41,3,114, + 41,1,78,41,8,114,93,0,0,0,114,233,0,0,0,114, + 234,0,0,0,114,235,0,0,0,114,231,0,0,0,114,127, + 0,0,0,114,156,0,0,0,114,232,0,0,0,41,3,114, 108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, 104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108, - 97,116,101,194,3,0,0,115,16,0,0,0,0,2,18,1, + 97,116,101,191,3,0,0,115,16,0,0,0,0,2,18,1, 15,1,21,3,27,1,9,1,12,1,9,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,2,0,0,0,67,0,0,0,115,16, 0,0,0,116,0,0,124,0,0,106,1,0,131,0,0,131, - 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,243, + 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,240, 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101, - 114,95,95,207,3,0,0,115,2,0,0,0,0,1,122,23, + 114,95,95,204,3,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,1,0,0,0,0,0,0,0, 1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0, 0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0, - 83,41,1,78,41,2,114,31,0,0,0,114,243,0,0,0, + 83,41,1,78,41,2,114,31,0,0,0,114,240,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,210, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,207, 3,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,2, 0,0,0,67,0,0,0,115,16,0,0,0,100,1,0,106, 0,0,124,0,0,106,1,0,131,1,0,83,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,47,0,0,0,114,235,0,0, + 123,33,114,125,41,41,2,114,47,0,0,0,114,232,0,0, 0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95, - 95,213,3,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,210,3,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,2,0,0,0,67,0,0,0,115,16,0,0,0,124, 1,0,124,0,0,106,0,0,131,0,0,107,6,0,83,41, - 1,78,41,1,114,243,0,0,0,41,2,114,108,0,0,0, + 1,78,41,1,114,240,0,0,0,41,2,114,108,0,0,0, 218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110, - 115,95,95,216,3,0,0,115,2,0,0,0,0,1,122,27, + 115,95,95,213,3,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,2,0,0,0,67,0,0,0, 115,20,0,0,0,124,0,0,106,0,0,106,1,0,124,1, - 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,235, + 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,232, 0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114, - 248,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,163,0,0,0,219,3,0,0,115,2,0,0, + 245,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, + 0,0,0,114,163,0,0,0,216,3,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,13,114,112,0, 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, - 0,114,185,0,0,0,114,241,0,0,0,114,236,0,0,0, - 114,243,0,0,0,114,245,0,0,0,114,246,0,0,0,114, - 247,0,0,0,114,249,0,0,0,114,163,0,0,0,114,4, + 0,114,185,0,0,0,114,238,0,0,0,114,233,0,0,0, + 114,240,0,0,0,114,242,0,0,0,114,243,0,0,0,114, + 244,0,0,0,114,246,0,0,0,114,163,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,233,0,0,0,167,3,0,0,115,20,0,0,0, + 0,0,114,230,0,0,0,164,3,0,0,115,20,0,0,0, 12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3, - 12,3,12,3,114,233,0,0,0,99,0,0,0,0,0,0, + 12,3,12,3,114,230,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,118, 0,0,0,101,0,0,90,1,0,100,0,0,90,2,0,100, 1,0,100,2,0,132,0,0,90,3,0,101,4,0,100,3, @@ -1802,10 +1808,10 @@ 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, 0,0,115,25,0,0,0,116,0,0,124,1,0,124,2,0, 124,3,0,131,3,0,124,0,0,95,1,0,100,0,0,83, - 41,1,78,41,2,114,233,0,0,0,114,235,0,0,0,41, + 41,1,78,41,2,114,230,0,0,0,114,232,0,0,0,41, 4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0, - 114,239,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,225,3,0,0,115,2,0, + 114,236,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,114,185,0,0,0,222,3,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,2,0,0,0, @@ -1822,14 +1828,14 @@ 110,97,109,101,115,112,97,99,101,41,62,41,2,114,47,0, 0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,228, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,225, 3,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,0,83,41,2,78,84,114,4,0,0,0,41, 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,237, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,234, 3,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, @@ -1837,7 +1843,7 @@ 0,100,1,0,83,41,2,78,114,30,0,0,0,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0, - 0,0,240,3,0,0,115,2,0,0,0,0,1,122,27,95, + 0,0,237,3,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, @@ -1846,7 +1852,7 @@ 0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0, 0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2, 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,187,0,0,0,243,3, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,240,3, 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, @@ -1856,14 +1862,14 @@ 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, 78,114,4,0,0,0,41,2,114,108,0,0,0,114,164,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,186,0,0,0,246,3,0,0,115,0,0,0,0,122, + 0,114,186,0,0,0,243,3,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,0,83,41,1,78, 114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,191,0,0,0,249,3,0,0,115,2,0,0,0,0,1, + 114,191,0,0,0,246,3,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,3,0,0,0,67, @@ -1878,20 +1884,20 @@ 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,105,0,0,0,114,235,0, + 104,32,123,33,114,125,41,4,114,105,0,0,0,114,232,0, 0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108, 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,193,0,0,0,252,3,0,0, + 0,0,114,5,0,0,0,114,193,0,0,0,249,3,0,0, 115,4,0,0,0,0,7,16,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,112,0,0,0,114, 111,0,0,0,114,113,0,0,0,114,185,0,0,0,114,183, - 0,0,0,114,251,0,0,0,114,159,0,0,0,114,202,0, + 0,0,0,114,248,0,0,0,114,159,0,0,0,114,202,0, 0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0, 0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,250,0,0,0,224, + 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,221, 3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3, - 12,3,12,3,12,3,12,3,114,250,0,0,0,99,0,0, + 12,3,12,3,12,3,12,3,114,247,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0, 0,0,115,160,0,0,0,101,0,0,90,1,0,100,0,0, 90,2,0,100,1,0,90,3,0,101,4,0,100,2,0,100, @@ -1925,9 +1931,9 @@ 97,116,101,95,99,97,99,104,101,115,78,41,5,114,7,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, - 115,0,0,0,114,253,0,0,0,41,2,114,170,0,0,0, + 115,0,0,0,114,250,0,0,0,41,2,114,170,0,0,0, 218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,253,0,0,0,13,4,0,0, + 0,0,114,5,0,0,0,114,250,0,0,0,10,4,0,0, 115,6,0,0,0,0,4,22,1,15,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, @@ -1953,7 +1959,7 @@ 107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0, 90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111, - 107,115,21,4,0,0,115,16,0,0,0,0,7,25,1,16, + 107,115,18,4,0,0,115,16,0,0,0,0,7,25,1,16, 1,16,1,3,1,14,1,13,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, @@ -1981,11 +1987,11 @@ 111,110,101,46,10,10,32,32,32,32,32,32,32,32,114,30, 0,0,0,78,41,7,114,3,0,0,0,114,45,0,0,0, 218,17,70,105,108,101,78,111,116,70,111,117,110,100,69,114, - 114,111,114,114,7,0,0,0,114,254,0,0,0,114,137,0, - 0,0,114,2,1,0,0,41,3,114,170,0,0,0,114,35, - 0,0,0,114,0,1,0,0,114,4,0,0,0,114,4,0, + 114,111,114,114,7,0,0,0,114,251,0,0,0,114,137,0, + 0,0,114,255,0,0,0,41,3,114,170,0,0,0,114,35, + 0,0,0,114,253,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,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,38,4,0, + 109,112,111,114,116,101,114,95,99,97,99,104,101,35,4,0, 0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3, 9,1,3,1,17,1,13,1,15,1,18,1,122,31,80,97, 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, @@ -2002,10 +2008,10 @@ 78,114,124,0,0,0,41,7,114,115,0,0,0,114,124,0, 0,0,114,182,0,0,0,114,121,0,0,0,114,179,0,0, 0,114,160,0,0,0,114,156,0,0,0,41,6,114,170,0, - 0,0,114,126,0,0,0,114,0,1,0,0,114,127,0,0, + 0,0,114,126,0,0,0,114,253,0,0,0,114,127,0,0, 0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,60,4,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,57,4,0,0, 115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12, 1,16,1,18,1,9,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, @@ -2033,15 +2039,15 @@ 110,97,109,101,46,78,114,181,0,0,0,122,19,115,112,101, 99,32,109,105,115,115,105,110,103,32,108,111,97,100,101,114, 41,13,114,143,0,0,0,114,69,0,0,0,218,5,98,121, - 116,101,115,114,4,1,0,0,114,115,0,0,0,114,181,0, - 0,0,114,5,1,0,0,114,127,0,0,0,114,156,0,0, + 116,101,115,114,1,1,0,0,114,115,0,0,0,114,181,0, + 0,0,114,2,1,0,0,114,127,0,0,0,114,156,0,0, 0,114,107,0,0,0,114,149,0,0,0,114,121,0,0,0, 114,160,0,0,0,41,9,114,170,0,0,0,114,126,0,0, 0,114,35,0,0,0,114,180,0,0,0,218,14,110,97,109, 101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116, - 114,121,114,0,1,0,0,114,164,0,0,0,114,128,0,0, + 114,121,114,253,0,0,0,114,164,0,0,0,114,128,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,95,103,101,116,95,115,112,101,99,75,4,0,0,115, + 218,9,95,103,101,116,95,115,112,101,99,72,4,0,0,115, 40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1, 12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1, 9,1,12,1,12,5,17,2,18,1,9,1,122,20,80,97, @@ -2064,12 +2070,12 @@ 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,78,90, 9,110,97,109,101,115,112,97,99,101,41,7,114,7,0,0, - 0,114,35,0,0,0,114,8,1,0,0,114,127,0,0,0, - 114,156,0,0,0,114,158,0,0,0,114,233,0,0,0,41, + 0,114,35,0,0,0,114,5,1,0,0,114,127,0,0,0, + 114,156,0,0,0,114,158,0,0,0,114,230,0,0,0,41, 6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0, - 114,180,0,0,0,114,164,0,0,0,114,7,1,0,0,114, + 114,180,0,0,0,114,164,0,0,0,114,4,1,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181, - 0,0,0,107,4,0,0,115,26,0,0,0,0,4,12,1, + 0,0,0,104,4,0,0,115,26,0,0,0,0,4,12,1, 9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1, 24,1,4,2,7,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, @@ -2091,17 +2097,17 @@ 114,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 182,0,0,0,129,4,0,0,115,8,0,0,0,0,8,18, + 182,0,0,0,126,4,0,0,115,8,0,0,0,0,8,18, 1,12,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,12,114, 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, - 0,0,0,114,183,0,0,0,114,253,0,0,0,114,2,1, - 0,0,114,4,1,0,0,114,5,1,0,0,114,8,1,0, + 0,0,0,114,183,0,0,0,114,250,0,0,0,114,255,0, + 0,0,114,1,1,0,0,114,2,1,0,0,114,5,1,0, 0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 252,0,0,0,9,4,0,0,115,22,0,0,0,12,2,6, + 249,0,0,0,6,4,0,0,115,22,0,0,0,12,2,6, 2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21, - 21,3,1,114,252,0,0,0,99,0,0,0,0,0,0,0, + 21,3,1,114,249,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,133,0, 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, 0,90,3,0,100,2,0,100,3,0,132,0,0,90,4,0, @@ -2146,9 +2152,9 @@ 0,0,3,0,0,0,51,0,0,0,115,27,0,0,0,124, 0,0,93,17,0,125,1,0,124,1,0,136,0,0,102,2, 0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0, - 0,0,41,2,114,22,0,0,0,114,228,0,0,0,41,1, + 0,0,41,2,114,22,0,0,0,114,225,0,0,0,41,1, 114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 230,0,0,0,158,4,0,0,115,2,0,0,0,6,0,122, + 227,0,0,0,155,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0, @@ -2161,7 +2167,7 @@ 111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108, 111,97,100,101,114,115,114,166,0,0,0,114,4,0,0,0, 41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0, - 0,152,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 0,149,4,0,0,115,16,0,0,0,0,4,6,1,19,1, 36,1,9,2,15,1,9,1,12,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, @@ -2169,9 +2175,9 @@ 0,0,100,2,0,83,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,29,0,0,0,78,114, - 87,0,0,0,41,1,114,11,1,0,0,41,1,114,108,0, + 87,0,0,0,41,1,114,8,1,0,0,41,1,114,108,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,253,0,0,0,166,4,0,0,115,2,0,0,0,0, + 0,114,250,0,0,0,163,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, @@ -2195,7 +2201,7 @@ 114,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41, 3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 124,0,0,0,172,4,0,0,115,8,0,0,0,0,7,15, + 124,0,0,0,169,4,0,0,115,8,0,0,0,0,7,15, 1,12,1,10,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,7,0,0,0,67,0, @@ -2206,7 +2212,7 @@ 0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114, 126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, 180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,8,1,0,0,184,4,0, + 0,0,0,114,5,0,0,0,114,5,1,0,0,181,4,0, 0,115,6,0,0,0,0,1,15,1,18,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, @@ -2256,21 +2262,21 @@ 99,101,32,102,111,114,32,123,125,114,87,0,0,0,41,23, 114,32,0,0,0,114,39,0,0,0,114,35,0,0,0,114, 3,0,0,0,114,45,0,0,0,114,219,0,0,0,114,40, - 0,0,0,114,11,1,0,0,218,11,95,102,105,108,108,95, - 99,97,99,104,101,114,6,0,0,0,114,14,1,0,0,114, - 88,0,0,0,114,13,1,0,0,114,28,0,0,0,114,10, - 1,0,0,114,44,0,0,0,114,8,1,0,0,114,46,0, + 0,0,0,114,8,1,0,0,218,11,95,102,105,108,108,95, + 99,97,99,104,101,114,6,0,0,0,114,11,1,0,0,114, + 88,0,0,0,114,10,1,0,0,114,28,0,0,0,114,7, + 1,0,0,114,44,0,0,0,114,5,1,0,0,114,46,0, 0,0,114,105,0,0,0,114,47,0,0,0,114,121,0,0, 0,114,160,0,0,0,114,156,0,0,0,41,14,114,108,0, 0,0,114,126,0,0,0,114,180,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,133,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,228,0,0, + 101,90,9,98,97,115,101,95,112,97,116,104,114,225,0,0, 0,114,165,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,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,181,0,0,0,189,4,0,0,115,68,0, + 5,0,0,0,114,181,0,0,0,186,4,0,0,115,68,0, 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1, 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2, 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2, @@ -2307,24 +2313,24 @@ 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22, 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112, - 62,7,5,0,0,115,2,0,0,0,9,0,122,41,70,105, + 62,4,5,0,0,115,2,0,0,0,9,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, 3,0,0,0,90,7,108,105,115,116,100,105,114,114,45,0, - 0,0,114,3,1,0,0,218,15,80,101,114,109,105,115,115, + 0,0,114,0,1,0,0,218,15,80,101,114,109,105,115,115, 105,111,110,69,114,114,111,114,218,18,78,111,116,65,68,105, 114,101,99,116,111,114,121,69,114,114,111,114,114,7,0,0, - 0,114,8,0,0,0,114,9,0,0,0,114,12,1,0,0, - 114,13,1,0,0,114,83,0,0,0,114,47,0,0,0,114, - 88,0,0,0,218,3,97,100,100,114,10,0,0,0,114,14, + 0,114,8,0,0,0,114,9,0,0,0,114,9,1,0,0, + 114,10,1,0,0,114,83,0,0,0,114,47,0,0,0,114, + 88,0,0,0,218,3,97,100,100,114,10,0,0,0,114,11, 1,0,0,41,9,114,108,0,0,0,114,35,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,248,0,0,0,114,106,0,0,0,114,240,0,0,0,114, - 228,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,114,16,1, - 0,0,234,4,0,0,115,34,0,0,0,0,2,9,1,3, + 114,245,0,0,0,114,106,0,0,0,114,237,0,0,0,114, + 225,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, + 0,0,0,114,4,0,0,0,114,5,0,0,0,114,13,1, + 0,0,231,4,0,0,115,34,0,0,0,0,2,9,1,3, 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24, 1,6,1,27,2,6,1,17,1,9,1,18,1,122,22,70, 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, @@ -2360,17 +2366,17 @@ 100,105,114,101,99,116,111,114,105,101,115,32,97,114,101,32, 115,117,112,112,111,114,116,101,100,114,35,0,0,0,41,2, 114,46,0,0,0,114,107,0,0,0,41,1,114,35,0,0, - 0,41,2,114,170,0,0,0,114,15,1,0,0,114,4,0, + 0,41,2,114,170,0,0,0,114,12,1,0,0,114,4,0, 0,0,114,5,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,19,5,0,0,115,6,0,0,0,0,2,12,1,18,1, + 114,16,5,0,0,115,6,0,0,0,0,2,12,1,18,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, - 170,0,0,0,114,15,1,0,0,114,21,1,0,0,114,4, - 0,0,0,41,2,114,170,0,0,0,114,15,1,0,0,114, - 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,9, + 170,0,0,0,114,12,1,0,0,114,18,1,0,0,114,4, + 0,0,0,41,2,114,170,0,0,0,114,12,1,0,0,114, + 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,6, 5,0,0,115,4,0,0,0,0,10,21,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, @@ -2379,17 +2385,17 @@ 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114, 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,247,0,0,0,27,5,0,0,115,2,0,0, + 0,0,0,114,244,0,0,0,24,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,15,114,112,0,0,0,114, 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185, - 0,0,0,114,253,0,0,0,114,130,0,0,0,114,182,0, - 0,0,114,124,0,0,0,114,8,1,0,0,114,181,0,0, - 0,114,16,1,0,0,114,183,0,0,0,114,22,1,0,0, - 114,247,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,9,1,0,0,143,4, + 0,0,0,114,250,0,0,0,114,130,0,0,0,114,182,0, + 0,0,114,124,0,0,0,114,5,1,0,0,114,181,0,0, + 0,114,13,1,0,0,114,183,0,0,0,114,19,1,0,0, + 114,244,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,5,0,0,0,114,6,1,0,0,140,4, 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6, - 2,12,12,12,5,15,45,12,31,18,18,114,9,1,0,0, + 2,12,12,12,5,15,45,12,31,18,18,114,6,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,195,0,0,0,124,0,0,106,0,0, 100,1,0,131,1,0,125,4,0,124,0,0,106,0,0,100, @@ -2404,187 +2410,187 @@ 2,0,124,0,0,100,4,0,60,124,3,0,124,0,0,100, 5,0,60,87,110,18,0,4,116,5,0,107,10,0,114,190, 0,1,1,1,89,110,1,0,88,100,0,0,83,41,6,78, - 114,226,0,0,0,218,8,95,95,115,112,101,99,95,95,114, - 127,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,127,0,0,0,114,223,0,0,0,114,218,0,0,0, - 114,167,0,0,0,218,9,69,120,99,101,112,116,105,111,110, - 41,6,90,2,110,115,114,106,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,127,0,0,0,114,164,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,218,14,95,102,105,120,95, - 117,112,95,109,111,100,117,108,101,33,5,0,0,115,34,0, - 0,0,0,2,15,1,15,1,6,1,6,1,12,1,12,1, - 18,2,15,1,6,1,21,1,3,1,10,1,10,1,10,1, - 14,1,13,2,114,26,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,55, - 0,0,0,116,0,0,116,1,0,106,2,0,131,0,0,102, - 2,0,125,0,0,116,3,0,116,4,0,102,2,0,125,1, - 0,116,5,0,116,6,0,102,2,0,125,2,0,124,0,0, - 124,1,0,124,2,0,103,3,0,83,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, - 224,0,0,0,114,145,0,0,0,218,18,101,120,116,101,110, - 115,105,111,110,95,115,117,102,102,105,120,101,115,114,218,0, - 0,0,114,84,0,0,0,114,223,0,0,0,114,74,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,5,0,0,0, - 114,161,0,0,0,56,5,0,0,115,8,0,0,0,0,5, - 18,1,12,1,12,1,114,161,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,70,2,0,0,124,0,0,97,0,0,116,0,0,106,1, - 0,97,1,0,116,0,0,106,2,0,97,2,0,116,1,0, - 106,3,0,116,4,0,25,125,1,0,120,76,0,100,26,0, - 68,93,68,0,125,2,0,124,2,0,116,1,0,106,3,0, - 107,7,0,114,83,0,116,0,0,106,5,0,124,2,0,131, - 1,0,125,3,0,110,13,0,116,1,0,106,3,0,124,2, - 0,25,125,3,0,116,6,0,124,1,0,124,2,0,124,3, - 0,131,3,0,1,113,44,0,87,100,5,0,100,6,0,103, - 1,0,102,2,0,100,7,0,100,8,0,100,6,0,103,2, - 0,102,2,0,102,2,0,125,4,0,120,149,0,124,4,0, - 68,93,129,0,92,2,0,125,5,0,125,6,0,116,7,0, - 100,9,0,100,10,0,132,0,0,124,6,0,68,131,1,0, - 131,1,0,115,199,0,116,8,0,130,1,0,124,6,0,100, - 11,0,25,125,7,0,124,5,0,116,1,0,106,3,0,107, - 6,0,114,241,0,116,1,0,106,3,0,124,5,0,25,125, - 8,0,80,113,156,0,121,20,0,116,0,0,106,5,0,124, - 5,0,131,1,0,125,8,0,80,87,113,156,0,4,116,9, - 0,107,10,0,114,28,1,1,1,1,119,156,0,89,113,156, - 0,88,113,156,0,87,116,9,0,100,12,0,131,1,0,130, - 1,0,116,6,0,124,1,0,100,13,0,124,8,0,131,3, - 0,1,116,6,0,124,1,0,100,14,0,124,7,0,131,3, - 0,1,116,6,0,124,1,0,100,15,0,100,16,0,106,10, - 0,124,6,0,131,1,0,131,3,0,1,121,19,0,116,0, - 0,106,5,0,100,17,0,131,1,0,125,9,0,87,110,24, - 0,4,116,9,0,107,10,0,114,147,1,1,1,1,100,18, - 0,125,9,0,89,110,1,0,88,116,6,0,124,1,0,100, - 17,0,124,9,0,131,3,0,1,116,0,0,106,5,0,100, - 19,0,131,1,0,125,10,0,116,6,0,124,1,0,100,19, - 0,124,10,0,131,3,0,1,124,5,0,100,7,0,107,2, - 0,114,238,1,116,0,0,106,5,0,100,20,0,131,1,0, - 125,11,0,116,6,0,124,1,0,100,21,0,124,11,0,131, - 3,0,1,116,6,0,124,1,0,100,22,0,116,11,0,131, - 0,0,131,3,0,1,116,12,0,106,13,0,116,2,0,106, - 14,0,131,0,0,131,1,0,1,124,5,0,100,7,0,107, - 2,0,114,66,2,116,15,0,106,16,0,100,23,0,131,1, - 0,1,100,24,0,116,12,0,107,6,0,114,66,2,100,25, - 0,116,17,0,95,18,0,100,18,0,83,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,49,0,0, - 0,114,60,0,0,0,218,8,98,117,105,108,116,105,110,115, - 114,142,0,0,0,90,5,112,111,115,105,120,250,1,47,218, - 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,33,0,0,0, - 124,0,0,93,23,0,125,1,0,116,0,0,124,1,0,131, - 1,0,100,0,0,107,2,0,86,1,113,3,0,100,1,0, - 83,41,2,114,29,0,0,0,78,41,1,114,31,0,0,0, - 41,2,114,22,0,0,0,114,77,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,5,0,0,0,114,230,0,0,0, - 92,5,0,0,115,2,0,0,0,6,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,59,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,25,0,0,0,114,21,0,0,0,114,30,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,169,0,0,0, - 114,6,0,0,0,122,4,46,112,121,119,122,6,95,100,46, - 112,121,100,84,41,4,122,3,95,105,111,122,9,95,119,97, - 114,110,105,110,103,115,122,8,98,117,105,108,116,105,110,115, - 122,7,109,97,114,115,104,97,108,41,19,114,121,0,0,0, - 114,7,0,0,0,114,145,0,0,0,114,242,0,0,0,114, - 112,0,0,0,90,18,95,98,117,105,108,116,105,110,95,102, - 114,111,109,95,110,97,109,101,114,116,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,107,0,0,0,114,26,0,0,0,114,11,0,0, - 0,114,232,0,0,0,114,149,0,0,0,114,27,1,0,0, - 114,84,0,0,0,114,163,0,0,0,114,168,0,0,0,114, - 173,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, - 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,6, - 95,115,101,116,117,112,67,5,0,0,115,82,0,0,0,0, - 8,6,1,9,1,9,3,13,1,13,1,15,1,18,2,13, - 1,20,3,33,1,19,2,31,1,10,1,15,1,13,1,4, - 2,3,1,15,1,5,1,13,1,12,2,12,1,16,1,16, - 1,25,3,3,1,19,1,13,2,11,1,16,3,15,1,16, - 3,12,1,15,1,16,3,19,1,19,1,12,1,13,1,12, - 1,114,35,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,116,0,0,0, - 116,0,0,124,0,0,131,1,0,1,116,1,0,131,0,0, - 125,1,0,116,2,0,106,3,0,106,4,0,116,5,0,106, - 6,0,124,1,0,140,0,0,103,1,0,131,1,0,1,116, - 7,0,106,8,0,100,1,0,107,2,0,114,78,0,116,2, - 0,106,9,0,106,10,0,116,11,0,131,1,0,1,116,2, - 0,106,9,0,106,10,0,116,12,0,131,1,0,1,116,5, - 0,124,0,0,95,5,0,116,13,0,124,0,0,95,13,0, - 100,2,0,83,41,3,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,114,30,1,0,0,78,41,14,114,35,1,0,0,114,161, - 0,0,0,114,7,0,0,0,114,1,1,0,0,114,149,0, - 0,0,114,9,1,0,0,114,22,1,0,0,114,3,0,0, - 0,114,112,0,0,0,218,9,109,101,116,97,95,112,97,116, - 104,114,163,0,0,0,114,168,0,0,0,114,252,0,0,0, - 114,218,0,0,0,41,2,114,34,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,5,0,0,0,218,8, - 95,105,110,115,116,97,108,108,135,5,0,0,115,16,0,0, - 0,0,2,10,1,9,1,28,1,15,1,16,1,16,4,9, - 1,114,37,1,0,0,41,3,122,3,119,105,110,114,1,0, - 0,0,114,2,0,0,0,41,57,114,114,0,0,0,114,10, - 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,55,0,0,0,218,4,116,121,112,101,218,8,95,95,99, - 111,100,101,95,95,114,144,0,0,0,114,15,0,0,0,114, - 135,0,0,0,114,14,0,0,0,114,18,0,0,0,90,17, - 95,82,65,87,95,77,65,71,73,67,95,78,85,77,66,69, - 82,114,73,0,0,0,114,72,0,0,0,114,84,0,0,0, - 114,74,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,79,0,0,0, - 114,85,0,0,0,114,91,0,0,0,114,95,0,0,0,114, - 97,0,0,0,114,105,0,0,0,114,123,0,0,0,114,130, - 0,0,0,114,141,0,0,0,114,147,0,0,0,114,150,0, - 0,0,114,155,0,0,0,218,6,111,98,106,101,99,116,114, - 162,0,0,0,114,167,0,0,0,114,168,0,0,0,114,184, - 0,0,0,114,194,0,0,0,114,210,0,0,0,114,218,0, - 0,0,114,223,0,0,0,114,232,0,0,0,114,224,0,0, - 0,114,233,0,0,0,114,250,0,0,0,114,252,0,0,0, - 114,9,1,0,0,114,26,1,0,0,114,161,0,0,0,114, - 35,1,0,0,114,37,1,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,60, - 109,111,100,117,108,101,62,8,0,0,0,115,100,0,0,0, - 6,17,6,3,12,12,12,5,12,5,12,6,12,12,12,10, - 12,9,12,5,12,7,15,22,15,108,22,1,18,2,6,1, - 6,2,9,2,9,2,10,2,21,44,12,33,12,19,12,12, - 12,12,18,8,12,27,12,17,21,55,21,12,18,10,12,14, - 9,3,12,1,15,65,19,64,19,28,22,110,19,41,25,43, - 25,16,6,3,19,57,19,57,19,41,19,134,19,146,15,23, - 12,11,12,68, + 218,10,95,95,108,111,97,100,101,114,95,95,218,8,95,95, + 115,112,101,99,95,95,114,127,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,127,0,0,0,114,223,0, + 0,0,114,218,0,0,0,114,167,0,0,0,218,9,69,120, + 99,101,112,116,105,111,110,41,6,90,2,110,115,114,106,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,127,0,0,0,114,164,0,0, + 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, + 218,14,95,102,105,120,95,117,112,95,109,111,100,117,108,101, + 30,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, + 1,6,1,12,1,12,1,18,2,15,1,6,1,21,1,3, + 1,10,1,10,1,10,1,14,1,13,2,114,24,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,55,0,0,0,116,0,0,116,1,0, + 106,2,0,131,0,0,102,2,0,125,0,0,116,3,0,116, + 4,0,102,2,0,125,1,0,116,5,0,116,6,0,102,2, + 0,125,2,0,124,0,0,124,1,0,124,2,0,103,3,0, + 83,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,224,0,0,0,114,145,0,0,0, + 218,18,101,120,116,101,110,115,105,111,110,95,115,117,102,102, + 105,120,101,115,114,218,0,0,0,114,84,0,0,0,114,223, + 0,0,0,114,74,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,5,0,0,0,114,161,0,0,0,53,5,0,0, + 115,8,0,0,0,0,5,18,1,12,1,12,1,114,161,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,70,2,0,0,124,0,0,97, + 0,0,116,0,0,106,1,0,97,1,0,116,0,0,106,2, + 0,97,2,0,116,1,0,106,3,0,116,4,0,25,125,1, + 0,120,76,0,100,26,0,68,93,68,0,125,2,0,124,2, + 0,116,1,0,106,3,0,107,7,0,114,83,0,116,0,0, + 106,5,0,124,2,0,131,1,0,125,3,0,110,13,0,116, + 1,0,106,3,0,124,2,0,25,125,3,0,116,6,0,124, + 1,0,124,2,0,124,3,0,131,3,0,1,113,44,0,87, + 100,5,0,100,6,0,103,1,0,102,2,0,100,7,0,100, + 8,0,100,6,0,103,2,0,102,2,0,102,2,0,125,4, + 0,120,149,0,124,4,0,68,93,129,0,92,2,0,125,5, + 0,125,6,0,116,7,0,100,9,0,100,10,0,132,0,0, + 124,6,0,68,131,1,0,131,1,0,115,199,0,116,8,0, + 130,1,0,124,6,0,100,11,0,25,125,7,0,124,5,0, + 116,1,0,106,3,0,107,6,0,114,241,0,116,1,0,106, + 3,0,124,5,0,25,125,8,0,80,113,156,0,121,20,0, + 116,0,0,106,5,0,124,5,0,131,1,0,125,8,0,80, + 87,113,156,0,4,116,9,0,107,10,0,114,28,1,1,1, + 1,119,156,0,89,113,156,0,88,113,156,0,87,116,9,0, + 100,12,0,131,1,0,130,1,0,116,6,0,124,1,0,100, + 13,0,124,8,0,131,3,0,1,116,6,0,124,1,0,100, + 14,0,124,7,0,131,3,0,1,116,6,0,124,1,0,100, + 15,0,100,16,0,106,10,0,124,6,0,131,1,0,131,3, + 0,1,121,19,0,116,0,0,106,5,0,100,17,0,131,1, + 0,125,9,0,87,110,24,0,4,116,9,0,107,10,0,114, + 147,1,1,1,1,100,18,0,125,9,0,89,110,1,0,88, + 116,6,0,124,1,0,100,17,0,124,9,0,131,3,0,1, + 116,0,0,106,5,0,100,19,0,131,1,0,125,10,0,116, + 6,0,124,1,0,100,19,0,124,10,0,131,3,0,1,124, + 5,0,100,7,0,107,2,0,114,238,1,116,0,0,106,5, + 0,100,20,0,131,1,0,125,11,0,116,6,0,124,1,0, + 100,21,0,124,11,0,131,3,0,1,116,6,0,124,1,0, + 100,22,0,116,11,0,131,0,0,131,3,0,1,116,12,0, + 106,13,0,116,2,0,106,14,0,131,0,0,131,1,0,1, + 124,5,0,100,7,0,107,2,0,114,66,2,116,15,0,106, + 16,0,100,23,0,131,1,0,1,100,24,0,116,12,0,107, + 6,0,114,66,2,100,25,0,116,17,0,95,18,0,100,18, + 0,83,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,49,0,0,0,114,60,0,0,0,218,8,98, + 117,105,108,116,105,110,115,114,142,0,0,0,90,5,112,111, + 115,105,120,250,1,47,218,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,33,0,0,0,124,0,0,93,23,0,125,1,0, + 116,0,0,124,1,0,131,1,0,100,0,0,107,2,0,86, + 1,113,3,0,100,1,0,83,41,2,114,29,0,0,0,78, + 41,1,114,31,0,0,0,41,2,114,22,0,0,0,114,77, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, + 0,0,114,227,0,0,0,89,5,0,0,115,2,0,0,0, + 6,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,59,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,25,0,0,0,114,21,0,0, + 0,114,30,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,169,0,0,0,114,6,0,0,0,122,4,46,112, + 121,119,122,6,95,100,46,112,121,100,84,41,4,122,3,95, + 105,111,122,9,95,119,97,114,110,105,110,103,115,122,8,98, + 117,105,108,116,105,110,115,122,7,109,97,114,115,104,97,108, + 41,19,114,121,0,0,0,114,7,0,0,0,114,145,0,0, + 0,114,239,0,0,0,114,112,0,0,0,90,18,95,98,117, + 105,108,116,105,110,95,102,114,111,109,95,110,97,109,101,114, + 116,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,107,0,0,0,114,26, + 0,0,0,114,11,0,0,0,114,229,0,0,0,114,149,0, + 0,0,114,25,1,0,0,114,84,0,0,0,114,163,0,0, + 0,114,168,0,0,0,114,173,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,4,0,0,0,114,4,0,0,0, + 114,5,0,0,0,218,6,95,115,101,116,117,112,64,5,0, + 0,115,82,0,0,0,0,8,6,1,9,1,9,3,13,1, + 13,1,15,1,18,2,13,1,20,3,33,1,19,2,31,1, + 10,1,15,1,13,1,4,2,3,1,15,1,5,1,13,1, + 12,2,12,1,16,1,16,1,25,3,3,1,19,1,13,2, + 11,1,16,3,15,1,16,3,12,1,15,1,16,3,19,1, + 19,1,12,1,13,1,12,1,114,33,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,116,0,0,0,116,0,0,124,0,0,131,1,0, + 1,116,1,0,131,0,0,125,1,0,116,2,0,106,3,0, + 106,4,0,116,5,0,106,6,0,124,1,0,140,0,0,103, + 1,0,131,1,0,1,116,7,0,106,8,0,100,1,0,107, + 2,0,114,78,0,116,2,0,106,9,0,106,10,0,116,11, + 0,131,1,0,1,116,2,0,106,9,0,106,10,0,116,12, + 0,131,1,0,1,116,5,0,124,0,0,95,5,0,116,13, + 0,124,0,0,95,13,0,100,2,0,83,41,3,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,114,28,1,0,0,78,41,14, + 114,33,1,0,0,114,161,0,0,0,114,7,0,0,0,114, + 254,0,0,0,114,149,0,0,0,114,6,1,0,0,114,19, + 1,0,0,114,3,0,0,0,114,112,0,0,0,218,9,109, + 101,116,97,95,112,97,116,104,114,163,0,0,0,114,168,0, + 0,0,114,249,0,0,0,114,218,0,0,0,41,2,114,32, + 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,5,0,0,0,218,8,95,105,110,115,116,97,108,108,132, + 5,0,0,115,16,0,0,0,0,2,10,1,9,1,28,1, + 15,1,16,1,16,4,9,1,114,35,1,0,0,41,3,122, + 3,119,105,110,114,1,0,0,0,114,2,0,0,0,41,57, + 114,114,0,0,0,114,10,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,55,0,0,0,218,4,116,121, + 112,101,218,8,95,95,99,111,100,101,95,95,114,144,0,0, + 0,114,15,0,0,0,114,135,0,0,0,114,14,0,0,0, + 114,18,0,0,0,90,17,95,82,65,87,95,77,65,71,73, + 67,95,78,85,77,66,69,82,114,73,0,0,0,114,72,0, + 0,0,114,84,0,0,0,114,74,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,79,0,0,0,114,85,0,0,0,114,91,0,0, + 0,114,95,0,0,0,114,97,0,0,0,114,105,0,0,0, + 114,123,0,0,0,114,130,0,0,0,114,141,0,0,0,114, + 147,0,0,0,114,150,0,0,0,114,155,0,0,0,218,6, + 111,98,106,101,99,116,114,162,0,0,0,114,167,0,0,0, + 114,168,0,0,0,114,184,0,0,0,114,194,0,0,0,114, + 210,0,0,0,114,218,0,0,0,114,223,0,0,0,114,229, + 0,0,0,114,224,0,0,0,114,230,0,0,0,114,247,0, + 0,0,114,249,0,0,0,114,6,1,0,0,114,24,1,0, + 0,114,161,0,0,0,114,33,1,0,0,114,35,1,0,0, + 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 5,0,0,0,218,8,60,109,111,100,117,108,101,62,8,0, + 0,0,115,100,0,0,0,6,17,6,3,12,12,12,5,12, + 5,12,6,12,12,12,10,12,9,12,5,12,7,15,22,15, + 108,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, + 44,12,33,12,19,12,12,12,12,18,8,12,28,12,17,21, + 55,21,12,18,10,12,14,9,3,12,1,15,65,19,64,19, + 28,22,110,19,41,25,43,25,16,6,3,25,53,19,57,19, + 41,19,134,19,146,15,23,12,11,12,68, }; diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -255,6 +255,9 @@ Py_ssize_t index = module->m_base.m_index; PyInterpreterState *state = PyThreadState_GET()->interp; PyObject *res; + if (module->m_slots) { + return NULL; + } if (index == 0) return NULL; if (state->modules_by_index == NULL) @@ -268,7 +271,13 @@ int _PyState_AddModule(PyObject* module, struct PyModuleDef* def) { - PyInterpreterState *state = PyThreadState_GET()->interp; + PyInterpreterState *state; + if (def->m_slots) { + PyErr_SetString(PyExc_SystemError, + "PyState_AddModule called on module with slots"); + return -1; + } + state = PyThreadState_GET()->interp; if (!def) return -1; if (!state->modules_by_index) { @@ -308,8 +317,14 @@ int PyState_RemoveModule(struct PyModuleDef* def) { + PyInterpreterState *state; Py_ssize_t index = def->m_base.m_index; - PyInterpreterState *state = PyThreadState_GET()->interp; + if (def->m_slots) { + PyErr_SetString(PyExc_SystemError, + "PyState_RemoveModule called on module with slots"); + return -1; + } + state = PyThreadState_GET()->interp; if (index == 0) { Py_FatalError("PyState_RemoveModule: Module index invalid."); return -1; diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -620,6 +620,8 @@ exts.append( Extension('_testbuffer', ['_testbuffer.c']) ) # Test loading multiple modules from one compiled file (http://bugs.python.org/issue16421) exts.append( Extension('_testimportmultiple', ['_testimportmultiple.c']) ) + # Test multi-phase extension module init (PEP 489) + exts.append( Extension('_testmultiphase', ['_testmultiphase.c']) ) # profiler (_lsprof is for cProfile.py) exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) ) # static Unicode character database -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:03:57 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 23 May 2015 15:03:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324268=3A_Address_?= =?utf-8?q?some_PEP_489_refleaks?= Message-ID: <20150523150357.16297.59596@psf.io> https://hg.python.org/cpython/rev/7f2e6f236202 changeset: 96229:7f2e6f236202 user: Nick Coghlan date: Sun May 24 01:03:46 2015 +1000 summary: Issue #24268: Address some PEP 489 refleaks - missing DECREF in PyModule_FromDefAndSpec2 - missing DECREF in PyType_FromSpecAndBases2 - missing DECREF in _testmultiphase module Patch by Petr Viktorin files: Modules/_testmultiphase.c | 1 + Objects/moduleobject.c | 1 + Objects/typeobject.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -262,6 +262,7 @@ return NULL; } PyDict_SetItemString(dct, "three", three); + Py_DECREF(three); ns = _PyNamespace_New(dct); Py_DECREF(dct); diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -311,6 +311,7 @@ } } + Py_DECREF(nameobj); return m; error: diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2694,6 +2694,7 @@ { PyHeapTypeObject *res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); PyTypeObject *type, *base; + PyObject *modname; char *s; char *res_start = (char*)res; PyType_Slot *slot; @@ -2807,11 +2808,15 @@ /* Set type.__module__ */ s = strrchr(spec->name, '.'); - if (s != NULL) - _PyDict_SetItemId(type->tp_dict, &PyId___module__, - PyUnicode_FromStringAndSize( - spec->name, (Py_ssize_t)(s - spec->name))); - else { + if (s != NULL) { + modname = PyUnicode_FromStringAndSize( + spec->name, (Py_ssize_t)(s - spec->name)); + if (modname == NULL) { + goto fail; + } + _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname); + Py_DECREF(modname); + } else { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "builtin type %.200s has no __module__ attribute", spec->name)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3_=28=2322931=29?= Message-ID: <20150523154814.16283.86351@psf.io> https://hg.python.org/cpython/rev/a43f5515e3a2 changeset: 96232:a43f5515e3a2 branch: 3.4 parent: 96225:4c16773052d1 parent: 96231:c7b3a50a2f01 user: Benjamin Peterson date: Sat May 23 10:40:47 2015 -0500 summary: merge 3.3 (#22931) files: Lib/http/cookies.py | 7 ++++--- Lib/test/test_http_cookies.py | 13 +++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -428,12 +428,13 @@ # result, the parsing rules here are less strict. # -_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]" +_LegalKeyChars = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=" +_LegalValueChars = _LegalKeyChars + '\[\]' _CookiePattern = re.compile(r""" (?x) # This is a verbose pattern \s* # Optional whitespace at start of cookie (?P # Start of group 'key' - """ + _LegalCharsPatt + r"""+? # Any word of at least one letter + [""" + _LegalKeyChars + r"""]+? # Any word of at least one letter ) # End of group 'key' ( # Optional group: there may not be a value. \s*=\s* # Equal Sign @@ -442,7 +443,7 @@ | # or \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr | # or - """ + _LegalCharsPatt + r"""* # Any word or empty string + [""" + _LegalValueChars + r"""]* # Any word or empty string ) # End of group 'val' )? # End of optional value group \s* # Any number of spaces. diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -43,6 +43,19 @@ 'repr': "", 'output': 'Set-Cookie: key:term=value:term'}, + # issue22931 - Adding '[' and ']' as valid characters in cookie + # values as defined in RFC 6265 + { + 'data': 'a=b; c=[; d=r; f=h', + 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'}, + 'repr': "", + 'output': '\n'.join(( + 'Set-Cookie: a=b', + 'Set-Cookie: c=[', + 'Set-Cookie: d=r', + 'Set-Cookie: f=h' + )) + } ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,8 @@ - Issue #23796: peek and read1 methods of BufferedReader now raise ValueError if they called on a closed object. Patch by John Hergenroeder. +- Issue #22931: Allow '[' and ']' in cookie values. + - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_merge_3=2E2_=28=2322931=29?= Message-ID: <20150523154814.16709.40593@psf.io> https://hg.python.org/cpython/rev/c7b3a50a2f01 changeset: 96231:c7b3a50a2f01 branch: 3.3 parent: 95870:ffc1f9d1c8b3 parent: 96230:710cdba13323 user: Benjamin Peterson date: Sat May 23 10:38:48 2015 -0500 summary: merge 3.2 (#22931) files: Lib/http/cookies.py | 7 ++++--- Lib/test/test_http_cookies.py | 13 +++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -428,12 +428,13 @@ # result, the parsing rules here are less strict. # -_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]" +_LegalKeyChars = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=" +_LegalValueChars = _LegalKeyChars + '\[\]' _CookiePattern = re.compile(r""" (?x) # This is a verbose pattern \s* # Optional whitespace at start of cookie (?P # Start of group 'key' - """ + _LegalCharsPatt + r"""+? # Any word of at least one letter + [""" + _LegalKeyChars + r"""]+? # Any word of at least one letter ) # End of group 'key' ( # Optional group: there may not be a value. \s*=\s* # Equal Sign @@ -442,7 +443,7 @@ | # or \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr | # or - """ + _LegalCharsPatt + r"""* # Any word or empty string + [""" + _LegalValueChars + r"""]* # Any word or empty string ) # End of group 'val' )? # End of optional value group \s* # Any number of spaces. diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -43,6 +43,19 @@ 'repr': "", 'output': 'Set-Cookie: key:term=value:term'}, + # issue22931 - Adding '[' and ']' as valid characters in cookie + # values as defined in RFC 6265 + { + 'data': 'a=b; c=[; d=r; f=h', + 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'}, + 'repr': "", + 'output': '\n'.join(( + 'Set-Cookie: a=b', + 'Set-Cookie: c=[', + 'Set-Cookie: d=r', + 'Set-Cookie: f=h' + )) + } ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Library ------- +- Issue #22931: Allow '[' and ']' in cookie values. + - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_allow_square_b?= =?utf-8?q?rackets_in_cookie_values_=28closes_=2322931=29?= Message-ID: <20150523154814.96196.82181@psf.io> https://hg.python.org/cpython/rev/710cdba13323 changeset: 96230:710cdba13323 branch: 3.2 parent: 95786:91096d27c802 user: Benjamin Peterson date: Sat May 23 10:36:48 2015 -0500 summary: allow square brackets in cookie values (closes #22931) files: Lib/http/cookies.py | 7 ++++--- Lib/test/test_http_cookies.py | 14 ++++++++++++++ Misc/NEWS | 5 +++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -429,12 +429,13 @@ # result, the parsing rules here are less strict. # -_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]" +_LegalKeyChars = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=" +_LegalValueChars = _LegalKeyChars + '\[\]' _CookiePattern = re.compile(r""" (?x) # This is a verbose pattern \s* # Optional whitespace at start of cookie (?P # Start of group 'key' - """ + _LegalCharsPatt + r"""+? # Any word of at least one letter + [""" + _LegalKeyChars + r"""]+? # Any word of at least one letter ) # End of group 'key' \s*=\s* # Equal Sign (?P # Start of group 'val' @@ -442,7 +443,7 @@ | # or \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr | # or - """ + _LegalCharsPatt + r"""* # Any word or empty string + [""" + _LegalValueChars + r"""]* # Any word or empty string ) # End of group 'val' \s*;? # Probably ending in a semi-colon """, re.ASCII) # May be removed if safe. diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -34,6 +34,20 @@ 'dict': {'keebler' : 'E=mc2'}, 'repr': "", 'output': 'Set-Cookie: keebler=E=mc2'}, + + # issue22931 - Adding '[' and ']' as valid characters in cookie + # values as defined in RFC 6265 + { + 'data': 'a=b; c=[; d=r; f=h', + 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'}, + 'repr': "", + 'output': '\n'.join(( + 'Set-Cookie: a=b', + 'Set-Cookie: c=[', + 'Set-Cookie: d=r', + 'Set-Cookie: f=h' + )) + } ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,11 @@ - Issue #23055: Fixed a buffer overflow in PyUnicode_FromFormatV. Analysis and fix by Guido Vranken. +Library +------- + +- Issue #22931: Allow '[' and ']' in cookie values. + What's New in Python 3.2.6? =========================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjI5MzEp?= Message-ID: <20150523154814.126956.25798@psf.io> https://hg.python.org/cpython/rev/c58f3e76dc6c changeset: 96233:c58f3e76dc6c parent: 96229:7f2e6f236202 parent: 96232:a43f5515e3a2 user: Benjamin Peterson date: Sat May 23 10:41:30 2015 -0500 summary: merge 3.4 (#22931) files: Lib/http/cookies.py | 7 ++++--- Lib/test/test_http_cookies.py | 13 +++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -455,12 +455,13 @@ # result, the parsing rules here are less strict. # -_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]" +_LegalKeyChars = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=" +_LegalValueChars = _LegalKeyChars + '\[\]' _CookiePattern = re.compile(r""" (?x) # This is a verbose pattern \s* # Optional whitespace at start of cookie (?P # Start of group 'key' - """ + _LegalCharsPatt + r"""+? # Any word of at least one letter + [""" + _LegalKeyChars + r"""]+? # Any word of at least one letter ) # End of group 'key' ( # Optional group: there may not be a value. \s*=\s* # Equal Sign @@ -469,7 +470,7 @@ | # or \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr | # or - """ + _LegalCharsPatt + r"""* # Any word or empty string + [""" + _LegalValueChars + r"""]* # Any word or empty string ) # End of group 'val' )? # End of optional value group \s* # Any number of spaces. diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -44,6 +44,19 @@ 'repr': "", 'output': 'Set-Cookie: key:term=value:term'}, + # issue22931 - Adding '[' and ']' as valid characters in cookie + # values as defined in RFC 6265 + { + 'data': 'a=b; c=[; d=r; f=h', + 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'}, + 'repr': "", + 'output': '\n'.join(( + 'Set-Cookie: a=b', + 'Set-Cookie: c=[', + 'Set-Cookie: d=r', + 'Set-Cookie: f=h' + )) + } ] for case in cases: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -325,6 +325,8 @@ lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger and Allison Kaptur. +- Issue #22931: Allow '[' and ']' in cookie values. + - The keywords attribute of functools.partial is now always a dictionary. - Issue #23811: Add missing newline to the PyCompileError error message. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:14 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_allow_square_b?= =?utf-8?q?rackets_in_cookie_values_=28=2322931=29?= Message-ID: <20150523154814.96190.13536@psf.io> https://hg.python.org/cpython/rev/2a7b0e145945 changeset: 96234:2a7b0e145945 branch: 2.7 parent: 96216:117af4bc0513 user: Benjamin Peterson date: Sat May 23 10:46:25 2015 -0500 summary: allow square brackets in cookie values (#22931) files: Lib/Cookie.py | 7 ++++--- Lib/test/test_cookie.py | 14 ++++++++++++++ Misc/NEWS | 11 +++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Lib/Cookie.py b/Lib/Cookie.py --- a/Lib/Cookie.py +++ b/Lib/Cookie.py @@ -528,12 +528,13 @@ # result, the parsing rules here are less strict. # -_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]" +_LegalKeyChars = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=" +_LegalValueChars = _LegalKeyChars + r"\[\]" _CookiePattern = re.compile( r"(?x)" # This is a Verbose pattern r"\s*" # Optional whitespace at start of cookie r"(?P" # Start of group 'key' - ""+ _LegalCharsPatt +"+?" # Any word of at least one letter, nongreedy + "["+ _LegalKeyChars +"]+?" # Any word of at least one letter, nongreedy r")" # End of group 'key' r"(" # Optional group: there may not be a value. r"\s*=\s*" # Equal Sign @@ -542,7 +543,7 @@ r"|" # or r"\w{3},\s[\s\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr r"|" # or - ""+ _LegalCharsPatt +"*" # Any word or empty string + "["+ _LegalValueChars +"]*" # Any word or empty string r")" # End of group 'val' r")?" # End of optional value group r"\s*" # Any number of spaces. diff --git a/Lib/test/test_cookie.py b/Lib/test/test_cookie.py --- a/Lib/test/test_cookie.py +++ b/Lib/test/test_cookie.py @@ -27,6 +27,20 @@ 'dict': {'keebler' : 'E=mc2'}, 'repr': "", 'output': 'Set-Cookie: keebler=E=mc2', + }, + + # issue22931 - Adding '[' and ']' as valid characters in cookie + # values as defined in RFC 6265 + { + 'data': 'a=b; c=[; d=r; f=h', + 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'}, + 'repr': "", + 'output': '\n'.join(( + 'Set-Cookie: a=b', + 'Set-Cookie: c=[', + 'Set-Cookie: d=r', + 'Set-Cookie: f=h' + )) } ] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,17 @@ Python News +++++++++++ +What's New in Python 2.7.10? +============================ + +*Release date: 2015-05-23* + +Library +------- + +- Issue #22931: Allow '[' and ']' in cookie values. + + What's New in Python 2.7.10 release candidate 1? ================================================ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:48:15 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:48:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge_2=2E7=2E10_release_branch?= Message-ID: <20150523154815.27953.85015@psf.io> https://hg.python.org/cpython/rev/115d46d16b97 changeset: 96235:115d46d16b97 branch: 2.7 parent: 96234:2a7b0e145945 parent: 96224:428d2eec7e77 user: Benjamin Peterson date: Sat May 23 10:47:39 2015 -0500 summary: merge 2.7.10 release branch files: Doc/c-api/iter.rst | 4 + Doc/faq/gui.rst | 25 +- Doc/library/collections.rst | 6 +- Doc/library/math.rst | 4 +- Doc/library/tkinter.rst | 50 +++ Lib/email/test/test_email.py | 25 +- Lib/email/utils.py | 9 +- Lib/ensurepip/__init__.py | 4 +- Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl | Bin Lib/httplib.py | 2 +- Lib/idlelib/EditorWindow.py | 2 - Lib/idlelib/GrepDialog.py | 1 - Lib/idlelib/IOBinding.py | 7 +- Lib/idlelib/PyShell.py | 27 +- Lib/idlelib/RemoteDebugger.py | 3 +- Lib/idlelib/SearchDialog.py | 2 +- Lib/idlelib/TreeWidget.py | 2 +- Lib/idlelib/aboutDialog.py | 15 +- Lib/idlelib/configDialog.py | 1 - Lib/idlelib/idle.pyw | 26 +- Lib/idlelib/idle_test/README.txt | 128 ++++++--- Lib/idlelib/idle_test/test_autocomplete.py | 4 +- Lib/idlelib/idle_test/test_formatparagraph.py | 2 +- Lib/idlelib/idle_test/test_searchdialogbase.py | 7 +- Lib/idlelib/idle_test/test_searchengine.py | 2 +- Lib/idlelib/idle_test/test_text.py | 1 - Lib/idlelib/macosxSupport.py | 4 +- Lib/idlelib/rpc.py | 5 +- Lib/idlelib/run.py | 3 +- Lib/lib2to3/refactor.py | 2 +- Lib/sqlite3/test/factory.py | 8 + Lib/tempfile.py | 19 +- Lib/test/seq_tests.py | 12 + Lib/test/test_array.py | 21 + Lib/test/test_codeccallbacks.py | 20 + Lib/test/test_httplib.py | 17 + Lib/test/test_pprint.py | 9 +- Lib/test/test_slice.py | 3 +- Lib/test/test_tempfile.py | 50 +++- Lib/test/test_warnings.py | 57 ++++ Lib/unittest/case.py | 12 +- Lib/unittest/test/test_case.py | 5 - Lib/warnings.py | 22 +- Misc/ACKS | 1 + Misc/NEWS | 60 ++++- Misc/python.man | 14 +- Modules/_elementtree.c | 65 +++- Modules/_heapqmodule.c | 5 + Modules/_sqlite/row.c | 2 +- Modules/arraymodule.c | 18 +- Objects/abstract.c | 2 +- Objects/dictobject.c | 4 +- Objects/iterobject.c | 5 + Python/codecs.c | 17 +- Tools/msi/uuids.py | 2 + 58 files changed, 599 insertions(+), 224 deletions(-) diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -14,6 +14,10 @@ Return true if the object *o* supports the iterator protocol. + This function can return a false positive in the case of old-style + classes because those classes always define a :c:member:`tp_iternext` + slot with logic that either invokes a :meth:`next` method or raises + a :exc:`TypeError`. .. c:function:: PyObject* PyIter_Next(PyObject *o) diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -125,30 +125,11 @@ Can I have Tk events handled while waiting for I/O? --------------------------------------------------- -Yes, and you don't even need threads! But you'll have to restructure your I/O +On platforms other than Windows, yes, and you don't even +need threads! But you'll have to restructure your I/O code a bit. Tk has the equivalent of Xt's :c:func:`XtAddInput()` call, which allows you to register a callback function which will be called from the Tk mainloop when -I/O is possible on a file descriptor. Here's what you need:: - - from Tkinter import tkinter - tkinter.createfilehandler(file, mask, callback) - -The file may be a Python file or socket object (actually, anything with a -fileno() method), or an integer file descriptor. The mask is one of the -constants tkinter.READABLE or tkinter.WRITABLE. The callback is called as -follows:: - - callback(file, mask) - -You must unregister the callback when you're done, using :: - - tkinter.deletefilehandler(file) - -Note: since you don't know *how many bytes* are available for reading, you can't -use the Python file object's read or readline methods, since these will insist -on reading a predefined number of bytes. For sockets, the :meth:`recv` or -:meth:`recvfrom` methods will work fine; for other files, use -``os.read(file.fileno(), maxbytecount)``. +I/O is possible on a file descriptor. See :ref:`tkinter-file-handlers`. I can't get key bindings to work in Tkinter: why? diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -104,9 +104,9 @@ .. method:: most_common([n]) Return a list of the *n* most common elements and their counts from the - most common to the least. If *n* is not specified, :func:`most_common` - returns *all* elements in the counter. Elements with equal counts are - ordered arbitrarily: + most common to the least. If *n* is omitted or ``None``, + :func:`most_common` returns *all* elements in the counter. + Elements with equal counts are ordered arbitrarily: >>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)] diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -280,12 +280,12 @@ .. function:: degrees(x) - Converts angle *x* from radians to degrees. + Convert angle *x* from radians to degrees. .. function:: radians(x) - Converts angle *x* from degrees to radians. + Convert angle *x* from degrees to radians. Hyperbolic functions diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -817,3 +817,53 @@ deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used. + +.. _tkinter-file-handlers: + +File Handlers +------------- + +Tk allows you to register and unregister a callback function which will be +called from the Tk mainloop when I/O is possible on a file descriptor. +Only one handler may be registered per file descriptor. Example code:: + + import Tkinter + widget = Tkinter.Tk() + mask = Tkinter.READABLE | Tkinter.WRITABLE + widget.tk.createfilehandler(file, mask, callback) + ... + widget.tk.deletefilehandler(file) + +This feature is not available on Windows. + +Since you don't know how many bytes are available for reading, you may not +want to use the :class:`~io.BufferedIOBase` or :class:`~io.TextIOBase` +:meth:`~io.BufferedIOBase.read` or :meth:`~io.IOBase.readline` methods, +since these will insist on reading a predefined number of bytes. +For sockets, the :meth:`~socket.socket.recv` or +:meth:`~socket.socket.recvfrom` methods will work fine; for other files, +use raw reads or ``os.read(file.fileno(), maxbytecount)``. + + +.. method:: Widget.tk.createfilehandler(file, mask, func) + + Registers the file handler callback function *func*. The *file* argument + may either be an object with a :meth:`~io.IOBase.fileno` method (such as + a file or socket object), or an integer file descriptor. The *mask* + argument is an ORed combination of any of the three constants below. + The callback is called as follows:: + + callback(file, mask) + + +.. method:: Widget.tk.deletefilehandler(file) + + Unregisters a file handler. + + +.. data:: READABLE + WRITABLE + EXCEPTION + + Constants used in the *mask* arguments. + diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -12,6 +12,10 @@ import textwrap from cStringIO import StringIO from random import choice +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread import email @@ -33,7 +37,7 @@ from email import base64MIME from email import quopriMIME -from test.test_support import findfile, run_unittest +from test.test_support import findfile, run_unittest, start_threads from email.test import __file__ as landmark @@ -2412,6 +2416,25 @@ addrs = Utils.getaddresses(['User ((nested comment)) ']) eq(addrs[0][1], 'foo at bar.com') + def test_make_msgid_collisions(self): + # Test make_msgid uniqueness, even with multiple threads + class MsgidsThread(Thread): + def run(self): + # generate msgids for 3 seconds + self.msgids = [] + append = self.msgids.append + make_msgid = Utils.make_msgid + clock = time.clock + tfin = clock() + 3.0 + while clock() < tfin: + append(make_msgid()) + + threads = [MsgidsThread() for i in range(5)] + with start_threads(threads): + pass + all_ids = sum([t.msgids for t in threads], []) + self.assertEqual(len(set(all_ids)), len(all_ids)) + def test_utils_quote_unquote(self): eq = self.assertEqual msg = Message() diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -177,21 +177,20 @@ def make_msgid(idstring=None): """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: - <20020201195627.33539.96671 at nightshade.la.mastaler.com> + <142480216486.20800.16526388040877946887 at nightshade.la.mastaler.com> Optional idstring if given is a string used to strengthen the uniqueness of the message id. """ - timeval = time.time() - utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + timeval = int(time.time()*100) pid = os.getpid() - randint = random.randrange(100000) + randint = random.getrandbits(64) if idstring is None: idstring = '' else: idstring = '.' + idstring idhost = socket.getfqdn() - msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost) + msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, idhost) return msgid diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "15.2" +_SETUPTOOLS_VERSION = "16.0" -_PIP_VERSION = "6.1.1" +_PIP_VERSION = "7.0.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl deleted file mode 100644 index e59694a019051d58b9a378a1adfc9461b8cec9c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.0.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..30a61f0a0e9dde9b4dde32876e65213e7ceb4f8e GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.2-py2.py3-none-any.whl deleted file mode 100644 index f153ed376684275e08fcfebdb2de8352fb074171..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-16.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fa4e994929b5bd27f99a44c78e08f48d142ccfd9 GIT binary patch [stripped] diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -1063,7 +1063,7 @@ elif body is not None: try: thelen = str(len(body)) - except TypeError: + except (TypeError, AttributeError): # If this is a file-like object, try to # fstat its file descriptor try: diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -9,7 +9,6 @@ import webbrowser from idlelib.MultiCall import MultiCallCreator -from idlelib import idlever from idlelib import WindowList from idlelib import SearchDialog from idlelib import GrepDialog @@ -154,7 +153,6 @@ EditorWindow.help_url = 'file://' + EditorWindow.help_url else: EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2] - currentTheme=idleConf.CurrentTheme() self.flist = flist root = root or flist.root self.root = root diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -5,7 +5,6 @@ from Tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog from Tkinter import Tk, Text, Button, SEL, END # for htest from idlelib import SearchEngine -import itertools from idlelib.SearchDialogBase import SearchDialogBase # Importing OutputWindow fails due to import loop # EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -6,7 +6,6 @@ # which will only understand the local convention. import os -import types import pipes import sys import codecs @@ -391,7 +390,7 @@ return False def encode(self, chars): - if isinstance(chars, types.StringType): + if isinstance(chars, str): # This is either plain ASCII, or Tk was returning mixed-encoding # text to us. Don't try to guess further. return chars @@ -568,7 +567,7 @@ "Update recent file list on all editor windows" self.editwin.update_recent_files_list(filename) -def _io_binding(parent): +def _io_binding(parent): # htest # root = Tk() root.title("Test IOBinding") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) @@ -591,7 +590,7 @@ text.pack() text.focus_set() editwin = MyEditWin(text) - io = IOBinding(editwin) + IOBinding(editwin) if __name__ == "__main__": from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -10,8 +10,6 @@ import socket import time import threading -import traceback -import types import io import linecache @@ -32,11 +30,11 @@ from idlelib.UndoDelegator import UndoDelegator from idlelib.OutputWindow import OutputWindow from idlelib.configHandler import idleConf -from idlelib import idlever from idlelib import rpc from idlelib import Debugger from idlelib import RemoteDebugger from idlelib import macosxSupport +from idlelib import IOBinding IDENTCHARS = string.ascii_letters + string.digits + "_" HOST = '127.0.0.1' # python execution server on localhost loopback @@ -171,7 +169,7 @@ filename = self.io.filename text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) try: - i = self.breakpoints.index(lineno) + self.breakpoints.index(lineno) except ValueError: # only add if missing, i.e. do once self.breakpoints.append(lineno) try: # update the subprocess debugger @@ -439,7 +437,7 @@ try: self.rpcclt = MyRPCClient(addr) break - except socket.error as err: + except socket.error: pass else: self.display_port_binding_error() @@ -460,7 +458,7 @@ self.rpcclt.listening_sock.settimeout(10) try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.rpcclt.register("console", self.tkconsole) @@ -495,7 +493,7 @@ self.spawn_subprocess() try: self.rpcclt.accept() - except socket.timeout as err: + except socket.timeout: self.display_no_subprocess_error() return None self.transfer_path(with_cwd=with_cwd) @@ -513,7 +511,7 @@ # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI - gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) + RemoteDebugger.restart_subprocess_debugger(self.rpcclt) # reload remote debugger breakpoints for all PyShellEditWindows debug.load_breakpoints() self.compile.compiler.flags = self.original_compiler_flags @@ -654,7 +652,7 @@ if source is None: source = open(filename, "r").read() try: - code = compile(source, filename, "exec") + code = compile(source, filename, "exec", dont_inherit=True) except (OverflowError, SyntaxError): self.tkconsole.resetoutput() print('*** Error in script or command!\n' @@ -671,10 +669,11 @@ self.more = 0 self.save_warnings_filters = warnings.filters[:] warnings.filterwarnings(action="error", category=SyntaxWarning) - if isinstance(source, types.UnicodeType): - from idlelib import IOBinding + if isinstance(source, unicode) and IOBinding.encoding != 'utf-8': try: - source = source.encode(IOBinding.encoding) + source = '# -*- coding: %s -*-\n%s' % ( + IOBinding.encoding, + source.encode(IOBinding.encoding)) except UnicodeError: self.tkconsole.resetoutput() self.write("Unsupported characters in input\n") @@ -1246,7 +1245,7 @@ while i > 0 and line[i-1] in " \t": i = i-1 line = line[:i] - more = self.interp.runsource(line) + self.interp.runsource(line) def open_stack_viewer(self, event=None): if self.interp.rpcclt: @@ -1260,7 +1259,7 @@ master=self.text) return from idlelib.StackViewer import StackBrowser - sv = StackBrowser(self.root, self.flist) + StackBrowser(self.root, self.flist) def view_restart_mark(self, event=None): self.text.see("iomark") diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py --- a/Lib/idlelib/RemoteDebugger.py +++ b/Lib/idlelib/RemoteDebugger.py @@ -21,7 +21,6 @@ """ import types -from idlelib import rpc from idlelib import Debugger debugging = 0 @@ -101,7 +100,7 @@ tb = tracebacktable[tbid] stack, i = self.idb.get_stack(frame, tb) ##print >>sys.__stderr__, "get_stack() ->", stack - stack = [(wrap_frame(frame), k) for frame, k in stack] + stack = [(wrap_frame(frame2), k) for frame2, k in stack] ##print >>sys.__stderr__, "get_stack() ->", stack return stack, i diff --git a/Lib/idlelib/SearchDialog.py b/Lib/idlelib/SearchDialog.py --- a/Lib/idlelib/SearchDialog.py +++ b/Lib/idlelib/SearchDialog.py @@ -23,7 +23,7 @@ class SearchDialog(SearchDialogBase): def create_widgets(self): - f = SearchDialogBase.create_widgets(self) + SearchDialogBase.create_widgets(self) self.make_button("Find Next", self.default_command, 1) def default_command(self, event=None): diff --git a/Lib/idlelib/TreeWidget.py b/Lib/idlelib/TreeWidget.py --- a/Lib/idlelib/TreeWidget.py +++ b/Lib/idlelib/TreeWidget.py @@ -246,7 +246,7 @@ else: self.edit_finish() try: - label = self.label + self.label except AttributeError: # padding carefully selected (on Windows) to match Entry widget: self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -1,12 +1,10 @@ """About Dialog for IDLE """ - +import os +from sys import version from Tkinter import * -import os - from idlelib import textView -from idlelib import idlever class AboutDialog(Toplevel): """Modal about dialog for idle @@ -37,6 +35,7 @@ self.wait_window() def CreateWidgets(self): + release = version[:version.index(' ')] frameMain = Frame(self, borderwidth=2, relief=SUNKEN) frameButtons = Frame(self) frameButtons.pack(side=BOTTOM, fill=X) @@ -63,14 +62,14 @@ labelEmail.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) labelWWW = Label(frameBg, text='https://docs.python.org/' + - sys.version[:3] + '/library/idle.html', + version[:3] + '/library/idle.html', justify=LEFT, fg=self.fg, bg=self.bg) labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg, text='Python version: ' + \ - sys.version.split()[0], fg=self.fg, bg=self.bg) + labelPythonVer = Label(frameBg, text='Python version: ' + + release, fg=self.fg, bg=self.bg) labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) tkVer = self.tk.call('info', 'patchlevel') labelTkVer = Label(frameBg, text='Tk version: '+ @@ -93,7 +92,7 @@ Frame(frameBg, borderwidth=1, relief=SUNKEN, height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, + idle_v = Label(frameBg, text='IDLE version: ' + release, fg=self.fg, bg=self.bg) idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_button_f = Frame(frameBg, bg=self.bg) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -14,7 +14,6 @@ from idlelib.configHandler import idleConf from idlelib.dynOptionMenuWidget import DynOptionMenu -from idlelib.tabbedpages import TabbedPageSet from idlelib.keybindingDialog import GetKeysDialog from idlelib.configSectionNameDialog import GetCfgSectionNameDialog from idlelib.configHelpSourceEdit import GetHelpSourceDialog diff --git a/Lib/idlelib/idle.pyw b/Lib/idlelib/idle.pyw --- a/Lib/idlelib/idle.pyw +++ b/Lib/idlelib/idle.pyw @@ -2,20 +2,16 @@ import idlelib.PyShell except ImportError: # IDLE is not installed, but maybe PyShell is on sys.path: - try: - import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() + import PyShell + import os + idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) + if idledir != os.getcwd(): + # We're not in the IDLE directory, help the subprocess find run.py + pypath = os.environ.get('PYTHONPATH', '') + if pypath: + os.environ['PYTHONPATH'] = pypath + ':' + idledir + else: + os.environ['PYTHONPATH'] = idledir + PyShell.main() else: idlelib.PyShell.main() diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -1,14 +1,24 @@ README FOR IDLE TESTS IN IDLELIB.IDLE_TEST +0. Quick Start + +Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x. +To run the tests from a command line: + +python -m test.test_idle + +Human-mediated tests were added later in 2.7 and in 3.4. + +python -m idlelib.idle_test.htest + 1. Test Files The idle directory, idlelib, has over 60 xyz.py files. The idle_test -subdirectory should contain a test_xyy.py for each. (For test modules, make -'xyz' lower case, and possibly shorten it.) Each file should start with the -something like the following template, with the blanks after after '.' and 'as', -and before and after '_' filled in. ---- +subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased +even if xyz.py is not. Here is a possible template, with the blanks after after +'.' and 'as', and before and after '_' to be filled in. + import unittest from test.support import requires import idlelib. as @@ -18,33 +28,33 @@ def test_(self): if __name__ == '__main__': - unittest.main(verbosity=2, exit=2) ---- -Idle tests are run with unittest; do not use regrtest's test_main. + unittest.main(verbosity=2) -Once test_xyy is written, the following should go at the end of xyy.py, -with xyz (lowercased) added after 'test_'. ---- +Add the following at the end of xyy.py, with the appropriate name added after +'test_'. Some files already have something like this for htest. If so, insert +the import and unittest.main lines before the htest lines. + if __name__ == "__main__": import unittest unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False) ---- -2. Gui Tests -Gui tests need 'requires' from test.support (test.test_support in 2.7). A -test is a gui test if it creates a Tk root or master object either directly -or indirectly by instantiating a tkinter or idle class. For the benefit of -test processes that either have no graphical environment available or are not -allowed to use it, gui tests must be 'guarded' by "requires('gui')" in a -setUp function or method. This will typically be setUpClass. +2. GUI Tests -To avoid interfering with other gui tests, all gui objects must be destroyed -and deleted by the end of the test. If a widget, such as a Tk root, is created -in a setUpX function, destroy it in the corresponding tearDownX. For module -and class attributes, also delete the widget. ---- +When run as part of the Python test suite, Idle gui tests need to run +test.support.requires('gui') (test.test_support in 2.7). A test is a gui test +if it creates a Tk root or master object either directly or indirectly by +instantiating a tkinter or idle class. For the benefit of test processes that +either have no graphical environment available or are not allowed to use it, gui +tests must be 'guarded' by "requires('gui')" in a setUp function or method. +This will typically be setUpClass. + +To avoid interfering with other gui tests, all gui objects must be destroyed and +deleted by the end of the test. Widgets, such as a Tk root, created in a setUpX +function, should be destroyed in the corresponding tearDownX. Module and class +widget attributes should also be deleted.. + @classmethod def setUpClass(cls): requires('gui') @@ -54,49 +64,55 @@ def tearDownClass(cls): cls.root.destroy() del cls.root ---- -Support.requires('gui') causes the test(s) it guards to be skipped if any of + +Requires('gui') causes the test(s) it guards to be skipped if any of a few conditions are met: - - The tests are being run by regrtest.py, and it was started without - enabling the "gui" resource with the "-u" command line option. + + - The tests are being run by regrtest.py, and it was started without enabling + the "gui" resource with the "-u" command line option. + - The tests are being run on Windows by a service that is not allowed to interact with the graphical environment. + - The tests are being run on Mac OSX in a process that cannot make a window manager connection. + - tkinter.Tk cannot be successfully instantiated for some reason. + - test.support.use_resources has been set by something other than regrtest.py and does not contain "gui". + +Tests of non-gui operations should avoid creating tk widgets. Incidental uses of +tk variables and messageboxes can be replaced by the mock classes in +idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget. -Since non-gui tests always run, but gui tests only sometimes, tests of non-gui -operations should best avoid needing a gui. Methods that make incidental use of -tkinter (tk) variables and messageboxes can do this by using the mock classes in -idle_test/mock_tk.py. There is also a mock text that will handle some uses of the -tk Text widget. +3. Running Unit Tests -3. Running Tests +Assume that xyz.py and test_xyz.py both end with a unittest.main() call. +Running either from an Idle editor runs all tests in the test_xyz file with the +version of Python running Idle. Test output appears in the Shell window. The +'verbosity=2' option lists all test methods in the file, which is appropriate +when developing tests. The 'exit=False' option is needed in xyx.py files when an +htest follows. -Assume that xyz.py and test_xyz.py end with the "if __name__" statements given -above. In Idle, pressing F5 in an editor window with either loaded will run all -tests in the test_xyz file with the version of Python running Idle. The test -report and any tracebacks will appear in the Shell window. The options in these -"if __name__" statements are appropriate for developers running (as opposed to -importing) either of the files during development: verbosity=2 lists all test -methods in the file; exit=False avoids a spurious sys.exit traceback that would -otherwise occur when running in Idle. The following command lines also run -all test methods, including gui tests, in test_xyz.py. (The exceptions are that -idlelib and idlelib.idle start Idle and idlelib.PyShell should (issue 18330).) +The following command lines also run all test methods, including +gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start +Idle and so cannot run tests.) -python -m idlelib.xyz # With the capitalization of the xyz module +python -m idlelib.xyz python -m idlelib.idle_test.test_xyz -To run all idle_test/test_*.py tests, either interactively -('>>>', with unittest imported) or from a command line, use one of the -following. (Notes: in 2.7, 'test ' (with the space) is 'test.regrtest '; -where present, -v and -ugui can be omitted.) +The following runs all idle_test/test_*.py tests interactively. ->>> unittest.main('idlelib.idle_test', verbosity=2, exit=False) +>>> import unittest +>>> unittest.main('idlelib.idle_test', verbosity=2) + +The following run all Idle tests at a command line. Option '-v' is the same as +'verbosity=2'. (For 2.7, replace 'test' in the second line with +'test.regrtest'.) + python -m unittest -v idlelib.idle_test python -m test -v -ugui test_idle python -m test.test_idle @@ -113,3 +129,15 @@ unittest on the command line. python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth + + +4. Human-mediated Tests + +Human-mediated tests are widget tests that cannot be automated but need human +verification. They are contained in idlelib/idle_test/htest.py, which has +instructions. (Some modules need an auxiliary function, identified with # htest +# on the header line.) The set is about complete, though some tests need +improvement. To run all htests, run the htest file from an editor or from the +command line with: + +python -m idlelib.idle_test.htest diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,6 +1,6 @@ import unittest from test.test_support import requires -from Tkinter import Tk, Text, TclError +from Tkinter import Tk, Text import idlelib.AutoComplete as ac import idlelib.AutoCompleteWindow as acw @@ -95,8 +95,8 @@ del ev.mc_state # If autocomplete window is open, complete() method is called - testwin = self.autocomplete._make_autocomplete_window() self.text.insert('1.0', 're.') + # This must call autocomplete._make_autocomplete_window() Equal(self.autocomplete.autocomplete_event(ev), 'break') # If autocomplete window is not active or does not exist, diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -2,7 +2,7 @@ import unittest from idlelib import FormatParagraph as fp from idlelib.EditorWindow import EditorWindow -from Tkinter import Tk, Text, TclError +from Tkinter import Tk, Text from test.test_support import requires diff --git a/Lib/idlelib/idle_test/test_searchdialogbase.py b/Lib/idlelib/idle_test/test_searchdialogbase.py --- a/Lib/idlelib/idle_test/test_searchdialogbase.py +++ b/Lib/idlelib/idle_test/test_searchdialogbase.py @@ -6,14 +6,13 @@ ''' import unittest from test.test_support import requires -from Tkinter import Tk, Toplevel, Frame, Label, BooleanVar, StringVar +from Tkinter import Tk, Toplevel, Frame ## BooleanVar, StringVar from idlelib import SearchEngine as se from idlelib import SearchDialogBase as sdb from idlelib.idle_test.mock_idle import Func -from idlelib.idle_test.mock_tk import Var, Mbox +##from idlelib.idle_test.mock_tk import Var -# The following could help make some tests gui-free. -# However, they currently make radiobutton tests fail. +# The ## imports above & following could help make some tests gui-free.# However, they currently make radiobutton tests fail. ##def setUpModule(): ## # Replace tk objects used to initialize se.SearchEngine. ## se.BooleanVar = Var diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -7,7 +7,7 @@ import re import unittest -from test.test_support import requires +#from test.test_support import requires from Tkinter import BooleanVar, StringVar, TclError # ,Tk, Text import tkMessageBox from idlelib import SearchEngine as se diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -3,7 +3,6 @@ from test.test_support import requires from _tkinter import TclError -import Tkinter as tk class TextTest(object): diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -125,11 +125,9 @@ # # Due to a (mis-)feature of TkAqua the user will also see an empty Help # menu. - from Tkinter import Menu, Text, Text - from idlelib.EditorWindow import prepstr, get_accelerator + from Tkinter import Menu from idlelib import Bindings from idlelib import WindowList - from idlelib.MultiCall import MultiCallCreator closeItem = Bindings.menudefs[0][1][-2] diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -332,10 +332,7 @@ n = self.sock.send(s[:BUFSIZE]) except (AttributeError, TypeError): raise IOError, "socket no longer exists" - except socket.error: - raise - else: - s = s[n:] + s = s[n:] buffer = "" bufneed = 4 diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -1,5 +1,4 @@ import sys -import io import linecache import time import socket @@ -211,6 +210,8 @@ fn, ln, nm, line = tb[i] if nm == '?': nm = "-toplevel-" + if fn.startswith("ghi'*n text.translate(charmap) + def test_fake_error_class(self): + handlers = [ + codecs.strict_errors, + codecs.ignore_errors, + codecs.replace_errors, + codecs.backslashreplace_errors, + codecs.xmlcharrefreplace_errors, + ] + for cls in UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError: + class FakeUnicodeError(str): + __class__ = cls + for handler in handlers: + self.assertRaises(TypeError, handler, FakeUnicodeError()) + class FakeUnicodeError(Exception): + __class__ = cls + for handler in handlers: + with self.assertRaises((TypeError, FakeUnicodeError)): + handler(FakeUnicodeError()) + + def test_main(): test.test_support.run_unittest(CodecCallbackTest) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -5,6 +5,7 @@ import socket import errno import os +import tempfile import unittest TestCase = unittest.TestCase @@ -399,6 +400,22 @@ conn.sock = sock conn.request('GET', '/foo', body) self.assertTrue(sock.data.startswith(expected)) + self.assertIn('def test_send_file', sock.data) + + def test_send_tempfile(self): + expected = ('GET /foo HTTP/1.1\r\nHost: example.com\r\n' + 'Accept-Encoding: identity\r\nContent-Length: 9\r\n\r\n' + 'fake\ndata') + + with tempfile.TemporaryFile() as body: + body.write('fake\ndata') + body.seek(0) + + conn = httplib.HTTPConnection('example.com') + sock = FakeSocket(body) + conn.sock = sock + conn.request('GET', '/foo', body) + self.assertEqual(sock.data, expected) def test_send(self): expected = 'this is a test this is only a test' diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -56,6 +56,7 @@ # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() for safe in (2, 2.0, 2j, "abc", [3], (2,2), {3: 3}, uni("yaddayadda"), + bytearray(b"ghi"), True, False, None, self.a, self.b): # module-level convenience functions self.assertFalse(pprint.isrecursive(safe), @@ -125,21 +126,23 @@ # it sorted a dict display if and only if the display required # multiple lines. For that reason, dicts with more than one element # aren't tested here. - for simple in (0, 0L, 0+0j, 0.0, "", uni(""), + for simple in (0, 0L, 0+0j, 0.0, "", uni(""), bytearray(), (), tuple2(), tuple3(), [], list2(), list3(), set(), set2(), set3(), frozenset(), frozenset2(), frozenset3(), {}, dict2(), dict3(), self.assertTrue, pprint, - -6, -6L, -6-6j, -1.5, "x", uni("x"), (3,), [3], {3: 6}, + -6, -6L, -6-6j, -1.5, "x", uni("x"), bytearray(b"x"), + (3,), [3], {3: 6}, (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), set({7}), set2({7}), set3({7}), frozenset({8}), frozenset2({8}), frozenset3({8}), dict2({5: 6}), dict3({5: 6}), - range(10, -11, -1) + range(10, -11, -1), + True, False, None, ): native = repr(simple) self.assertEqual(pprint.pformat(simple), native) diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py --- a/Lib/test/test_slice.py +++ b/Lib/test/test_slice.py @@ -18,7 +18,8 @@ def test_hash(self): # Verify clearing of SF bug #800796 self.assertRaises(TypeError, hash, slice(5)) - self.assertRaises(TypeError, slice(5).__hash__) + with self.assertRaises(TypeError): + slice(5).__hash__() def test_cmp(self): s1 = slice(1, 2, 3) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -287,7 +287,42 @@ lambda: iter(names)) -class test__mkstemp_inner(TC): +class TestBadTempdir: + + def test_read_only_directory(self): + with _inside_empty_temp_dir(): + oldmode = mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + os.chmod(tempfile.tempdir, mode) + try: + if os.access(tempfile.tempdir, os.W_OK): + self.skipTest("can't set the directory read-only") + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertIn(cm.exception.errno, (errno.EPERM, errno.EACCES)) + self.assertEqual(os.listdir(tempfile.tempdir), []) + finally: + os.chmod(tempfile.tempdir, oldmode) + + def test_nonexisting_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'nonexistent') + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertEqual(cm.exception.errno, errno.ENOENT) + + def test_non_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'file') + open(tempdir, 'wb').close() + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(OSError) as cm: + self.make_temp() + self.assertIn(cm.exception.errno, (errno.ENOTDIR, errno.ENOENT)) + + +class test__mkstemp_inner(TestBadTempdir, TC): """Test the internal function _mkstemp_inner.""" class mkstemped: @@ -400,7 +435,7 @@ self.do_create(bin=0).write("blat\n") # XXX should test that the file really is a text file - def default_mkstemp_inner(self): + def make_temp(self): return tempfile._mkstemp_inner(tempfile.gettempdir(), tempfile.template, '', @@ -411,11 +446,11 @@ # the chosen name already exists with _inside_empty_temp_dir(), \ _mock_candidate_names('aaa', 'aaa', 'bbb'): - (fd1, name1) = self.default_mkstemp_inner() + (fd1, name1) = self.make_temp() os.close(fd1) self.assertTrue(name1.endswith('aaa')) - (fd2, name2) = self.default_mkstemp_inner() + (fd2, name2) = self.make_temp() os.close(fd2) self.assertTrue(name2.endswith('bbb')) @@ -427,7 +462,7 @@ dir = tempfile.mkdtemp() self.assertTrue(dir.endswith('aaa')) - (fd, name) = self.default_mkstemp_inner() + (fd, name) = self.make_temp() os.close(fd) self.assertTrue(name.endswith('bbb')) @@ -542,9 +577,12 @@ test_classes.append(test_mkstemp) -class test_mkdtemp(TC): +class test_mkdtemp(TestBadTempdir, TC): """Test mkdtemp().""" + def make_temp(self): + return tempfile.mkdtemp() + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir() diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -593,6 +593,63 @@ self.assertEqual(expect, self.module.formatwarning(message, category, file_name, line_num, file_line)) + @test_support.requires_unicode + def test_formatwarning_unicode_msg(self): + message = u"msg" + category = Warning + file_name = os.path.splitext(warning_tests.__file__)[0] + '.py' + line_num = 3 + file_line = linecache.getline(file_name, line_num).strip() + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num)) + # Test the 'line' argument. + file_line += " for the win!" + expect = format % (file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + + @test_support.requires_unicode + @unittest.skipUnless(test_support.FS_NONASCII, 'need test_support.FS_NONASCII') + def test_formatwarning_unicode_msg_nonascii_filename(self): + message = u"msg" + category = Warning + unicode_file_name = test_support.FS_NONASCII + u'.py' + file_name = unicode_file_name.encode(sys.getfilesystemencoding()) + line_num = 3 + file_line = 'spam' + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, str(message), + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + message = u"\xb5sg" + expect = format % (unicode_file_name, line_num, category.__name__, message, + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + + @test_support.requires_unicode + def test_formatwarning_unicode_msg_nonascii_fileline(self): + message = u"msg" + category = Warning + file_name = 'file.py' + line_num = 3 + file_line = 'sp\xe4m' + format = "%s:%s: %s: %s\n %s\n" + expect = format % (file_name, line_num, category.__name__, str(message), + file_line) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + message = u"\xb5sg" + expect = format % (file_name, line_num, category.__name__, message, + unicode(file_line, 'latin1')) + self.assertEqual(expect, self.module.formatwarning(message, + category, file_name, line_num, file_line)) + def test_showwarning(self): file_name = os.path.splitext(warning_tests.__file__)[0] + '.py' line_num = 3 diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -127,8 +127,6 @@ (expected_regexp.pattern, str(exc_value))) return True -def _sentinel(*args, **kwargs): - raise AssertionError('Should never be called') class TestCase(object): """A class whose instances are single test cases. @@ -445,7 +443,7 @@ return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg)) - def assertRaises(self, excClass, callableObj=_sentinel, *args, **kwargs): + def assertRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -453,7 +451,7 @@ deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted, will return a + If called with callableObj omitted or None, will return a context object used like this:: with self.assertRaises(SomeException): @@ -469,7 +467,7 @@ self.assertEqual(the_exception.error_code, 3) """ context = _AssertRaisesContext(excClass, self) - if callableObj is _sentinel: + if callableObj is None: return context with context: callableObj(*args, **kwargs) @@ -975,7 +973,7 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegexp(self, expected_exception, expected_regexp, - callable_obj=_sentinel, *args, **kwargs): + callable_obj=None, *args, **kwargs): """Asserts that the message in a raised exception matches a regexp. Args: @@ -989,7 +987,7 @@ if expected_regexp is not None: expected_regexp = re.compile(expected_regexp) context = _AssertRaisesContext(expected_exception, self, expected_regexp) - if callable_obj is _sentinel: + if callable_obj is None: return context with context: callable_obj(*args, **kwargs) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -967,9 +967,6 @@ # Failure when no exception is raised with self.assertRaises(self.failureException): self.assertRaises(ExceptionMock, lambda: 0) - # Failure when the function is None - with self.assertRaises(TypeError): - self.assertRaises(ExceptionMock, None) # Failure when another exception is raised with self.assertRaises(ExceptionMock): self.assertRaises(ValueError, Stub) @@ -1008,8 +1005,6 @@ self.assertRaisesRegexp(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegexp(ExceptionMock, 'expect$', Stub) self.assertRaisesRegexp(ExceptionMock, u'expect$', Stub) - with self.assertRaises(TypeError): - self.assertRaisesRegexp(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegexp(self): self.assertRaisesRegexp( diff --git a/Lib/warnings.py b/Lib/warnings.py --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -31,7 +31,7 @@ return try: file.write(formatwarning(message, category, filename, lineno, line)) - except IOError: + except (IOError, UnicodeError): pass # the file (probably stderr) is invalid - this warning gets lost. # Keep a working version around in case the deprecation of the old API is # triggered. @@ -39,11 +39,29 @@ def formatwarning(message, category, filename, lineno, line=None): """Function to format a warning the standard way.""" - s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message) + try: + unicodetype = unicode + except NameError: + unicodetype = () + try: + message = str(message) + except UnicodeEncodeError: + pass + s = "%s: %s: %s\n" % (lineno, category.__name__, message) line = linecache.getline(filename, lineno) if line is None else line if line: line = line.strip() + if isinstance(s, unicodetype) and isinstance(line, str): + line = unicode(line, 'latin1') s += " %s\n" % line + if isinstance(s, unicodetype) and isinstance(filename, str): + enc = sys.getfilesystemencoding() + if enc: + try: + filename = unicode(filename, enc) + except UnicodeDecodeError: + pass + s = "%s:%s" % (filename, s) return s def filterwarnings(action, message="", category=Warning, module="", lineno=0, diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1159,6 +1159,7 @@ Just van Rossum Hugo van Rossum Saskia van Rossum +Clement Rouault Donald Wallace Rouse II Liam Routt Todd Rovito diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,60 @@ Python News +++++++++++ +What's New in Python 2.7.11? +============================ + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +- Issue #22939: Fixed integer overflow in iterator object. Original patch by + Clement Rouault. + +- Issue #24102: Fixed exception type checking in standard error handlers. + +Library +------- + +- Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked + cursor type. + +- Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again + when a directory with the chosen name already exists on Windows as well as + on Unix. tempfile.mkstemp() now fails early if parent directory is not + valid (not exists or is a file) on Windows. + +- Issue #6598: Increased time precision and random number range in + email.utils.make_msgid() to strengthen the uniqueness of the message ID. + +- Issue #24091: Fixed various crashes in corner cases in cElementTree. + +- Issue #15267: HTTPConnection.request() now is compatibile with old-style + classes (such as TemporaryFile). Original patch by Atsuo Ishimoto. + +- Issue #20014: array.array() now accepts unicode typecodes. Based on patch by + Vajrasky Kok. + +- Issue #23637: Showing a warning no longer fails with UnicodeErrror. + Formatting unicode warning in the file with the path containing non-ascii + characters no longer fails with UnicodeErrror. + +- Issue #24134: Reverted issue #24134 changes. + +IDLE +---- + +- Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for + decoding unicode literals. + +Documentation +------------- + +- Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter + doc. Remove obsolete example from FAQ. Patch by Martin Panter. + + What's New in Python 2.7.10? ============================ @@ -12,7 +66,6 @@ - Issue #22931: Allow '[' and ']' in cookie values. - What's New in Python 2.7.10 release candidate 1? ================================================ @@ -24,6 +77,11 @@ - Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. +- Issue #23971: Fix underestimated presizing in dict.fromkeys(). + +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API + when the data was a list subclass. + - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -289,9 +289,9 @@ from that file; when called with .B \-c -.I command, +.IR command , it executes the Python statement(s) given as -.I command. +.IR command . Here .I command may contain multiple statements separated by newlines. @@ -301,7 +301,7 @@ .PP If available, the script name and additional arguments thereafter are passed to the script in the Python variable -.I sys.argv , +.IR sys.argv , which is a list of strings (you must first .I import sys to be able to access it). @@ -315,14 +315,14 @@ .I '-c'. Note that options interpreted by the Python interpreter itself are not placed in -.I sys.argv. +.IR sys.argv . .PP In interactive mode, the primary prompt is `>>>'; the second prompt (which appears when a command is not complete) is `...'. The prompts can be changed by assignment to .I sys.ps1 or -.I sys.ps2. +.IR sys.ps2 . The interpreter quits when it reads an EOF at a prompt. When an unhandled exception occurs, a stack trace is printed and control returns to the primary prompt; in non-interactive mode, the @@ -381,7 +381,7 @@ inserted in the path in front of $PYTHONPATH. The search path can be manipulated from within a Python program as the variable -.I sys.path . +.IR sys.path . .IP PYTHONSTARTUP If this is the name of a readable file, the Python commands in that file are executed before the first prompt is displayed in interactive @@ -452,7 +452,7 @@ the value 0 will lead to the same hash values as when hash randomization is disabled. .SH AUTHOR -The Python Software Foundation: https://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES Main website: https://www.python.org/ .br diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -756,7 +756,7 @@ element_extend(ElementObject* self, PyObject* args) { PyObject* seq; - Py_ssize_t i, seqlen = 0; + Py_ssize_t i; PyObject* seq_in; if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) @@ -771,8 +771,7 @@ return NULL; } - seqlen = PySequence_Size(seq); - for (i = 0; i < seqlen; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) { PyObject* element = PySequence_Fast_GET_ITEM(seq, i); if (element_add_subelement(self, element) < 0) { Py_DECREF(seq); @@ -805,11 +804,16 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { - Py_INCREF(item); + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(((ElementObject*)item)->tag, tag); + if (rc == 0) return item; - } + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) + return NULL; } Py_RETURN_NONE; @@ -838,13 +842,24 @@ for (i = 0; i < self->extra->length; i++) { ElementObject* item = (ElementObject*) self->extra->children[i]; - if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(item->tag, tag); + if (rc == 0) { PyObject* text = element_get_text(item); - if (text == Py_None) + if (text == Py_None) { + Py_DECREF(item); return PyString_FromString(""); + } Py_XINCREF(text); + Py_DECREF(item); return text; } + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) + return NULL; } Py_INCREF(default_value); @@ -876,12 +891,17 @@ for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; - if (Element_CheckExact(item) && - PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { - if (PyList_Append(out, item) < 0) { - Py_DECREF(out); - return NULL; - } + int rc; + if (!Element_CheckExact(item)) + continue; + Py_INCREF(item); + rc = PyObject_Compare(((ElementObject*)item)->tag, tag); + if (rc == 0) + rc = PyList_Append(out, item); + Py_DECREF(item); + if (rc < 0 && PyErr_Occurred()) { + Py_DECREF(out); + return NULL; } } @@ -1147,8 +1167,10 @@ element_remove(ElementObject* self, PyObject* args) { int i; - + int rc; PyObject* element; + PyObject* found; + if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element)) return NULL; @@ -1164,11 +1186,14 @@ for (i = 0; i < self->extra->length; i++) { if (self->extra->children[i] == element) break; - if (PyObject_Compare(self->extra->children[i], element) == 0) + rc = PyObject_Compare(self->extra->children[i], element); + if (rc == 0) break; + if (rc < 0 && PyErr_Occurred()) + return NULL; } - if (i == self->extra->length) { + if (i >= self->extra->length) { /* element is not in children, so raise exception */ PyErr_SetString( PyExc_ValueError, @@ -1177,13 +1202,13 @@ return NULL; } - Py_DECREF(self->extra->children[i]); + found = self->extra->children[i]; self->extra->length--; - for (; i < self->extra->length; i++) self->extra->children[i] = self->extra->children[i+1]; + Py_DECREF(found); Py_RETURN_NONE; } diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -244,6 +244,11 @@ return item; } + if (PyList_GET_SIZE(heap) == 0) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; + } + returnitem = PyList_GET_ITEM(heap, 0); Py_INCREF(item); PyList_SET_ITEM(heap, 0, item); diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -47,7 +47,7 @@ if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) return NULL; - if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { + if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return NULL; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1928,16 +1928,28 @@ static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - char c; - PyObject *initial = NULL, *it = NULL; + int c = -1; + PyObject *initial = NULL, *it = NULL, *typecode = NULL; struct arraydescr *descr; if (type == &Arraytype && !_PyArg_NoKeywords("array.array()", kwds)) return NULL; - if (!PyArg_ParseTuple(args, "c|O:array", &c, &initial)) + if (!PyArg_ParseTuple(args, "O|O:array", &typecode, &initial)) return NULL; + if (PyString_Check(typecode) && PyString_GET_SIZE(typecode) == 1) + c = (unsigned char)*PyString_AS_STRING(typecode); + else if (PyUnicode_Check(typecode) && PyUnicode_GET_SIZE(typecode) == 1) + c = *PyUnicode_AS_UNICODE(typecode); + else { + PyErr_Format(PyExc_TypeError, + "array() argument 1 or typecode must be char (string or " + "ascii-unicode with length 1), not %s", + Py_TYPE(typecode)->tp_name); + return NULL; + } + if (!(initial == NULL || PyList_Check(initial) || PyString_Check(initial) || PyTuple_Check(initial) || (c == 'u' && PyUnicode_Check(initial)))) { diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2169,7 +2169,7 @@ Py_INCREF(v); return v; } - if (PyList_Check(v)) + if (PyList_CheckExact(v)) return PyList_AsTuple(v); /* Get iterator. */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1361,7 +1361,7 @@ PyObject *key; long hash; - if (dictresize(mp, Py_SIZE(seq))) { + if (dictresize(mp, Py_SIZE(seq) / 2 * 3)) { Py_DECREF(d); return NULL; } @@ -1382,7 +1382,7 @@ PyObject *key; long hash; - if (dictresize(mp, PySet_GET_SIZE(seq))) { + if (dictresize(mp, PySet_GET_SIZE(seq) / 2 * 3)) { Py_DECREF(d); return NULL; } diff --git a/Objects/iterobject.c b/Objects/iterobject.c --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -54,6 +54,11 @@ seq = it->it_seq; if (seq == NULL) return NULL; + if (it->it_index == LONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "iter index too large"); + return NULL; + } result = PySequence_GetItem(seq, it->it_index); if (result != NULL) { diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -472,15 +472,16 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -500,7 +501,7 @@ Py_ssize_t end; Py_ssize_t i; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *res; Py_UNICODE *p; if (PyUnicodeEncodeError_GetStart(exc, &start)) @@ -517,13 +518,13 @@ Py_DECREF(res); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER; if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; return Py_BuildValue("(u#n)", &res, (Py_ssize_t)1, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) { PyObject *res; Py_UNICODE *p; if (PyUnicodeTranslateError_GetStart(exc, &start)) @@ -548,7 +549,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t start; @@ -673,7 +674,7 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t start; diff --git a/Tools/msi/uuids.py b/Tools/msi/uuids.py --- a/Tools/msi/uuids.py +++ b/Tools/msi/uuids.py @@ -68,4 +68,6 @@ '2.7.8150':'{61121B12-88BD-4261-A6EE-AB32610A56DD}', # 2.7.8 '2.7.9121':'{AAB1E8FF-6D00-4409-8F13-BE365AB92FFE}', # 2.7.9rc1 '2.7.9150':'{79F081BF-7454-43DB-BD8F-9EE596813232}', # 2.7.9 + '2.7.10121':'{872BE558-2E5F-4E9C-A42D-8561FA43811C}', # 2.7.10rc1 + '2.7.10150':'{E2B51919-207A-43EB-AE78-733F9C6797C2}', # 2.7.10 } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 17:57:10 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 15:57:10 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_write_access_to_SVN=3F_I_thin?= =?utf-8?q?k_not?= Message-ID: <20150523155710.17941.14577@psf.io> https://hg.python.org/peps/rev/3507b104c54c changeset: 5877:3507b104c54c user: Benjamin Peterson date: Sat May 23 10:57:06 2015 -0500 summary: write access to SVN? I think not files: pep-0101.txt | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -41,12 +41,6 @@ * Shell access to ``hg.python.org``, the Python Mercurial host. You'll have to adapt repository configuration there. - * Write access to the website SVN repository - - Instructions here: - - http://www.python.org/dev/pydotorg/website/ - * Write access to the PEP repository. If you're reading this, you probably already have this--the first -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat May 23 17:58:10 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 23 May 2015 15:58:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324269=3A_Minor_do?= =?utf-8?q?c_fixups=2E?= Message-ID: <20150523155809.27929.5806@psf.io> https://hg.python.org/cpython/rev/4d92ce08de6a changeset: 96236:4d92ce08de6a parent: 96233:c58f3e76dc6c user: Raymond Hettinger date: Sat May 23 08:57:58 2015 -0700 summary: Issue #24269: Minor doc fixups. files: Doc/library/collections.rst | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -387,7 +387,7 @@ Section 4.6.3, Exercise 19*. * To enumerate all distinct multisets of a given size over a given set of - elements, see :func:`itertools.combinations_with_replacement`. + elements, see :func:`itertools.combinations_with_replacement`: map(Counter, combinations_with_replacement('ABC', 2)) --> AA AB AC BB BC CC @@ -464,10 +464,11 @@ elements in the iterable argument. - .. method:: index(x[, start[, end]]) + .. method:: index(x[, start[, stop]]) - Return the position of *x* in the deque. Returns the first match - or raises :exc:`ValueError` if not found. + Return the position of *x* in the deque (at or after index *start* + and before index *stop*). Returns the first match or raises + :exc:`ValueError` if not found. .. versionadded:: 3.5 @@ -493,7 +494,7 @@ .. 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`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:00:08 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 16:00:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixes_cast_warning_in_buff?= =?utf-8?q?eredio=2Ec?= Message-ID: <20150523160005.96198.97998@psf.io> https://hg.python.org/cpython/rev/366e8aa65902 changeset: 96237:366e8aa65902 user: Steve Dower date: Sat May 23 08:59:25 2015 -0700 summary: Fixes cast warning in bufferedio.c files: Modules/_io/bufferedio.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -297,7 +297,7 @@ * Note that non-daemon threads have already exited here, so this * shouldn't affect carefully written threaded I/O code. */ - st = PyThread_acquire_lock_timed(self->lock, 1e6, 0); + st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0); } Py_END_ALLOW_THREADS if (relax_locking && st != PY_LOCK_ACQUIRED) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:00:08 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 16:00:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324268=3A_Fixes_ge?= =?utf-8?q?neration_of_init_import_name_on_Windows=2E?= Message-ID: <20150523160005.96198.96049@psf.io> https://hg.python.org/cpython/rev/a811f5561c99 changeset: 96238:a811f5561c99 user: Steve Dower date: Sat May 23 08:59:25 2015 -0700 summary: Issue #24268: Fixes generation of init import name on Windows. files: Python/dynload_win.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/dynload_win.c b/Python/dynload_win.c --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -202,7 +202,7 @@ if (wpathname == NULL) return NULL; - PyOS_snprintf(funcname, sizeof(funcname), "%20_%.200s", prefix, shortname); + PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname); { HINSTANCE hDLL = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:04:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 16:04:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogMi43LjEwKw==?= Message-ID: <20150523160406.17939.72062@psf.io> https://hg.python.org/cpython/rev/df37c0893816 changeset: 96242:df37c0893816 branch: 2.7 user: Benjamin Peterson date: Sat May 23 11:03:53 2015 -0500 summary: 2.7.10+ files: Include/patchlevel.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.10" +#define PY_VERSION "2.7.10+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:04:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 16:04:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge_2=2E7=2E10_release_branch?= Message-ID: <20150523160406.16307.78688@psf.io> https://hg.python.org/cpython/rev/ccecc8a91eed changeset: 96241:ccecc8a91eed branch: 2.7 parent: 96235:115d46d16b97 parent: 96240:a2548573e2e6 user: Benjamin Peterson date: Sat May 23 11:03:20 2015 -0500 summary: merge 2.7.10 release branch files: .hgtags | 1 + Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -169,3 +169,4 @@ 40eada278702349a2b2f334aa9d91fa7090ea1e3 v2.7.9rc1 648dcafa7e5f40da31079bc7a7f0c445f1ea4ab9 v2.7.9 80ccce248ba2657ed5da3ccf7999f35b78827f5e v2.7.10rc1 +15c95b7d81dcf821daade360741e00714667653f v2.7.10 diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 10 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.10rc1" +#define PY_VERSION "2.7.10" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.10rc1" +__version__ = "2.7.10" #--end constants-- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:04:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 16:04:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_tag_v2?= =?utf-8?q?=2E7=2E10_for_changeset_15c95b7d81dc?= Message-ID: <20150523160406.27933.89152@psf.io> https://hg.python.org/cpython/rev/a2548573e2e6 changeset: 96240:a2548573e2e6 branch: 2.7 user: Benjamin Peterson date: Sat May 23 11:02:34 2015 -0500 summary: Added tag v2.7.10 for changeset 15c95b7d81dc files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -169,3 +169,4 @@ 40eada278702349a2b2f334aa9d91fa7090ea1e3 v2.7.9rc1 648dcafa7e5f40da31079bc7a7f0c445f1ea4ab9 v2.7.9 80ccce248ba2657ed5da3ccf7999f35b78827f5e v2.7.10rc1 +15c95b7d81dcf821daade360741e00714667653f v2.7.10 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:04:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 23 May 2015 16:04:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogcHl0aG9uIDIuNy4x?= =?utf-8?q?0_final?= Message-ID: <20150523160406.126978.73478@psf.io> https://hg.python.org/cpython/rev/15c95b7d81dc changeset: 96239:15c95b7d81dc branch: 2.7 tag: v2.7.10 parent: 96234:2a7b0e145945 user: Benjamin Peterson date: Sat May 23 11:02:14 2015 -0500 summary: python 2.7.10 final files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 10 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.10rc1" +#define PY_VERSION "2.7.10" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.10rc1" +__version__ = "2.7.10" #--end constants-- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:04:47 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 16:04:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323970=3A_Adds_dis?= =?utf-8?q?tutils=2E=5Fmsvccompiler_for_new_Visual_Studio_versions=2E?= Message-ID: <20150523160446.126982.9305@psf.io> https://hg.python.org/cpython/rev/b2ee6206fa5e changeset: 96243:b2ee6206fa5e parent: 96238:a811f5561c99 user: Steve Dower date: Sat May 23 09:02:50 2015 -0700 summary: Issue #23970: Adds distutils._msvccompiler for new Visual Studio versions. files: Lib/distutils/msvccompiler.py | 686 ++++----- Lib/distutils/ccompiler.py | 2 +- Lib/distutils/command/bdist_wininst.py | 31 +- Lib/distutils/command/build_ext.py | 34 +- Lib/distutils/tests/test_msvc9compiler.py | 52 +- Lib/test/test_sundry.py | 2 - 6 files changed, 346 insertions(+), 461 deletions(-) diff --git a/Lib/distutils/msvccompiler.py b/Lib/distutils/_msvccompiler.py copy from Lib/distutils/msvccompiler.py copy to Lib/distutils/_msvccompiler.py --- a/Lib/distutils/msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -1,201 +1,120 @@ -"""distutils.msvccompiler +"""distutils._msvccompiler Contains MSVCCompiler, an implementation of the abstract CCompiler class -for the Microsoft Visual Studio. +for Microsoft Visual Studio 2015. + +The module is compatible with VS 2015 and later. You can find legacy support +for older versions in distutils.msvc9compiler and distutils.msvccompiler. """ # Written by Perry Stoll # hacked by Robin Becker and Thomas Heller to do a better job of # finding DevStudio (through the registry) +# ported to VS 2005 and VS 2008 by Christian Heimes +# ported to VS 2015 by Steve Dower -import sys, os -from distutils.errors import \ - DistutilsExecError, DistutilsPlatformError, \ - CompileError, LibError, LinkError -from distutils.ccompiler import \ - CCompiler, gen_preprocess_options, gen_lib_options +import os +import subprocess +import re + +from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import CCompiler, gen_lib_options from distutils import log +from distutils.util import get_platform -_can_read_reg = False -try: - import winreg +import winreg +from itertools import count - _can_read_reg = True - hkey_mod = winreg +def _find_vcvarsall(): + with winreg.OpenKeyEx( + winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\VisualStudio\SxS\VC7", + access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY + ) as key: + if not key: + log.debug("Visual C++ is not registered") + return None - RegOpenKeyEx = winreg.OpenKeyEx - RegEnumKey = winreg.EnumKey - RegEnumValue = winreg.EnumValue - RegError = winreg.error + best_version = 0 + best_dir = None + for i in count(): + try: + v, vc_dir, vt = winreg.EnumValue(key, i) + except OSError: + break + if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir): + try: + version = int(float(v)) + except (ValueError, TypeError): + continue + if version >= 14 and version > best_version: + best_version, best_dir = version, vc_dir + if not best_version: + log.debug("No suitable Visual C++ version found") + return None -except ImportError: + vcvarsall = os.path.join(best_dir, "vcvarsall.bat") + if not os.path.isfile(vcvarsall): + log.debug("%s cannot be found", vcvarsall) + return None + + return vcvarsall + +def _get_vc_env(plat_spec): + if os.getenv("DISTUTILS_USE_SDK"): + return { + key.lower(): value + for key, value in os.environ.items() + } + + vcvarsall = _find_vcvarsall() + if not vcvarsall: + raise DistutilsPlatformError("Unable to find vcvarsall.bat") + try: - import win32api - import win32con - _can_read_reg = True - hkey_mod = win32con + out = subprocess.check_output( + '"{}" {} && set'.format(vcvarsall, plat_spec), + shell=True, + stderr=subprocess.STDOUT, + universal_newlines=True, + ) + except subprocess.CalledProcessError as exc: + log.error(exc.output) + raise DistutilsPlatformError("Error executing {}" + .format(exc.cmd)) - RegOpenKeyEx = win32api.RegOpenKeyEx - RegEnumKey = win32api.RegEnumKey - RegEnumValue = win32api.RegEnumValue - RegError = win32api.error - except ImportError: - log.info("Warning: Can't read registry to find the " - "necessary compiler setting\n" - "Make sure that Python modules winreg, " - "win32api or win32con are installed.") - pass + return { + key.lower(): value + for key, _, value in + (line.partition('=') for line in out.splitlines()) + if key and value + } -if _can_read_reg: - HKEYS = (hkey_mod.HKEY_USERS, - hkey_mod.HKEY_CURRENT_USER, - hkey_mod.HKEY_LOCAL_MACHINE, - hkey_mod.HKEY_CLASSES_ROOT) +def _find_exe(exe, paths=None): + """Return path to an MSVC executable program. -def read_keys(base, key): - """Return list of registry keys.""" - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - L = [] - i = 0 - while True: - try: - k = RegEnumKey(handle, i) - except RegError: - break - L.append(k) - i += 1 - return L + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + if not paths: + paths = os.getenv('path').split(os.pathsep) + for p in paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + return exe -def read_values(base, key): - """Return dict of registry keys and values. - - All names are converted to lowercase. - """ - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - d = {} - i = 0 - while True: - try: - name, value, type = RegEnumValue(handle, i) - except RegError: - break - name = name.lower() - d[convert_mbcs(name)] = convert_mbcs(value) - i += 1 - return d - -def convert_mbcs(s): - dec = getattr(s, "decode", None) - if dec is not None: - try: - s = dec("mbcs") - except UnicodeError: - pass - return s - -class MacroExpander: - def __init__(self, version): - self.macros = {} - self.load_macros(version) - - def set_macro(self, macro, path, key): - for base in HKEYS: - d = read_values(base, path) - if d: - self.macros["$(%s)" % macro] = d[key] - break - - def load_macros(self, version): - vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version - self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir") - self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir") - net = r"Software\Microsoft\.NETFramework" - self.set_macro("FrameworkDir", net, "installroot") - try: - if version > 7.0: - self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") - else: - self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") - except KeyError as exc: # - raise DistutilsPlatformError( - """Python was built with Visual Studio 2003; -extensions must be built with a compiler than can generate compatible binaries. -Visual Studio 2003 was not found on this system. If you have Cygwin installed, -you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") - - p = r"Software\Microsoft\NET Framework Setup\Product" - for base in HKEYS: - try: - h = RegOpenKeyEx(base, p) - except RegError: - continue - key = RegEnumKey(h, 0) - d = read_values(base, r"%s\%s" % (p, key)) - self.macros["$(FrameworkVersion)"] = d["version"] - - def sub(self, s): - for k, v in self.macros.items(): - s = s.replace(k, v) - return s - -def get_build_version(): - """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. - """ - prefix = "MSC v." - i = sys.version.find(prefix) - if i == -1: - return 6 - i = i + len(prefix) - s, rest = sys.version[i:].split(" ", 1) - majorVersion = int(s[:-2]) - 6 - if majorVersion >= 13: - # v13 was skipped and should be v14 - majorVersion += 1 - minorVersion = int(s[2:3]) / 10.0 - # I don't think paths are affected by minor version in version 6 - if majorVersion == 6: - minorVersion = 0 - if majorVersion >= 6: - return majorVersion + minorVersion - # else we don't know what version of the compiler this is - return None - -def get_build_architecture(): - """Return the processor architecture. - - Possible results are "Intel", "Itanium", or "AMD64". - """ - - prefix = " bit (" - i = sys.version.find(prefix) - if i == -1: - return "Intel" - j = sys.version.find(")", i) - return sys.version[i+len(prefix):j] - -def normalize_and_reduce_paths(paths): - """Return a list of normalized paths with duplicates removed. - - The current order of paths is maintained. - """ - # Paths are normalized so things like: /a and /a/ aren't both preserved. - reduced_paths = [] - for p in paths: - np = os.path.normpath(p) - # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. - if np not in reduced_paths: - reduced_paths.append(np) - return reduced_paths - +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is +# the param to cross-compile on x86 targetting amd64.) +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'amd64', +} class MSVCCompiler(CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, @@ -227,83 +146,75 @@ static_lib_format = shared_lib_format = '%s%s' exe_extension = '.exe' + def __init__(self, verbose=0, dry_run=0, force=0): CCompiler.__init__ (self, verbose, dry_run, force) - self.__version = get_build_version() - self.__arch = get_build_architecture() - if self.__arch == "Intel": - # x86 - if self.__version >= 7: - self.__root = r"Software\Microsoft\VisualStudio" - self.__macros = MacroExpander(self.__version) - else: - self.__root = r"Software\Microsoft\Devstudio" - self.__product = "Visual Studio version %s" % self.__version - else: - # Win64. Assume this was built with the platform SDK - self.__product = "Microsoft SDK compiler %s" % (self.__version + 6) - + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None self.initialized = False - def initialize(self): - self.__paths = [] - if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): - # Assume that the SDK set up everything alright; don't try to be - # smarter - self.cc = "cl.exe" - self.linker = "link.exe" - self.lib = "lib.exe" - self.rc = "rc.exe" - self.mc = "mc.exe" + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + if plat_name not in PLAT_TO_VCVARS: + raise DistutilsPlatformError("--plat-name must be one of {}" + .format(tuple(PLAT_TO_VCVARS))) + + # On x86, 'vcvarsall.bat amd64' creates an env that doesn't work; + # to cross compile, you use 'x86_amd64'. + # On AMD64, 'vcvarsall.bat amd64' is a native build env; to cross + # compile use 'x86' (ie, it runs the x86 compiler directly) + if plat_name == get_platform() or plat_name == 'win32': + # native build or cross-compile to win32 + plat_spec = PLAT_TO_VCVARS[plat_name] else: - self.__paths = self.get_msvc_paths("path") + # cross compile from win32 -> some 64bit + plat_spec = '{}_{}'.format( + PLAT_TO_VCVARS[get_platform()], + PLAT_TO_VCVARS[plat_name] + ) - if len(self.__paths) == 0: - raise DistutilsPlatformError("Python was built with %s, " - "and extensions need to be built with the same " - "version of the compiler, but it isn't installed." - % self.__product) + vc_env = _get_vc_env(plat_spec) + if not vc_env: + raise DistutilsPlatformError("Unable to find a compatible " + "Visual Studio installation.") - self.cc = self.find_exe("cl.exe") - self.linker = self.find_exe("link.exe") - self.lib = self.find_exe("lib.exe") - self.rc = self.find_exe("rc.exe") # resource compiler - self.mc = self.find_exe("mc.exe") # message compiler - self.set_path_env_var('lib') - self.set_path_env_var('include') + paths = vc_env.get('path', '').split(os.pathsep) + self.cc = _find_exe("cl.exe", paths) + self.linker = _find_exe("link.exe", paths) + self.lib = _find_exe("lib.exe", paths) + self.rc = _find_exe("rc.exe", paths) # resource compiler + self.mc = _find_exe("mc.exe", paths) # message compiler + self.mt = _find_exe("mt.exe", paths) # message compiler - # extend the MSVC path with the current path - try: - for p in os.environ['path'].split(';'): - self.__paths.append(p) - except KeyError: - pass - self.__paths = normalize_and_reduce_paths(self.__paths) - os.environ['path'] = ";".join(self.__paths) + for dir in vc_env.get('include', '').split(os.pathsep): + if dir: + self.add_include_dir(dir) + + for dir in vc_env.get('lib', '').split(os.pathsep): + if dir: + self.add_library_dir(dir) self.preprocess_options = None - if self.__arch == "Intel": - self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' , - '/DNDEBUG'] - self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX', - '/Z7', '/D_DEBUG'] - else: - # Win64 - self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' , - '/DNDEBUG'] - self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', - '/Z7', '/D_DEBUG'] + self.compile_options = [ + '/nologo', '/Ox', '/MD', '/W3', '/GL', '/DNDEBUG' + ] + self.compile_options_debug = [ + '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' + ] - self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] - if self.__version >= 7: - self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' - ] - else: - self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG' - ] - self.ldflags_static = [ '/nologo'] + self.ldflags_shared = [ + '/nologo', '/DLL', '/INCREMENTAL:NO' + ] + self.ldflags_shared_debug = [ + '/nologo', '/DLL', '/INCREMENTAL:no', '/DEBUG:FULL' + ] + self.ldflags_static = [ + '/nologo' + ] self.initialized = True @@ -313,31 +224,31 @@ source_filenames, strip_dir=0, output_dir=''): - # Copied from ccompiler.py, extended to return .res as 'object'-file - # for .rc input file - if output_dir is None: output_dir = '' - obj_names = [] - for src_name in source_filenames: - (base, ext) = os.path.splitext (src_name) - base = os.path.splitdrive(base)[1] # Chop off the drive - base = base[os.path.isabs(base):] # If abs, chop off leading / - if ext not in self.src_extensions: + ext_map = {ext: self.obj_extension for ext in self.src_extensions} + ext_map.update((ext, self.res_extension) + for ext in self._rc_extensions + self._mc_extensions) + + def make_out_path(p): + base, ext = os.path.splitext(p) + if strip_dir: + base = os.path.basename(base) + else: + _, base = os.path.splitdrive(base) + if base.startswith((os.path.sep, os.path.altsep)): + base = base[1:] + try: + return base + ext_map[ext] + except LookupError: # Better to raise an exception instead of silently continuing # and later complain about sources and targets having # different lengths - raise CompileError ("Don't know how to compile %s" % src_name) - if strip_dir: - base = os.path.basename (base) - if ext in self._rc_extensions: - obj_names.append (os.path.join (output_dir, - base + self.res_extension)) - elif ext in self._mc_extensions: - obj_names.append (os.path.join (output_dir, - base + self.res_extension)) - else: - obj_names.append (os.path.join (output_dir, - base + self.obj_extension)) - return obj_names + raise CompileError("Don't know how to compile {}".format(p)) + + output_dir = output_dir or '' + return [ + os.path.join(output_dir, make_out_path(src_name)) + for src_name in source_filenames + ] def compile(self, sources, @@ -351,12 +262,15 @@ macros, objects, extra_postargs, pp_opts, build = compile_info compile_opts = extra_preargs or [] - compile_opts.append ('/c') + compile_opts.append('/c') if debug: compile_opts.extend(self.compile_options_debug) else: compile_opts.extend(self.compile_options) + + add_cpp_opts = False + for obj in objects: try: src, ext = build[obj] @@ -372,13 +286,13 @@ input_opt = "/Tc" + src elif ext in self._cpp_extensions: input_opt = "/Tp" + src + add_cpp_opts = True elif ext in self._rc_extensions: # compile .RC to .RES file input_opt = src output_opt = "/fo" + obj try: - self.spawn([self.rc] + pp_opts + - [output_opt] + [input_opt]) + self.spawn([self.rc] + pp_opts + [output_opt, input_opt]) except DistutilsExecError as msg: raise CompileError(msg) continue @@ -398,27 +312,29 @@ rc_dir = os.path.dirname(obj) try: # first compile .MC to .RC and .H file - self.spawn([self.mc] + - ['-h', h_dir, '-r', rc_dir] + [src]) - base, _ = os.path.splitext (os.path.basename (src)) - rc_file = os.path.join (rc_dir, base + '.rc') + self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src]) + base, _ = os.path.splitext(os.path.basename (src)) + rc_file = os.path.join(rc_dir, base + '.rc') # then compile .RC to .RES file - self.spawn([self.rc] + - ["/fo" + obj] + [rc_file]) + self.spawn([self.rc, "/fo" + obj, rc_file]) except DistutilsExecError as msg: raise CompileError(msg) continue else: # how to handle this file? - raise CompileError("Don't know how to compile %s to %s" - % (src, obj)) + raise CompileError("Don't know how to compile {} to {}" + .format(src, obj)) - output_opt = "/Fo" + obj + args = [self.cc] + compile_opts + pp_opts + if add_cpp_opts: + args.append('/EHsc') + args.append(input_opt) + args.append("/Fo" + obj) + args.extend(extra_postargs) + try: - self.spawn([self.cc] + compile_opts + pp_opts + - [input_opt, output_opt] + - extra_postargs) + self.spawn(args) except DistutilsExecError as msg: raise CompileError(msg) @@ -434,7 +350,7 @@ if not self.initialized: self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) + objects, output_dir = self._fix_object_args(objects, output_dir) output_filename = self.library_filename(output_libname, output_dir=output_dir) @@ -467,14 +383,14 @@ if not self.initialized: self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) + objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) - (libraries, library_dirs, runtime_library_dirs) = fixed_args + libraries, library_dirs, runtime_library_dirs = fixed_args if runtime_library_dirs: - self.warn ("I don't know what to do with 'runtime_library_dirs': " - + str (runtime_library_dirs)) + self.warn("I don't know what to do with 'runtime_library_dirs': " + + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, @@ -483,16 +399,10 @@ output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): + ldflags = (self.ldflags_shared_debug if debug + else self.ldflags_shared) if target_desc == CCompiler.EXECUTABLE: - if debug: - ldflags = self.ldflags_shared_debug[1:] - else: - ldflags = self.ldflags_shared[1:] - else: - if debug: - ldflags = self.ldflags_shared_debug - else: - ldflags = self.ldflags_shared + ldflags = ldflags[1:] export_opts = [] for sym in (export_symbols or []): @@ -506,14 +416,17 @@ # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext( os.path.basename(output_filename)) implib_file = os.path.join( - os.path.dirname(objects[0]), + build_temp, self.library_filename(dll_name)) ld_args.append ('/IMPLIB:' + implib_file) + self.manifest_setup_ldargs(output_filename, build_temp, ld_args) + if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: @@ -525,9 +438,97 @@ except DistutilsExecError as msg: raise LinkError(msg) + # embed the manifest + # XXX - this is somewhat fragile - if mt.exe fails, distutils + # will still consider the DLL up-to-date, but it will not have a + # manifest. Maybe we should link to a temp file? OTOH, that + # implies a build environment error that shouldn't go undetected. + mfinfo = self.manifest_get_embed_info(target_desc, ld_args) + if mfinfo is not None: + mffilename, mfid = mfinfo + out_arg = '-outputresource:{};{}'.format(output_filename, mfid) + try: + self.spawn([self.mt, '-nologo', '-manifest', + mffilename, out_arg]) + except DistutilsExecError as msg: + raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + # If we need a manifest at all, an embedded manifest is recommended. + # See MSDN article titled + # "How to: Embed a Manifest Inside a C/C++ Application" + # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) + # Ask the linker to generate the manifest in the temp dir, so + # we can check it, and possibly embed it, later. + temp_manifest = os.path.join( + build_temp, + os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFESTFILE:' + temp_manifest) + + def manifest_get_embed_info(self, target_desc, ld_args): + # If a manifest should be embedded, return a tuple of + # (manifest_filename, resource_id). Returns None if no manifest + # should be embedded. See http://bugs.python.org/issue7833 for why + # we want to avoid any manifest for extension modules if we can) + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + temp_manifest = arg.split(":", 1)[1] + break + else: + # no /MANIFESTFILE so nothing to do. + return None + if target_desc == CCompiler.EXECUTABLE: + # by default, executables always get the manifest with the + # CRT referenced. + mfid = 1 + else: + # Extension modules try and avoid any manifest if possible. + mfid = 2 + temp_manifest = self._remove_visual_c_ref(temp_manifest) + if temp_manifest is None: + return None + return temp_manifest, mfid + + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + # Returns either the filename of the modified manifest or + # None if no manifest should be embedded. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""|)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = "\s*" + manifest_buf = re.sub(pattern, "", manifest_buf) + # Now see if any other assemblies are referenced - if not, we + # don't want a manifest embedded. + pattern = re.compile( + r"""|)""", re.DOTALL) + if re.search(pattern, manifest_buf) is None: + return None + + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + return manifest_file + finally: + manifest_f.close() + except OSError: + pass # -- Miscellaneous methods ----------------------------------------- # These are all used by the 'gen_lib_options() function, in @@ -538,12 +539,11 @@ def runtime_library_dir_option(self, dir): raise DistutilsPlatformError( - "don't know how to set runtime library search path for MSVC++") + "don't know how to set runtime library search path for MSVC") def library_option(self, lib): return self.library_filename(lib) - def find_library_file(self, dirs, lib, debug=0): # Prefer a debugging library if found (and requested), but deal # with it if we don't have one. @@ -553,91 +553,9 @@ try_names = [lib] for dir in dirs: for name in try_names: - libfile = os.path.join(dir, self.library_filename (name)) - if os.path.exists(libfile): + libfile = os.path.join(dir, self.library_filename(name)) + if os.path.isfile(libfile): return libfile else: # Oops, didn't find it in *any* of 'dirs' return None - - # Helper methods for using the MSVC registry settings - - def find_exe(self, exe): - """Return path to an MSVC executable program. - - Tries to find the program in several places: first, one of the - MSVC program search paths from the registry; next, the directories - in the PATH environment variable. If any of those work, return an - absolute path that is known to exist. If none of them work, just - return the original program name, 'exe'. - """ - for p in self.__paths: - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - - # didn't find it; try existing path - for p in os.environ['Path'].split(';'): - fn = os.path.join(os.path.abspath(p),exe) - if os.path.isfile(fn): - return fn - - return exe - - def get_msvc_paths(self, path, platform='x86'): - """Get a list of devstudio directories (include, lib or path). - - Return a list of strings. The list will be empty if unable to - access the registry or appropriate registry keys not found. - """ - if not _can_read_reg: - return [] - - path = path + " dirs" - if self.__version >= 7: - key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories" - % (self.__root, self.__version)) - else: - key = (r"%s\6.0\Build System\Components\Platforms" - r"\Win32 (%s)\Directories" % (self.__root, platform)) - - for base in HKEYS: - d = read_values(base, key) - if d: - if self.__version >= 7: - return self.__macros.sub(d[path]).split(";") - else: - return d[path].split(";") - # MSVC 6 seems to create the registry entries we need only when - # the GUI is run. - if self.__version == 6: - for base in HKEYS: - if read_values(base, r"%s\6.0" % self.__root) is not None: - self.warn("It seems you have Visual Studio 6 installed, " - "but the expected registry settings are not present.\n" - "You must at least run the Visual Studio GUI once " - "so that these entries are created.") - break - return [] - - def set_path_env_var(self, name): - """Set environment variable 'name' to an MSVC path type value. - - This is equivalent to a SET command prior to execution of spawned - commands. - """ - - if name == "lib": - p = self.get_msvc_paths("library") - else: - p = self.get_msvc_paths(name) - if p: - os.environ[name] = ';'.join(p) - - -if get_build_version() >= 8.0: - log.debug("Importing new compiler from distutils.msvc9compiler") - OldMSVCCompiler = MSVCCompiler - from distutils.msvc9compiler import MSVCCompiler - # get_build_architecture not really relevant now we support cross-compile - from distutils.msvc9compiler import MacroExpander diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -959,7 +959,7 @@ # is assumed to be in the 'distutils' package.) compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler', "standard UNIX-style compiler"), - 'msvc': ('msvccompiler', 'MSVCCompiler', + 'msvc': ('_msvccompiler', 'MSVCCompiler', "Microsoft Visual C++"), 'cygwin': ('cygwinccompiler', 'CygwinCCompiler', "Cygwin port of GNU C Compiler for Win32"), diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py --- a/Lib/distutils/command/bdist_wininst.py +++ b/Lib/distutils/command/bdist_wininst.py @@ -303,7 +303,6 @@ return installer_name def get_exe_bytes(self): - from distutils.msvccompiler import get_build_version # If a target-version other than the current version has been # specified, then using the MSVC version from *this* build is no good. # Without actually finding and executing the target version and parsing @@ -313,20 +312,28 @@ # We can then execute this program to obtain any info we need, such # as the real sys.version string for the build. cur_version = get_python_version() - if self.target_version and self.target_version != cur_version: - # If the target version is *later* than us, then we assume they - # use what we use - # string compares seem wrong, but are what sysconfig.py itself uses - if self.target_version > cur_version: - bv = get_build_version() + + # If the target version is *later* than us, then we assume they + # use what we use + # string compares seem wrong, but are what sysconfig.py itself uses + if self.target_version and self.target_version < cur_version: + if self.target_version < "2.4": + bv = 6.0 + elif self.target_version == "2.4": + bv = 7.1 + elif self.target_version == "2.5": + bv = 8.0 + elif self.target_version <= "3.2": + bv = 9.0 + elif self.target_version <= "3.4": + bv = 10.0 else: - if self.target_version < "2.4": - bv = 6.0 - else: - bv = 7.1 + bv = 14.0 else: # for current version - use authoritative check. - bv = get_build_version() + from msvcrt import CRT_ASSEMBLY_VERSION + bv = float('.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2])) + # wininst-x.y.exe is in the same directory as this file directory = os.path.dirname(__file__) diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -19,10 +19,6 @@ from site import USER_BASE -if os.name == 'nt': - from distutils.msvccompiler import get_build_version - MSVC_VERSION = int(get_build_version()) - # An extension name is just a dot-separated list of Python NAMEs (ie. # the same as a fully-qualified module name). extension_name_re = re.compile \ @@ -206,27 +202,17 @@ _sys_home = getattr(sys, '_home', None) if _sys_home: self.library_dirs.append(_sys_home) - if MSVC_VERSION >= 9: - # Use the .lib files for the correct architecture - if self.plat_name == 'win32': - suffix = 'win32' - else: - # win-amd64 or win-ia64 - suffix = self.plat_name[4:] - new_lib = os.path.join(sys.exec_prefix, 'PCbuild') - if suffix: - new_lib = os.path.join(new_lib, suffix) - self.library_dirs.append(new_lib) - elif MSVC_VERSION == 8: - self.library_dirs.append(os.path.join(sys.exec_prefix, - 'PC', 'VS8.0')) - elif MSVC_VERSION == 7: - self.library_dirs.append(os.path.join(sys.exec_prefix, - 'PC', 'VS7.1')) + # Use the .lib files for the correct architecture + if self.plat_name == 'win32': + suffix = 'win32' else: - self.library_dirs.append(os.path.join(sys.exec_prefix, - 'PC', 'VC6')) + # win-amd64 or win-ia64 + suffix = self.plat_name[4:] + new_lib = os.path.join(sys.exec_prefix, 'PCbuild') + if suffix: + new_lib = os.path.join(new_lib, suffix) + self.library_dirs.append(new_lib) # for extensions under Cygwin and AtheOS Python's library directory must be # appended to library_dirs @@ -716,7 +702,7 @@ # to need it mentioned explicitly, though, so that's what we do. # Append '_d' to the python import library on debug builds. if sys.platform == "win32": - from distutils.msvccompiler import MSVCCompiler + from distutils._msvccompiler import MSVCCompiler if not isinstance(self.compiler, MSVCCompiler): template = "python%d%d" if self.debug: diff --git a/Lib/distutils/tests/test_msvc9compiler.py b/Lib/distutils/tests/test_msvccompiler.py copy from Lib/distutils/tests/test_msvc9compiler.py copy to Lib/distutils/tests/test_msvccompiler.py --- a/Lib/distutils/tests/test_msvc9compiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -1,4 +1,4 @@ -"""Tests for distutils.msvc9compiler.""" +"""Tests for distutils._msvccompiler.""" import sys import unittest import os @@ -90,56 +90,32 @@ """ -if sys.platform=="win32": - from distutils.msvccompiler import get_build_version - if get_build_version()>=8.0: - SKIP_MESSAGE = None - else: - SKIP_MESSAGE = "These tests are only for MSVC8.0 or above" -else: - SKIP_MESSAGE = "These tests are only for win32" +SKIP_MESSAGE = (None if sys.platform == "win32" else + "These tests are only for win32") @unittest.skipUnless(SKIP_MESSAGE is None, SKIP_MESSAGE) -class msvc9compilerTestCase(support.TempdirManager, +class msvccompilerTestCase(support.TempdirManager, unittest.TestCase): def test_no_compiler(self): # makes sure query_vcvarsall raises # a DistutilsPlatformError if the compiler # is not found - from distutils.msvc9compiler import query_vcvarsall - def _find_vcvarsall(version): + from distutils._msvccompiler import _get_vc_env + def _find_vcvarsall(): return None - from distutils import msvc9compiler - old_find_vcvarsall = msvc9compiler.find_vcvarsall - msvc9compiler.find_vcvarsall = _find_vcvarsall + import distutils._msvccompiler as _msvccompiler + old_find_vcvarsall = _msvccompiler._find_vcvarsall + _msvccompiler._find_vcvarsall = _find_vcvarsall try: - self.assertRaises(DistutilsPlatformError, query_vcvarsall, + self.assertRaises(DistutilsPlatformError, _get_vc_env, 'wont find this version') finally: - msvc9compiler.find_vcvarsall = old_find_vcvarsall - - def test_reg_class(self): - from distutils.msvc9compiler import Reg - self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx') - - # looking for values that should exist on all - # windows registeries versions. - path = r'Control Panel\Desktop' - v = Reg.get_value(path, 'dragfullwindows') - self.assertIn(v, ('0', '1', '2')) - - import winreg - HKCU = winreg.HKEY_CURRENT_USER - keys = Reg.read_keys(HKCU, 'xxxx') - self.assertEqual(keys, None) - - keys = Reg.read_keys(HKCU, r'Control Panel') - self.assertIn('Desktop', keys) + _msvccompiler._find_vcvarsall = old_find_vcvarsall def test_remove_visual_c_ref(self): - from distutils.msvc9compiler import MSVCCompiler + from distutils._msvccompiler import MSVCCompiler tempdir = self.mkdtemp() manifest = os.path.join(tempdir, 'manifest') f = open(manifest, 'w') @@ -163,7 +139,7 @@ self.assertEqual(content, _CLEANED_MANIFEST) def test_remove_entire_manifest(self): - from distutils.msvc9compiler import MSVCCompiler + from distutils._msvccompiler import MSVCCompiler tempdir = self.mkdtemp() manifest = os.path.join(tempdir, 'manifest') f = open(manifest, 'w') @@ -178,7 +154,7 @@ def test_suite(): - return unittest.makeSuite(msvc9compilerTestCase) + return unittest.makeSuite(msvccompilerTestCase) if __name__ == "__main__": run_unittest(test_suite()) diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -22,8 +22,6 @@ import distutils.ccompiler import distutils.cygwinccompiler import distutils.filelist - if sys.platform.startswith('win'): - import distutils.msvccompiler import distutils.text_file import distutils.unixccompiler -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 18:12:01 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 23 May 2015 16:12:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324204=3A__Elabora?= =?utf-8?q?te_of_the_str=2Estrip=28=29_documentation=2E?= Message-ID: <20150523161201.21236.65040@psf.io> https://hg.python.org/cpython/rev/367e3923532f changeset: 96244:367e3923532f user: Raymond Hettinger date: Sat May 23 09:11:55 2015 -0700 summary: Issue #24204: Elaborate of the str.strip() documentation. files: Doc/library/stdtypes.rst | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1937,6 +1937,16 @@ >>> 'www.example.com'.strip('cmowz.') 'example' + The outermost leading and trailing *chars* argument values are stripped + from the string. Characters are removed from the leading end until + reaching a string character that is not contained in the set of + characters in *chars*. A similar action takes place on the trailing end. + For example:: + + >>> comment_string = '#....... Section 3.2.1 Issue #32 .......' + >>> comment_string.strip('.#! ') + 'Section 3.2.1 Issue #32' + .. method:: str.swapcase() -- Repository URL: https://hg.python.org/cpython From tjreedy at udel.edu Sat May 23 18:52:36 2015 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 23 May 2015 12:52:36 -0400 Subject: [Python-checkins] devguide: Updated dev guide to reflect the new workflow we're trying for 3.5. In-Reply-To: <20150523083226.126986.26481@psf.io> References: <20150523083226.126986.26481@psf.io> Message-ID: <5560B054.307@udel.edu> On 5/23/2015 4:32 AM, larry.hastings wrote: > +.. note:: > + For the 3.5 release we're trying something new. At the point that we reach 3.5.0 > + release candidate 1, the official release branch will no longer be hosted at > + ``hg.python.org``. Instead, 3.5.0 rc 1 through final will be hosted > + by the 3.5 release manager on bitbucket. > + > + Bugfixes for 3.5 should still be checked in to the 3.5 branch. However, if the > + core developer responsible for the bugfix feels it should be merged into 3.5.0, they > + will need to create a bitbucket "pull request" for this change. Any bugfixes not > + merged into 3.5.0 in this way will be automatically shipped with 3.5.1. I somehow did not understand this last part before. Rather I thought the need for pull requests would be highly restricted (and not affect me ;-). 3.5 bugfixes (and idlelib patches, unclassified), especially those applied to 3.4, should automatically be in the next 3.5 release. I cannot imagine a reason not to so so. Otherwise, we could end up with the awful anomaly that a bugfix (or Idle change) could be in 3.4.4 (the final maintenance version that comes out after 3.5.0) but not in 3.5.0 itself. The presumed purpose of the new procedure is to encourage development. But having to make a pull request for every patch in addition to doing a second merge (and possibly or assuredly deal with a second merge conflict (especially NEWS) will only discourage me, if not others. tjr From python-checkins at python.org Sat May 23 21:16:10 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 19:16:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323970=3A_Fixes_bd?= =?utf-8?q?ist=5Fwininst_not_working_on_non-Windows_platform=2E?= Message-ID: <20150523191610.96184.87804@psf.io> https://hg.python.org/cpython/rev/32e6123f9f8c changeset: 96245:32e6123f9f8c user: Steve Dower date: Sat May 23 12:15:57 2015 -0700 summary: Issue #23970: Fixes bdist_wininst not working on non-Windows platform. files: Lib/distutils/command/bdist_wininst.py | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/distutils/command/bdist_wininst.py b/Lib/distutils/command/bdist_wininst.py --- a/Lib/distutils/command/bdist_wininst.py +++ b/Lib/distutils/command/bdist_wininst.py @@ -331,8 +331,13 @@ bv = 14.0 else: # for current version - use authoritative check. - from msvcrt import CRT_ASSEMBLY_VERSION - bv = float('.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2])) + try: + from msvcrt import CRT_ASSEMBLY_VERSION + except ImportError: + # cross-building, so assume the latest version + bv = 14.0 + else: + bv = float('.'.join(CRT_ASSEMBLY_VERSION.split('.', 2)[:2])) # wininst-x.y.exe is in the same directory as this file -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 21:43:13 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 23 May 2015 19:43:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2314373=3A_Added_C_?= =?utf-8?q?implementation_of_functools=2Elru=5Fcache=28=29=2E__Based_on?= Message-ID: <20150523194313.26118.75924@psf.io> https://hg.python.org/cpython/rev/57776eee74f2 changeset: 96246:57776eee74f2 user: Serhiy Storchaka date: Sat May 23 22:42:49 2015 +0300 summary: Issue #14373: Added C implementation of functools.lru_cache(). Based on patches by Matt Joiner and Alexey Kachayev. files: Lib/functools.py | 203 ++++---- Lib/test/test_functools.py | 109 ++++- Misc/NEWS | 3 + Modules/_functoolsmodule.c | 547 ++++++++++++++++++++++++- 4 files changed, 747 insertions(+), 115 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -419,120 +419,129 @@ if maxsize is not None and not isinstance(maxsize, int): raise TypeError('Expected maxsize to be an integer or None') + def decorating_function(user_function): + wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) + return update_wrapper(wrapper, user_function) + + return decorating_function + +def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): # Constants shared by all lru cache instances: sentinel = object() # unique object used to signal cache misses make_key = _make_key # build a key from the function arguments PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - def decorating_function(user_function): - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self - if maxsize == 0: + if maxsize == 0: - def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call - nonlocal misses - result = user_function(*args, **kwds) - misses += 1 + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result + + elif maxsize is None: + + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: + hits += 1 return result + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result - elif maxsize is None: + else: - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root hits += 1 return result - result = user_function(*args, **kwds) - cache[key] = result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + full = (len(cache) >= maxsize) misses += 1 - return result + return result - else: + def cache_info(): + """Report cache statistics""" + with lock: + return _CacheInfo(hits, misses, maxsize, len(cache)) - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - hits += 1 - return result - result = user_function(*args, **kwds) - with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) >= maxsize) - misses += 1 - return result + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return update_wrapper(wrapper, user_function) - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False - - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return update_wrapper(wrapper, user_function) - - return decorating_function +try: + from _functools import _lru_cache_wrapper +except ImportError: + pass ################################################################################ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -7,6 +7,10 @@ from test import support import unittest from weakref import proxy +try: + import threading +except ImportError: + threading = None import functools @@ -912,12 +916,12 @@ return self.value == other.value -class TestLRU(unittest.TestCase): +class TestLRU: def test_lru(self): def orig(x, y): return 3 * x + y - f = functools.lru_cache(maxsize=20)(orig) + f = self.module.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) self.assertEqual(currsize, 0) @@ -955,7 +959,7 @@ self.assertEqual(currsize, 1) # test size zero (which means "never-cache") - @functools.lru_cache(0) + @self.module.lru_cache(0) def f(): nonlocal f_cnt f_cnt += 1 @@ -971,7 +975,7 @@ self.assertEqual(currsize, 0) # test size one - @functools.lru_cache(1) + @self.module.lru_cache(1) def f(): nonlocal f_cnt f_cnt += 1 @@ -987,7 +991,7 @@ self.assertEqual(currsize, 1) # test size two - @functools.lru_cache(2) + @self.module.lru_cache(2) def f(x): nonlocal f_cnt f_cnt += 1 @@ -1004,7 +1008,7 @@ self.assertEqual(currsize, 2) def test_lru_with_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1012,17 +1016,26 @@ self.assertEqual([fib(n) for n in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_with_maxsize_negative(self): + @self.module.lru_cache(maxsize=-10) + def eq(n): + return n + for i in (0, 1): + self.assertEqual([eq(n) for n in range(150)], list(range(150))) + self.assertEqual(eq.cache_info(), + self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): - @functools.lru_cache(maxsize) + @self.module.lru_cache(maxsize) def func(i): return 'abc'[i] self.assertEqual(func(0), 'a') @@ -1035,7 +1048,7 @@ def test_lru_with_types(self): for maxsize in (None, 128): - @functools.lru_cache(maxsize=maxsize, typed=True) + @self.module.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x self.assertEqual(square(3), 9) @@ -1050,7 +1063,7 @@ self.assertEqual(square.cache_info().misses, 4) def test_lru_with_keyword_args(self): - @functools.lru_cache() + @self.module.lru_cache() def fib(n): if n < 2: return n @@ -1060,13 +1073,13 @@ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] ) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) def test_lru_with_keyword_args_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1074,15 +1087,71 @@ self.assertEqual([fib(n=number) for number in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_cache_decoration(self): + def f(zomg: 'zomg_annotation'): + """f doc string""" + return 42 + g = self.module.lru_cache()(f) + for attr in self.module.WRAPPER_ASSIGNMENTS: + self.assertEqual(getattr(g, attr), getattr(f, attr)) + + @unittest.skipUnless(threading, 'This test requires threading.') + def test_lru_cache_threaded(self): + def orig(x, y): + return 3 * x + y + f = self.module.lru_cache(maxsize=20)(orig) + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(currsize, 0) + + def full(f, *args): + for _ in range(10): + f(*args) + + def clear(f): + for _ in range(10): + f.cache_clear() + + orig_si = sys.getswitchinterval() + sys.setswitchinterval(1e-6) + try: + # create 5 threads in order to fill cache + threads = [] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(hits, 45) + self.assertEqual(misses, 5) + self.assertEqual(currsize, 5) + + # create 5 threads in order to fill cache and 1 to clear it + cleaner = threading.Thread(target=clear, args=[f]) + cleaner.start() + threads = [cleaner] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + finally: + sys.setswitchinterval(orig_si) def test_need_for_rlock(self): # This will deadlock on an LRU cache that uses a regular lock - @functools.lru_cache(maxsize=10) + @self.module.lru_cache(maxsize=10) def test_func(x): 'Used to demonstrate a reentrant lru_cache call within a single thread' return x @@ -1110,6 +1179,12 @@ def f(): pass +class TestLRUC(TestLRU, unittest.TestCase): + module = c_functools + +class TestLRUPy(TestLRU, unittest.TestCase): + module = py_functools + class TestSingleDispatch(unittest.TestCase): def test_simple_overloads(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,9 @@ Library ------- +- Issue #14373: Added C implementation of functools.lru_cache(). Based on + patches by Matt Joiner and Alexey Kachayev. + - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -590,6 +590,539 @@ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); +/* lru_cache object **********************************************************/ + +/* this object is used delimit args and keywords in the cache keys */ +static PyObject *kwd_mark = NULL; + +struct lru_list_elem; +struct lru_cache_object; + +typedef struct lru_list_elem { + PyObject_HEAD + struct lru_list_elem *prev, *next; /* borrowed links */ + PyObject *key, *result; +} lru_list_elem; + +static void +lru_list_elem_dealloc(lru_list_elem *link) +{ + _PyObject_GC_UNTRACK(link); + Py_XDECREF(link->key); + Py_XDECREF(link->result); + PyObject_GC_Del(link); +} + +static int +lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg) +{ + Py_VISIT(link->key); + Py_VISIT(link->result); + return 0; +} + +static int +lru_list_elem_clear(lru_list_elem *link) +{ + Py_CLEAR(link->key); + Py_CLEAR(link->result); + return 0; +} + +static PyTypeObject lru_list_elem_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "functools._lru_list_elem", /* tp_name */ + sizeof(lru_list_elem), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_list_elem_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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)lru_list_elem_traverse, /* tp_traverse */ + (inquiry)lru_list_elem_clear, /* tp_clear */ +}; + + +typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); + +typedef struct lru_cache_object { + lru_list_elem root; /* includes PyObject_HEAD */ + Py_ssize_t maxsize; + PyObject *maxsize_O; + PyObject *func; + lru_cache_ternaryfunc wrapper; + PyObject *cache; + PyObject *cache_info_type; + Py_ssize_t misses, hits; + int typed; + PyObject *dict; + int full; +} lru_cache_object; + +static PyTypeObject lru_cache_type; + +static PyObject * +lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) +{ + PyObject *key, *sorted_items; + Py_ssize_t key_size, pos, key_pos; + + /* short path, key will match args anyway, which is a tuple */ + if (!typed && !kwds) { + Py_INCREF(args); + return args; + } + + if (kwds && PyDict_Size(kwds) > 0) { + sorted_items = PyDict_Items(kwds); + if (!sorted_items) + return NULL; + if (PyList_Sort(sorted_items) < 0) { + Py_DECREF(sorted_items); + return NULL; + } + } else + sorted_items = NULL; + + key_size = PyTuple_GET_SIZE(args); + if (sorted_items) + key_size += PyList_GET_SIZE(sorted_items); + if (typed) + key_size *= 2; + if (sorted_items) + key_size++; + + key = PyTuple_New(key_size); + if (key == NULL) + goto done; + + key_pos = 0; + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = PyTuple_GET_ITEM(args, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + Py_INCREF(kwd_mark); + PyTuple_SET_ITEM(key, key_pos++, kwd_mark); + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *item = PyList_GET_ITEM(sorted_items, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + if (typed) { + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + } + assert(key_pos == key_size); + +done: + if (sorted_items) + Py_DECREF(sorted_items); + return key; +} + +static PyObject * +uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result = PyObject_Call(self->func, args, kwds); + if (!result) + return NULL; + self->misses++; + return result; +} + +static PyObject * +infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result; + PyObject *key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + result = PyDict_GetItemWithError(self->cache, key); + if (result) { + Py_INCREF(result); + self->hits++; + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (PyDict_SetItem(self->cache, key, result) < 0) { + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + Py_DECREF(key); + self->misses++; + return result; +} + +static void +lru_cache_extricate_link(lru_list_elem *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static void +lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) +{ + lru_list_elem *root = &self->root; + lru_list_elem *last = root->prev; + last->next = root->prev = link; + link->prev = last; + link->next = root; +} + +static PyObject * +bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + lru_list_elem *link; + PyObject *key, *result; + + key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); + if (link) { + lru_cache_extricate_link(link); + lru_cache_append_link(self, link); + self->hits++; + result = link->result; + Py_INCREF(result); + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (self->full && self->root.next != &self->root) { + /* Use the oldest item to store the new key and result. */ + PyObject *oldkey, *oldresult; + /* Extricate the oldest item. */ + link = self->root.next; + lru_cache_extricate_link(link); + /* Remove it from the cache. + The cache dict holds one reference to the link, + and the linked list holds yet one reference to it. */ + if (PyDict_DelItem(self->cache, link->key) < 0) { + lru_cache_append_link(self, link); + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + /* Keep a reference to the old key and old result to + prevent their ref counts from going to zero during the + update. That will prevent potentially arbitrary object + clean-up code (i.e. __del__) from running while we're + still adjusting the links. */ + oldkey = link->key; + oldresult = link->result; + + link->key = key; + link->result = result; + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + Py_DECREF(oldkey); + Py_DECREF(oldresult); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + Py_DECREF(oldkey); + Py_DECREF(oldresult); + } else { + /* Put result in a new link at the front of the queue. */ + link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, + &lru_list_elem_type); + if (link == NULL) { + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + + link->key = key; + link->result = result; + _PyObject_GC_TRACK(link); + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + self->full = (PyDict_Size(self->cache) >= self->maxsize); + } + self->misses++; + return result; +} + +static PyObject * +lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) +{ + PyObject *func, *maxsize_O, *cache_info_type; + int typed; + lru_cache_object *obj; + Py_ssize_t maxsize; + PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); + static char *keywords[] = {"user_function", "maxsize", "typed", + "cache_info_type", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, + &func, &maxsize_O, &typed, + &cache_info_type)) { + return NULL; + } + + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "the first argument must be callable"); + return NULL; + } + + /* select the caching function, and make/inc maxsize_O */ + if (maxsize_O == Py_None) { + wrapper = infinite_lru_cache_wrapper; + /* use this only to initialize lru_cache_object attribute maxsize */ + maxsize = -1; + } else if (PyIndex_Check(maxsize_O)) { + maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); + if (maxsize == -1 && PyErr_Occurred()) + return NULL; + if (maxsize == 0) + wrapper = uncached_lru_cache_wrapper; + else + wrapper = bounded_lru_cache_wrapper; + } else { + PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); + return NULL; + } + + obj = (lru_cache_object *)type->tp_alloc(type, 0); + if (obj == NULL) + return NULL; + + if (!(obj->cache = PyDict_New())) { + Py_DECREF(obj); + return NULL; + } + + obj->root.prev = &obj->root; + obj->root.next = &obj->root; + obj->maxsize = maxsize; + Py_INCREF(maxsize_O); + obj->maxsize_O = maxsize_O; + Py_INCREF(func); + obj->func = func; + obj->wrapper = wrapper; + obj->misses = obj->hits = 0; + obj->typed = typed; + Py_INCREF(cache_info_type); + obj->cache_info_type = cache_info_type; + + return (PyObject *)obj; +} + +static lru_list_elem * +lru_cache_unlink_list(lru_cache_object *self) +{ + lru_list_elem *root = &self->root; + lru_list_elem *link = root->next; + if (link == root) + return NULL; + root->prev->next = NULL; + root->next = root->prev = root; + return link; +} + +static void +lru_cache_clear_list(lru_list_elem *link) +{ + while (link != NULL) { + lru_list_elem *next = link->next; + Py_DECREF(link); + link = next; + } +} + +static void +lru_cache_dealloc(lru_cache_object *obj) +{ + lru_list_elem *list = lru_cache_unlink_list(obj); + Py_XDECREF(obj->maxsize_O); + Py_XDECREF(obj->func); + Py_XDECREF(obj->cache); + Py_XDECREF(obj->dict); + Py_XDECREF(obj->cache_info_type); + lru_cache_clear_list(list); + Py_TYPE(obj)->tp_free(obj); +} + +static PyObject * +lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + return self->wrapper(self, args, kwds); +} + +static PyObject * +lru_cache_cache_info(lru_cache_object *self, PyObject *unused) +{ + return PyObject_CallFunction(self->cache_info_type, "nnOn", + self->hits, self->misses, self->maxsize_O, + PyDict_Size(self->cache)); +} + +static PyObject * +lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + self->hits = self->misses = 0; + self->full = 0; + PyDict_Clear(self->cache); + lru_cache_clear_list(list); + Py_RETURN_NONE; +} + +static int +lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) +{ + lru_list_elem *link = self->root.next; + while (link != &self->root) { + lru_list_elem *next = link->next; + Py_VISIT(link); + link = next; + } + Py_VISIT(self->maxsize_O); + Py_VISIT(self->func); + Py_VISIT(self->cache); + Py_VISIT(self->cache_info_type); + Py_VISIT(self->dict); + return 0; +} + +static int +lru_cache_tp_clear(lru_cache_object *self) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + Py_CLEAR(self->maxsize_O); + Py_CLEAR(self->func); + Py_CLEAR(self->cache); + Py_CLEAR(self->cache_info_type); + Py_CLEAR(self->dict); + lru_cache_clear_list(list); + return 0; +} + + +PyDoc_STRVAR(lru_cache_doc, +"Create a cached callable that wraps another function.\n\ +\n\ +user_function: the function being cached\n\ +\n\ +maxsize: 0 for no caching\n\ + None for unlimited cache size\n\ + n for a bounded cache\n\ +\n\ +typed: False cache f(3) and f(3.0) as identical calls\n\ + True cache f(3) and f(3.0) as distinct calls\n\ +\n\ +cache_info_type: namedtuple class with the fields:\n\ + hits misses currsize maxsize\n" +); + +static PyMethodDef lru_cache_methods[] = { + {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, + {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, + {NULL} +}; + +static PyGetSetDef lru_cache_getsetlist[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + +static PyTypeObject lru_cache_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "functools._lru_cache_wrapper", /* tp_name */ + sizeof(lru_cache_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_cache_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 */ + (ternaryfunc)lru_cache_call, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + lru_cache_doc, /* tp_doc */ + (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ + (inquiry)lru_cache_tp_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lru_cache_methods, /* tp_methods */ + 0, /* tp_members */ + lru_cache_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(lru_cache_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + lru_cache_new, /* tp_new */ +}; + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -602,6 +1135,11 @@ {NULL, NULL} /* sentinel */ }; +static void +module_free(void *m) +{ + Py_CLEAR(kwd_mark); +} static struct PyModuleDef _functoolsmodule = { PyModuleDef_HEAD_INIT, @@ -612,7 +1150,7 @@ NULL, NULL, NULL, - NULL + module_free, }; PyMODINIT_FUNC @@ -623,6 +1161,7 @@ char *name; PyTypeObject *typelist[] = { &partial_type, + &lru_cache_type, NULL }; @@ -630,6 +1169,12 @@ if (m == NULL) return NULL; + kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL); + if (!kwd_mark) { + Py_DECREF(m); + return NULL; + } + for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) { Py_DECREF(m); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 22:17:10 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 20:17:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150523201710.27945.25334@psf.io> https://hg.python.org/cpython/rev/664432718dcb changeset: 96249:664432718dcb parent: 96246:57776eee74f2 parent: 96248:8c6170954789 user: Terry Jan Reedy date: Sat May 23 16:16:46 2015 -0400 summary: Merge with 3.4 files: Doc/library/functions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -249,7 +249,7 @@ .. class:: complex([real[, imag]]) - Return a complex number with the value *real* + *imag*\*j or convert a string + Return a complex number with the value *real* + *imag*\*1j or convert a string or number to a complex number. If the first parameter is a string, it will be interpreted as a complex number and the function must be called without a second parameter. The second parameter can never be a string. Each argument -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 22:17:10 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 20:17:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Make_expressio?= =?utf-8?q?n_legal_python_by_adding_=271=27=2E?= Message-ID: <20150523201710.16311.72473@psf.io> https://hg.python.org/cpython/rev/8c6170954789 changeset: 96248:8c6170954789 branch: 3.4 parent: 96232:a43f5515e3a2 user: Terry Jan Reedy date: Sat May 23 16:16:28 2015 -0400 summary: Make expression legal python by adding '1'. files: Doc/library/functions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -248,7 +248,7 @@ .. class:: complex([real[, imag]]) - Return a complex number with the value *real* + *imag*\*j or convert a string + Return a complex number with the value *real* + *imag*\*1j or convert a string or number to a complex number. If the first parameter is a string, it will be interpreted as a complex number and the function must be called without a second parameter. The second parameter can never be a string. Each argument -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 22:17:10 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 20:17:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Make_expressio?= =?utf-8?q?n_legal_python_by_adding_=271=27=2E?= Message-ID: <20150523201710.21256.51121@psf.io> https://hg.python.org/cpython/rev/0d16fb337e90 changeset: 96247:0d16fb337e90 branch: 2.7 parent: 96242:df37c0893816 user: Terry Jan Reedy date: Sat May 23 16:16:23 2015 -0400 summary: Make expression legal python by adding '1'. files: Doc/library/functions.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -261,7 +261,7 @@ .. class:: complex([real[, imag]]) - Return a complex number with the value *real* + *imag*\*j or convert a string or + Return a complex number with the value *real* + *imag*\*1j or convert a string or number to a complex number. If the first parameter is a string, it will be interpreted as a complex number and the function must be called without a second parameter. The second parameter can never be a string. Each argument may be any -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:14:16 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 21:14:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324268=3A_Fix_impo?= =?utf-8?q?rt_naming_when_loading_extension_modules=2E_Patch_by_Petr?= Message-ID: <20150523211416.17927.54594@psf.io> https://hg.python.org/cpython/rev/7b5f5f8b26a6 changeset: 96250:7b5f5f8b26a6 user: Steve Dower date: Sat May 23 14:13:41 2015 -0700 summary: Issue #24268: Fix import naming when loading extension modules. Patch by Petr Viktorin. files: Python/dynload_dl.c | 2 +- Python/dynload_hpux.c | 4 ++-- Python/dynload_next.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c --- a/Python/dynload_dl.c +++ b/Python/dynload_dl.c @@ -18,6 +18,6 @@ { char funcname[258]; - PyOS_snprintf(funcname, sizeof(funcname), "%20s_%.200s", prefix, shortname); + PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname); return dl_loadmod(Py_GetProgramName(), pathname, funcname); } diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -8,9 +8,9 @@ #include "importdl.h" #if defined(__hp9000s300) -#define FUNCNAME_PATTERN "_%20s_%.200s" +#define FUNCNAME_PATTERN "_%.20s_%.200s" #else -#define FUNCNAME_PATTERN "%20s_%.200s" +#define FUNCNAME_PATTERN "%.20s_%.200s" #endif const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL}; diff --git a/Python/dynload_next.c b/Python/dynload_next.c --- a/Python/dynload_next.c +++ b/Python/dynload_next.c @@ -40,7 +40,7 @@ const char *errString; char errBuf[512]; - PyOS_snprintf(funcname, sizeof(funcname), "_%20s_%.200s", prefix, shortname); + PyOS_snprintf(funcname, sizeof(funcname), "_%.20s_%.200s", prefix, shortname); #ifdef USE_DYLD_GLOBAL_NAMESPACE if (NSIsSymbolNameDefined(funcname)) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:19:06 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:19:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Add_Idle_NEWS_item=2E?= Message-ID: <20150523211906.16309.378@psf.io> https://hg.python.org/cpython/rev/53153672c300 changeset: 96252:53153672c300 parent: 96249:664432718dcb parent: 96251:b7926f038994 user: Terry Jan Reedy date: Sat May 23 17:14:09 2015 -0400 summary: Add Idle NEWS item. files: Misc/NEWS | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -230,6 +230,12 @@ - Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +IDLE +---- + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:19:06 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:19:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Add_NEWS_item_?= =?utf-8?q?for_Idle=2E?= Message-ID: <20150523211906.96198.75640@psf.io> https://hg.python.org/cpython/rev/b7926f038994 changeset: 96251:b7926f038994 branch: 3.4 parent: 96248:8c6170954789 user: Terry Jan Reedy date: Sat May 23 17:12:48 2015 -0400 summary: Add NEWS item for Idle. files: Misc/NEWS | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -271,6 +271,12 @@ - Issue 23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +IDLE +---- + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:19:06 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:19:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150523211906.45365.25030@psf.io> https://hg.python.org/cpython/rev/6c853a196a1b changeset: 96253:6c853a196a1b parent: 96250:7b5f5f8b26a6 parent: 96252:53153672c300 user: Terry Jan Reedy date: Sat May 23 17:18:40 2015 -0400 summary: merge files: Misc/NEWS | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -230,6 +230,12 @@ - Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +IDLE +---- + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + Tests ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:24:47 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:24:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_idlelib?= =?utf-8?q?/NEWS=2Etxt=2E?= Message-ID: <20150523212446.17949.75503@psf.io> https://hg.python.org/cpython/rev/1c4e89d1ae90 changeset: 96254:1c4e89d1ae90 branch: 2.7 parent: 96247:0d16fb337e90 user: Terry Jan Reedy date: Sat May 23 17:23:23 2015 -0400 summary: Update idlelib/NEWS.txt. files: Lib/idlelib/NEWS.txt | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,7 +1,26 @@ +What's New in IDLE 2.7.10? +========================= + +*Release data: 2015-05-23* + +- Issue #23583: Fixed writing unicode to standard output stream in IDLE. + +- Issue #20577: Configuration of the max line length for the FormatParagraph + extension has been moved from the General tab of the Idle preferences dialog + to the FormatParagraph tab of the Config Extensions dialog. + Patch by Tal Einat. + +- Issue #16893: Update Idle doc chapter to match current Idle and add new + information. + +- Issue #23180: Rename IDLE "Windows" menu item to "Window". + Patch by Al Sweigart. + + What's New in IDLE 2.7.9? ========================= -*Release data: 2014-12-07* (projected) +*Release data: 2014-12-10* - Issue #16893: Update Idle doc chapter to match current Idle and add new information. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:24:47 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:24:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Update_idlelib?= =?utf-8?q?/NEWS=2Etxt=2E?= Message-ID: <20150523212447.70429.75687@psf.io> https://hg.python.org/cpython/rev/e8cab5bef4f1 changeset: 96255:e8cab5bef4f1 branch: 3.4 parent: 96251:b7926f038994 user: Terry Jan Reedy date: Sat May 23 17:23:30 2015 -0400 summary: Update idlelib/NEWS.txt. files: Lib/idlelib/NEWS.txt | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,5 +1,19 @@ What's New in Idle 3.4.3? ========================= +*Release date: 2015-??-??* + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + + +What's New in Idle 3.4.3? +========================= +*Release date: 2015-02-25* + +- Issue #20577: Configuration of the max line length for the FormatParagraph + extension has been moved from the General tab of the Idle preferences dialog + to the FormatParagraph tab of the Config Extensions dialog. + Patch by Tal Einat. - Issue #16893: Update Idle doc chapter to match current Idle and add new information. @@ -21,9 +35,13 @@ - Issue #21986: Code objects are not normally pickled by the pickle module. To match this, they are no longer pickled when running under Idle. +- Issue #23180: Rename IDLE "Windows" menu item to "Window". + Patch by Al Sweigart. + What's New in IDLE 3.4.2? ========================= +*Release date: 2014-10-06* - Issue #17390: Adjust Editor window title; remove 'Python', move version to end. @@ -66,6 +84,7 @@ What's New in IDLE 3.4.1? ========================= +*Release date: 2014-05-18* - Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin consolidating and improving human-validated tests of Idle. Change other files @@ -81,6 +100,7 @@ What's New in IDLE 3.4.0? ========================= +*Release date: 2014-03-16* - Issue #17390: Display Python version on Idle title bar. Initial patch by Edmond Burnett. @@ -98,6 +118,7 @@ What's New in IDLE 3.3.0? ========================= +*Release date: 2012-09-29* - Issue #17625: Close the replace dialog after it is used. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:24:47 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 21:24:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Update_idlelib/NEWS=2Etxt?= Message-ID: <20150523212447.126958.89030@psf.io> https://hg.python.org/cpython/rev/08fb17d5d06d changeset: 96256:08fb17d5d06d parent: 96253:6c853a196a1b parent: 96255:e8cab5bef4f1 user: Terry Jan Reedy date: Sat May 23 17:24:22 2015 -0400 summary: Update idlelib/NEWS.txt files: Lib/idlelib/NEWS.txt | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,5 +1,14 @@ What's New in IDLE 3.5.0? ========================= +*Release date: 2015-09-13* ?? + +- Issue #23184: remove unused names and imports in idlelib. + Initial patch by Al Sweigart. + +- Issue #20577: Configuration of the max line length for the FormatParagraph + extension has been moved from the General tab of the Idle preferences dialog + to the FormatParagraph tab of the Config Extensions dialog. + Patch by Tal Einat. - Issue #16893: Update Idle doc chapter to match current Idle and add new information. @@ -20,6 +29,9 @@ - Issue #21986: Code objects are not normally pickled by the pickle module. To match this, they are no longer pickled when running under Idle. + +- Issue #23180: Rename IDLE "Windows" menu item to "Window". + Patch by Al Sweigart. - Issue #17390: Adjust Editor window title; remove 'Python', move version to end. @@ -72,6 +84,7 @@ What's New in IDLE 3.4.0? ========================= +*Release date: 2014-03-16* - Issue #17390: Display Python version on Idle title bar. Initial patch by Edmond Burnett. @@ -89,6 +102,7 @@ What's New in IDLE 3.3.0? ========================= +*Release date: 2012-09-29* - Issue #17625: Close the replace dialog after it is used. @@ -131,7 +145,6 @@ What's New in IDLE 3.2.1? ========================= - *Release date: 15-May-11* - Issue #6378: Further adjust idle.bat to start associated Python @@ -149,7 +162,6 @@ What's New in IDLE 3.1b1? ========================= - *Release date: 06-May-09* - Use of 'filter' in keybindingDialog.py was causing custom key assignment to @@ -158,7 +170,6 @@ What's New in IDLE 3.1a1? ========================= - *Release date: 07-Mar-09* - Issue #4815: Offer conversion to UTF-8 if source files have @@ -176,7 +187,6 @@ What's New in IDLE 2.7? (UNRELEASED, but merged into 3.1 releases above.) ======================= - *Release date: XX-XXX-2010* - idle.py modified and simplified to better support developing experimental -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:25:53 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 23 May 2015 21:25:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_Sphinx_warnings=2E?= Message-ID: <20150523212553.16709.40779@psf.io> https://hg.python.org/cpython/rev/ec1e187173f7 changeset: 96257:ec1e187173f7 user: Berker Peksag date: Sun May 24 00:26:05 2015 +0300 summary: Fix Sphinx warnings. files: Doc/library/development.rst | 1 + Doc/whatsnew/3.5.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/development.rst b/Doc/library/development.rst --- a/Doc/library/development.rst +++ b/Doc/library/development.rst @@ -16,6 +16,7 @@ .. toctree:: + typing.rst pydoc.rst doctest.rst unittest.rst diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -684,7 +684,7 @@ ------- * The :mod:`tkinter._fix` module used for setting up the Tcl/Tk environment - on Windows has been replaced by a private function in the :module:`_tkinter` + on Windows has been replaced by a private function in the :mod:`_tkinter` module which makes no permanent changes to environment variables. (Contributed by Zachary Ware in :issue:`20035`.) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 23 23:44:48 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 23 May 2015 21:44:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324268=3A_Adds_PyM?= =?utf-8?q?oduleDef=5FInit_and_PyModuleDef=5FType_to_python3=2Edef_=28stab?= =?utf-8?q?le?= Message-ID: <20150523214448.17925.97028@psf.io> https://hg.python.org/cpython/rev/af167a62e2a3 changeset: 96258:af167a62e2a3 user: Steve Dower date: Sat May 23 14:44:37 2015 -0700 summary: Issue #24268: Adds PyModuleDef_Init and PyModuleDef_Type to python3.def (stable ABI) files: Include/moduleobject.h | 2 +- PC/python3.def | 2 ++ 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -31,7 +31,7 @@ PyAPI_FUNC(void*) PyModule_GetState(PyObject*); PyAPI_FUNC(PyObject *) PyModuleDef_Init(struct PyModuleDef*); -PyTypeObject PyModuleDef_Type; +PyAPI_DATA(PyTypeObject) PyModuleDef_Type; typedef struct PyModuleDef_Base { PyObject_HEAD diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -330,6 +330,8 @@ PyModule_GetState=python35.PyModule_GetState PyModule_New=python35.PyModule_New PyModule_Type=python35.PyModule_Type DATA + PyModuleDef_Init=python35.PyModuleDef_Init + PyModuleDef_Type=python35.PyModuleDef_Type DATA PyNullImporter_Type=python35.PyNullImporter_Type DATA PyNumber_Absolute=python35.PyNumber_Absolute PyNumber_Add=python35.PyNumber_Add -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:07:10 2015 From: python-checkins at python.org (larry.hastings) Date: Sat, 23 May 2015 22:07:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_backout_of_57776eee74f2=2E?= Message-ID: <20150523220710.16719.7938@psf.io> https://hg.python.org/cpython/rev/423546c86416 changeset: 96260:423546c86416 parent: 96258:af167a62e2a3 parent: 96259:b0a0b9b59012 user: Larry Hastings date: Sat May 23 14:57:12 2015 -0700 summary: Merge backout of 57776eee74f2. files: Lib/functools.py | 207 ++++---- Lib/test/test_functools.py | 109 +---- Misc/NEWS | 3 - Modules/_functoolsmodule.c | 547 +------------------------ 4 files changed, 117 insertions(+), 749 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -419,129 +419,120 @@ if maxsize is not None and not isinstance(maxsize, int): raise TypeError('Expected maxsize to be an integer or None') - def decorating_function(user_function): - wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) - return update_wrapper(wrapper, user_function) - - return decorating_function - -def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): # Constants shared by all lru cache instances: sentinel = object() # unique object used to signal cache misses make_key = _make_key # build a key from the function arguments PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self + def decorating_function(user_function): + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self - if maxsize == 0: + if maxsize == 0: - def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call - nonlocal misses - result = user_function(*args, **kwds) - misses += 1 - return result + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result - elif maxsize is None: + elif maxsize is None: - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: - hits += 1 - return result - result = user_function(*args, **kwds) - cache[key] = result - misses += 1 - return result - - else: - - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: hits += 1 return result - result = user_function(*args, **kwds) + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result + + else: + + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root + hits += 1 + return result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + full = (len(cache) >= maxsize) + misses += 1 + return result + + def cache_info(): + """Report cache statistics""" with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) >= maxsize) - misses += 1 - return result + return _CacheInfo(hits, misses, maxsize, len(cache)) - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return update_wrapper(wrapper, user_function) - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return update_wrapper(wrapper, user_function) - -try: - from _functools import _lru_cache_wrapper -except ImportError: - pass + return decorating_function ################################################################################ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -7,10 +7,6 @@ from test import support import unittest from weakref import proxy -try: - import threading -except ImportError: - threading = None import functools @@ -916,12 +912,12 @@ return self.value == other.value -class TestLRU: +class TestLRU(unittest.TestCase): def test_lru(self): def orig(x, y): return 3 * x + y - f = self.module.lru_cache(maxsize=20)(orig) + f = functools.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) self.assertEqual(currsize, 0) @@ -959,7 +955,7 @@ self.assertEqual(currsize, 1) # test size zero (which means "never-cache") - @self.module.lru_cache(0) + @functools.lru_cache(0) def f(): nonlocal f_cnt f_cnt += 1 @@ -975,7 +971,7 @@ self.assertEqual(currsize, 0) # test size one - @self.module.lru_cache(1) + @functools.lru_cache(1) def f(): nonlocal f_cnt f_cnt += 1 @@ -991,7 +987,7 @@ self.assertEqual(currsize, 1) # test size two - @self.module.lru_cache(2) + @functools.lru_cache(2) def f(x): nonlocal f_cnt f_cnt += 1 @@ -1008,7 +1004,7 @@ self.assertEqual(currsize, 2) def test_lru_with_maxsize_none(self): - @self.module.lru_cache(maxsize=None) + @functools.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1016,26 +1012,17 @@ self.assertEqual([fib(n) for n in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) - - def test_lru_with_maxsize_negative(self): - @self.module.lru_cache(maxsize=-10) - def eq(n): - return n - for i in (0, 1): - self.assertEqual([eq(n) for n in range(150)], list(range(150))) - self.assertEqual(eq.cache_info(), - self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) + functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): - @self.module.lru_cache(maxsize) + @functools.lru_cache(maxsize) def func(i): return 'abc'[i] self.assertEqual(func(0), 'a') @@ -1048,7 +1035,7 @@ def test_lru_with_types(self): for maxsize in (None, 128): - @self.module.lru_cache(maxsize=maxsize, typed=True) + @functools.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x self.assertEqual(square(3), 9) @@ -1063,7 +1050,7 @@ self.assertEqual(square.cache_info().misses, 4) def test_lru_with_keyword_args(self): - @self.module.lru_cache() + @functools.lru_cache() def fib(n): if n < 2: return n @@ -1073,13 +1060,13 @@ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] ) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) def test_lru_with_keyword_args_maxsize_none(self): - @self.module.lru_cache(maxsize=None) + @functools.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1087,71 +1074,15 @@ self.assertEqual([fib(n=number) for number in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) - - def test_lru_cache_decoration(self): - def f(zomg: 'zomg_annotation'): - """f doc string""" - return 42 - g = self.module.lru_cache()(f) - for attr in self.module.WRAPPER_ASSIGNMENTS: - self.assertEqual(getattr(g, attr), getattr(f, attr)) - - @unittest.skipUnless(threading, 'This test requires threading.') - def test_lru_cache_threaded(self): - def orig(x, y): - return 3 * x + y - f = self.module.lru_cache(maxsize=20)(orig) - hits, misses, maxsize, currsize = f.cache_info() - self.assertEqual(currsize, 0) - - def full(f, *args): - for _ in range(10): - f(*args) - - def clear(f): - for _ in range(10): - f.cache_clear() - - orig_si = sys.getswitchinterval() - sys.setswitchinterval(1e-6) - try: - # create 5 threads in order to fill cache - threads = [] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() - - hits, misses, maxsize, currsize = f.cache_info() - self.assertEqual(hits, 45) - self.assertEqual(misses, 5) - self.assertEqual(currsize, 5) - - # create 5 threads in order to fill cache and 1 to clear it - cleaner = threading.Thread(target=clear, args=[f]) - cleaner.start() - threads = [cleaner] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() - finally: - sys.setswitchinterval(orig_si) + functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) def test_need_for_rlock(self): # This will deadlock on an LRU cache that uses a regular lock - @self.module.lru_cache(maxsize=10) + @functools.lru_cache(maxsize=10) def test_func(x): 'Used to demonstrate a reentrant lru_cache call within a single thread' return x @@ -1179,12 +1110,6 @@ def f(): pass -class TestLRUC(TestLRU, unittest.TestCase): - module = c_functools - -class TestLRUPy(TestLRU, unittest.TestCase): - module = py_functools - class TestSingleDispatch(unittest.TestCase): def test_simple_overloads(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,9 +63,6 @@ Library ------- -- Issue #14373: Added C implementation of functools.lru_cache(). Based on - patches by Matt Joiner and Alexey Kachayev. - - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -590,539 +590,6 @@ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); -/* lru_cache object **********************************************************/ - -/* this object is used delimit args and keywords in the cache keys */ -static PyObject *kwd_mark = NULL; - -struct lru_list_elem; -struct lru_cache_object; - -typedef struct lru_list_elem { - PyObject_HEAD - struct lru_list_elem *prev, *next; /* borrowed links */ - PyObject *key, *result; -} lru_list_elem; - -static void -lru_list_elem_dealloc(lru_list_elem *link) -{ - _PyObject_GC_UNTRACK(link); - Py_XDECREF(link->key); - Py_XDECREF(link->result); - PyObject_GC_Del(link); -} - -static int -lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg) -{ - Py_VISIT(link->key); - Py_VISIT(link->result); - return 0; -} - -static int -lru_list_elem_clear(lru_list_elem *link) -{ - Py_CLEAR(link->key); - Py_CLEAR(link->result); - return 0; -} - -static PyTypeObject lru_list_elem_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "functools._lru_list_elem", /* tp_name */ - sizeof(lru_list_elem), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_list_elem_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)lru_list_elem_traverse, /* tp_traverse */ - (inquiry)lru_list_elem_clear, /* tp_clear */ -}; - - -typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); - -typedef struct lru_cache_object { - lru_list_elem root; /* includes PyObject_HEAD */ - Py_ssize_t maxsize; - PyObject *maxsize_O; - PyObject *func; - lru_cache_ternaryfunc wrapper; - PyObject *cache; - PyObject *cache_info_type; - Py_ssize_t misses, hits; - int typed; - PyObject *dict; - int full; -} lru_cache_object; - -static PyTypeObject lru_cache_type; - -static PyObject * -lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) -{ - PyObject *key, *sorted_items; - Py_ssize_t key_size, pos, key_pos; - - /* short path, key will match args anyway, which is a tuple */ - if (!typed && !kwds) { - Py_INCREF(args); - return args; - } - - if (kwds && PyDict_Size(kwds) > 0) { - sorted_items = PyDict_Items(kwds); - if (!sorted_items) - return NULL; - if (PyList_Sort(sorted_items) < 0) { - Py_DECREF(sorted_items); - return NULL; - } - } else - sorted_items = NULL; - - key_size = PyTuple_GET_SIZE(args); - if (sorted_items) - key_size += PyList_GET_SIZE(sorted_items); - if (typed) - key_size *= 2; - if (sorted_items) - key_size++; - - key = PyTuple_New(key_size); - if (key == NULL) - goto done; - - key_pos = 0; - for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { - PyObject *item = PyTuple_GET_ITEM(args, pos); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - if (sorted_items) { - Py_INCREF(kwd_mark); - PyTuple_SET_ITEM(key, key_pos++, kwd_mark); - for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { - PyObject *item = PyList_GET_ITEM(sorted_items, pos); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - } - if (typed) { - for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { - PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - if (sorted_items) { - for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { - PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); - PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - } - } - assert(key_pos == key_size); - -done: - if (sorted_items) - Py_DECREF(sorted_items); - return key; -} - -static PyObject * -uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - PyObject *result = PyObject_Call(self->func, args, kwds); - if (!result) - return NULL; - self->misses++; - return result; -} - -static PyObject * -infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - PyObject *result; - PyObject *key = lru_cache_make_key(args, kwds, self->typed); - if (!key) - return NULL; - result = PyDict_GetItemWithError(self->cache, key); - if (result) { - Py_INCREF(result); - self->hits++; - Py_DECREF(key); - return result; - } - if (PyErr_Occurred()) { - Py_DECREF(key); - return NULL; - } - result = PyObject_Call(self->func, args, kwds); - if (!result) { - Py_DECREF(key); - return NULL; - } - if (PyDict_SetItem(self->cache, key, result) < 0) { - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } - Py_DECREF(key); - self->misses++; - return result; -} - -static void -lru_cache_extricate_link(lru_list_elem *link) -{ - link->prev->next = link->next; - link->next->prev = link->prev; -} - -static void -lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) -{ - lru_list_elem *root = &self->root; - lru_list_elem *last = root->prev; - last->next = root->prev = link; - link->prev = last; - link->next = root; -} - -static PyObject * -bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - lru_list_elem *link; - PyObject *key, *result; - - key = lru_cache_make_key(args, kwds, self->typed); - if (!key) - return NULL; - link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); - if (link) { - lru_cache_extricate_link(link); - lru_cache_append_link(self, link); - self->hits++; - result = link->result; - Py_INCREF(result); - Py_DECREF(key); - return result; - } - if (PyErr_Occurred()) { - Py_DECREF(key); - return NULL; - } - result = PyObject_Call(self->func, args, kwds); - if (!result) { - Py_DECREF(key); - return NULL; - } - if (self->full && self->root.next != &self->root) { - /* Use the oldest item to store the new key and result. */ - PyObject *oldkey, *oldresult; - /* Extricate the oldest item. */ - link = self->root.next; - lru_cache_extricate_link(link); - /* Remove it from the cache. - The cache dict holds one reference to the link, - and the linked list holds yet one reference to it. */ - if (PyDict_DelItem(self->cache, link->key) < 0) { - lru_cache_append_link(self, link); - Py_DECREF(key); - Py_DECREF(result); - return NULL; - } - /* Keep a reference to the old key and old result to - prevent their ref counts from going to zero during the - update. That will prevent potentially arbitrary object - clean-up code (i.e. __del__) from running while we're - still adjusting the links. */ - oldkey = link->key; - oldresult = link->result; - - link->key = key; - link->result = result; - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { - Py_DECREF(link); - Py_DECREF(oldkey); - Py_DECREF(oldresult); - return NULL; - } - lru_cache_append_link(self, link); - Py_INCREF(result); /* for return */ - Py_DECREF(oldkey); - Py_DECREF(oldresult); - } else { - /* Put result in a new link at the front of the queue. */ - link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, - &lru_list_elem_type); - if (link == NULL) { - Py_DECREF(key); - Py_DECREF(result); - return NULL; - } - - link->key = key; - link->result = result; - _PyObject_GC_TRACK(link); - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { - Py_DECREF(link); - return NULL; - } - lru_cache_append_link(self, link); - Py_INCREF(result); /* for return */ - self->full = (PyDict_Size(self->cache) >= self->maxsize); - } - self->misses++; - return result; -} - -static PyObject * -lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *func, *maxsize_O, *cache_info_type; - int typed; - lru_cache_object *obj; - Py_ssize_t maxsize; - PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); - static char *keywords[] = {"user_function", "maxsize", "typed", - "cache_info_type", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, - &func, &maxsize_O, &typed, - &cache_info_type)) { - return NULL; - } - - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, - "the first argument must be callable"); - return NULL; - } - - /* select the caching function, and make/inc maxsize_O */ - if (maxsize_O == Py_None) { - wrapper = infinite_lru_cache_wrapper; - /* use this only to initialize lru_cache_object attribute maxsize */ - maxsize = -1; - } else if (PyIndex_Check(maxsize_O)) { - maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); - if (maxsize == -1 && PyErr_Occurred()) - return NULL; - if (maxsize == 0) - wrapper = uncached_lru_cache_wrapper; - else - wrapper = bounded_lru_cache_wrapper; - } else { - PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); - return NULL; - } - - obj = (lru_cache_object *)type->tp_alloc(type, 0); - if (obj == NULL) - return NULL; - - if (!(obj->cache = PyDict_New())) { - Py_DECREF(obj); - return NULL; - } - - obj->root.prev = &obj->root; - obj->root.next = &obj->root; - obj->maxsize = maxsize; - Py_INCREF(maxsize_O); - obj->maxsize_O = maxsize_O; - Py_INCREF(func); - obj->func = func; - obj->wrapper = wrapper; - obj->misses = obj->hits = 0; - obj->typed = typed; - Py_INCREF(cache_info_type); - obj->cache_info_type = cache_info_type; - - return (PyObject *)obj; -} - -static lru_list_elem * -lru_cache_unlink_list(lru_cache_object *self) -{ - lru_list_elem *root = &self->root; - lru_list_elem *link = root->next; - if (link == root) - return NULL; - root->prev->next = NULL; - root->next = root->prev = root; - return link; -} - -static void -lru_cache_clear_list(lru_list_elem *link) -{ - while (link != NULL) { - lru_list_elem *next = link->next; - Py_DECREF(link); - link = next; - } -} - -static void -lru_cache_dealloc(lru_cache_object *obj) -{ - lru_list_elem *list = lru_cache_unlink_list(obj); - Py_XDECREF(obj->maxsize_O); - Py_XDECREF(obj->func); - Py_XDECREF(obj->cache); - Py_XDECREF(obj->dict); - Py_XDECREF(obj->cache_info_type); - lru_cache_clear_list(list); - Py_TYPE(obj)->tp_free(obj); -} - -static PyObject * -lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - return self->wrapper(self, args, kwds); -} - -static PyObject * -lru_cache_cache_info(lru_cache_object *self, PyObject *unused) -{ - return PyObject_CallFunction(self->cache_info_type, "nnOn", - self->hits, self->misses, self->maxsize_O, - PyDict_Size(self->cache)); -} - -static PyObject * -lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) -{ - lru_list_elem *list = lru_cache_unlink_list(self); - self->hits = self->misses = 0; - self->full = 0; - PyDict_Clear(self->cache); - lru_cache_clear_list(list); - Py_RETURN_NONE; -} - -static int -lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) -{ - lru_list_elem *link = self->root.next; - while (link != &self->root) { - lru_list_elem *next = link->next; - Py_VISIT(link); - link = next; - } - Py_VISIT(self->maxsize_O); - Py_VISIT(self->func); - Py_VISIT(self->cache); - Py_VISIT(self->cache_info_type); - Py_VISIT(self->dict); - return 0; -} - -static int -lru_cache_tp_clear(lru_cache_object *self) -{ - lru_list_elem *list = lru_cache_unlink_list(self); - Py_CLEAR(self->maxsize_O); - Py_CLEAR(self->func); - Py_CLEAR(self->cache); - Py_CLEAR(self->cache_info_type); - Py_CLEAR(self->dict); - lru_cache_clear_list(list); - return 0; -} - - -PyDoc_STRVAR(lru_cache_doc, -"Create a cached callable that wraps another function.\n\ -\n\ -user_function: the function being cached\n\ -\n\ -maxsize: 0 for no caching\n\ - None for unlimited cache size\n\ - n for a bounded cache\n\ -\n\ -typed: False cache f(3) and f(3.0) as identical calls\n\ - True cache f(3) and f(3.0) as distinct calls\n\ -\n\ -cache_info_type: namedtuple class with the fields:\n\ - hits misses currsize maxsize\n" -); - -static PyMethodDef lru_cache_methods[] = { - {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, - {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, - {NULL} -}; - -static PyGetSetDef lru_cache_getsetlist[] = { - {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, - {NULL} -}; - -static PyTypeObject lru_cache_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "functools._lru_cache_wrapper", /* tp_name */ - sizeof(lru_cache_object), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_cache_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 */ - (ternaryfunc)lru_cache_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - lru_cache_doc, /* tp_doc */ - (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ - (inquiry)lru_cache_tp_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - lru_cache_methods, /* tp_methods */ - 0, /* tp_members */ - lru_cache_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(lru_cache_object, dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - lru_cache_new, /* tp_new */ -}; - /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -1135,11 +602,6 @@ {NULL, NULL} /* sentinel */ }; -static void -module_free(void *m) -{ - Py_CLEAR(kwd_mark); -} static struct PyModuleDef _functoolsmodule = { PyModuleDef_HEAD_INIT, @@ -1150,7 +612,7 @@ NULL, NULL, NULL, - module_free, + NULL }; PyMODINIT_FUNC @@ -1161,7 +623,6 @@ char *name; PyTypeObject *typelist[] = { &partial_type, - &lru_cache_type, NULL }; @@ -1169,12 +630,6 @@ if (m == NULL) return NULL; - kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL); - if (!kwd_mark) { - Py_DECREF(m); - return NULL; - } - for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) { Py_DECREF(m); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:07:10 2015 From: python-checkins at python.org (larry.hastings) Date: Sat, 23 May 2015 22:07:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset_57776?= =?utf-8?q?eee74f2?= Message-ID: <20150523220710.27925.17302@psf.io> https://hg.python.org/cpython/rev/b0a0b9b59012 changeset: 96259:b0a0b9b59012 parent: 96246:57776eee74f2 user: Larry Hastings date: Sat May 23 14:56:23 2015 -0700 summary: Backed out changeset 57776eee74f2 files: Lib/functools.py | 207 ++++---- Lib/test/test_functools.py | 109 +---- Misc/NEWS | 3 - Modules/_functoolsmodule.c | 547 +------------------------ 4 files changed, 117 insertions(+), 749 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -419,129 +419,120 @@ if maxsize is not None and not isinstance(maxsize, int): raise TypeError('Expected maxsize to be an integer or None') - def decorating_function(user_function): - wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) - return update_wrapper(wrapper, user_function) - - return decorating_function - -def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): # Constants shared by all lru cache instances: sentinel = object() # unique object used to signal cache misses make_key = _make_key # build a key from the function arguments PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self + def decorating_function(user_function): + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self - if maxsize == 0: + if maxsize == 0: - def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call - nonlocal misses - result = user_function(*args, **kwds) - misses += 1 - return result + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result - elif maxsize is None: + elif maxsize is None: - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: - hits += 1 - return result - result = user_function(*args, **kwds) - cache[key] = result - misses += 1 - return result - - else: - - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: hits += 1 return result - result = user_function(*args, **kwds) + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result + + else: + + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root + hits += 1 + return result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + full = (len(cache) >= maxsize) + misses += 1 + return result + + def cache_info(): + """Report cache statistics""" with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) >= maxsize) - misses += 1 - return result + return _CacheInfo(hits, misses, maxsize, len(cache)) - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return update_wrapper(wrapper, user_function) - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return update_wrapper(wrapper, user_function) - -try: - from _functools import _lru_cache_wrapper -except ImportError: - pass + return decorating_function ################################################################################ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -7,10 +7,6 @@ from test import support import unittest from weakref import proxy -try: - import threading -except ImportError: - threading = None import functools @@ -916,12 +912,12 @@ return self.value == other.value -class TestLRU: +class TestLRU(unittest.TestCase): def test_lru(self): def orig(x, y): return 3 * x + y - f = self.module.lru_cache(maxsize=20)(orig) + f = functools.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) self.assertEqual(currsize, 0) @@ -959,7 +955,7 @@ self.assertEqual(currsize, 1) # test size zero (which means "never-cache") - @self.module.lru_cache(0) + @functools.lru_cache(0) def f(): nonlocal f_cnt f_cnt += 1 @@ -975,7 +971,7 @@ self.assertEqual(currsize, 0) # test size one - @self.module.lru_cache(1) + @functools.lru_cache(1) def f(): nonlocal f_cnt f_cnt += 1 @@ -991,7 +987,7 @@ self.assertEqual(currsize, 1) # test size two - @self.module.lru_cache(2) + @functools.lru_cache(2) def f(x): nonlocal f_cnt f_cnt += 1 @@ -1008,7 +1004,7 @@ self.assertEqual(currsize, 2) def test_lru_with_maxsize_none(self): - @self.module.lru_cache(maxsize=None) + @functools.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1016,26 +1012,17 @@ self.assertEqual([fib(n) for n in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) - - def test_lru_with_maxsize_negative(self): - @self.module.lru_cache(maxsize=-10) - def eq(n): - return n - for i in (0, 1): - self.assertEqual([eq(n) for n in range(150)], list(range(150))) - self.assertEqual(eq.cache_info(), - self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) + functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): - @self.module.lru_cache(maxsize) + @functools.lru_cache(maxsize) def func(i): return 'abc'[i] self.assertEqual(func(0), 'a') @@ -1048,7 +1035,7 @@ def test_lru_with_types(self): for maxsize in (None, 128): - @self.module.lru_cache(maxsize=maxsize, typed=True) + @functools.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x self.assertEqual(square(3), 9) @@ -1063,7 +1050,7 @@ self.assertEqual(square.cache_info().misses, 4) def test_lru_with_keyword_args(self): - @self.module.lru_cache() + @functools.lru_cache() def fib(n): if n < 2: return n @@ -1073,13 +1060,13 @@ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] ) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) def test_lru_with_keyword_args_maxsize_none(self): - @self.module.lru_cache(maxsize=None) + @functools.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1087,71 +1074,15 @@ self.assertEqual([fib(n=number) for number in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) - - def test_lru_cache_decoration(self): - def f(zomg: 'zomg_annotation'): - """f doc string""" - return 42 - g = self.module.lru_cache()(f) - for attr in self.module.WRAPPER_ASSIGNMENTS: - self.assertEqual(getattr(g, attr), getattr(f, attr)) - - @unittest.skipUnless(threading, 'This test requires threading.') - def test_lru_cache_threaded(self): - def orig(x, y): - return 3 * x + y - f = self.module.lru_cache(maxsize=20)(orig) - hits, misses, maxsize, currsize = f.cache_info() - self.assertEqual(currsize, 0) - - def full(f, *args): - for _ in range(10): - f(*args) - - def clear(f): - for _ in range(10): - f.cache_clear() - - orig_si = sys.getswitchinterval() - sys.setswitchinterval(1e-6) - try: - # create 5 threads in order to fill cache - threads = [] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() - - hits, misses, maxsize, currsize = f.cache_info() - self.assertEqual(hits, 45) - self.assertEqual(misses, 5) - self.assertEqual(currsize, 5) - - # create 5 threads in order to fill cache and 1 to clear it - cleaner = threading.Thread(target=clear, args=[f]) - cleaner.start() - threads = [cleaner] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() - finally: - sys.setswitchinterval(orig_si) + functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) def test_need_for_rlock(self): # This will deadlock on an LRU cache that uses a regular lock - @self.module.lru_cache(maxsize=10) + @functools.lru_cache(maxsize=10) def test_func(x): 'Used to demonstrate a reentrant lru_cache call within a single thread' return x @@ -1179,12 +1110,6 @@ def f(): pass -class TestLRUC(TestLRU, unittest.TestCase): - module = c_functools - -class TestLRUPy(TestLRU, unittest.TestCase): - module = py_functools - class TestSingleDispatch(unittest.TestCase): def test_simple_overloads(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,9 +63,6 @@ Library ------- -- Issue #14373: Added C implementation of functools.lru_cache(). Based on - patches by Matt Joiner and Alexey Kachayev. - - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -590,539 +590,6 @@ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); -/* lru_cache object **********************************************************/ - -/* this object is used delimit args and keywords in the cache keys */ -static PyObject *kwd_mark = NULL; - -struct lru_list_elem; -struct lru_cache_object; - -typedef struct lru_list_elem { - PyObject_HEAD - struct lru_list_elem *prev, *next; /* borrowed links */ - PyObject *key, *result; -} lru_list_elem; - -static void -lru_list_elem_dealloc(lru_list_elem *link) -{ - _PyObject_GC_UNTRACK(link); - Py_XDECREF(link->key); - Py_XDECREF(link->result); - PyObject_GC_Del(link); -} - -static int -lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg) -{ - Py_VISIT(link->key); - Py_VISIT(link->result); - return 0; -} - -static int -lru_list_elem_clear(lru_list_elem *link) -{ - Py_CLEAR(link->key); - Py_CLEAR(link->result); - return 0; -} - -static PyTypeObject lru_list_elem_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "functools._lru_list_elem", /* tp_name */ - sizeof(lru_list_elem), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_list_elem_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)lru_list_elem_traverse, /* tp_traverse */ - (inquiry)lru_list_elem_clear, /* tp_clear */ -}; - - -typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); - -typedef struct lru_cache_object { - lru_list_elem root; /* includes PyObject_HEAD */ - Py_ssize_t maxsize; - PyObject *maxsize_O; - PyObject *func; - lru_cache_ternaryfunc wrapper; - PyObject *cache; - PyObject *cache_info_type; - Py_ssize_t misses, hits; - int typed; - PyObject *dict; - int full; -} lru_cache_object; - -static PyTypeObject lru_cache_type; - -static PyObject * -lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) -{ - PyObject *key, *sorted_items; - Py_ssize_t key_size, pos, key_pos; - - /* short path, key will match args anyway, which is a tuple */ - if (!typed && !kwds) { - Py_INCREF(args); - return args; - } - - if (kwds && PyDict_Size(kwds) > 0) { - sorted_items = PyDict_Items(kwds); - if (!sorted_items) - return NULL; - if (PyList_Sort(sorted_items) < 0) { - Py_DECREF(sorted_items); - return NULL; - } - } else - sorted_items = NULL; - - key_size = PyTuple_GET_SIZE(args); - if (sorted_items) - key_size += PyList_GET_SIZE(sorted_items); - if (typed) - key_size *= 2; - if (sorted_items) - key_size++; - - key = PyTuple_New(key_size); - if (key == NULL) - goto done; - - key_pos = 0; - for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { - PyObject *item = PyTuple_GET_ITEM(args, pos); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - if (sorted_items) { - Py_INCREF(kwd_mark); - PyTuple_SET_ITEM(key, key_pos++, kwd_mark); - for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { - PyObject *item = PyList_GET_ITEM(sorted_items, pos); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - } - if (typed) { - for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { - PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - if (sorted_items) { - for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { - PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); - PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); - Py_INCREF(item); - PyTuple_SET_ITEM(key, key_pos++, item); - } - } - } - assert(key_pos == key_size); - -done: - if (sorted_items) - Py_DECREF(sorted_items); - return key; -} - -static PyObject * -uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - PyObject *result = PyObject_Call(self->func, args, kwds); - if (!result) - return NULL; - self->misses++; - return result; -} - -static PyObject * -infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - PyObject *result; - PyObject *key = lru_cache_make_key(args, kwds, self->typed); - if (!key) - return NULL; - result = PyDict_GetItemWithError(self->cache, key); - if (result) { - Py_INCREF(result); - self->hits++; - Py_DECREF(key); - return result; - } - if (PyErr_Occurred()) { - Py_DECREF(key); - return NULL; - } - result = PyObject_Call(self->func, args, kwds); - if (!result) { - Py_DECREF(key); - return NULL; - } - if (PyDict_SetItem(self->cache, key, result) < 0) { - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } - Py_DECREF(key); - self->misses++; - return result; -} - -static void -lru_cache_extricate_link(lru_list_elem *link) -{ - link->prev->next = link->next; - link->next->prev = link->prev; -} - -static void -lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) -{ - lru_list_elem *root = &self->root; - lru_list_elem *last = root->prev; - last->next = root->prev = link; - link->prev = last; - link->next = root; -} - -static PyObject * -bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - lru_list_elem *link; - PyObject *key, *result; - - key = lru_cache_make_key(args, kwds, self->typed); - if (!key) - return NULL; - link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); - if (link) { - lru_cache_extricate_link(link); - lru_cache_append_link(self, link); - self->hits++; - result = link->result; - Py_INCREF(result); - Py_DECREF(key); - return result; - } - if (PyErr_Occurred()) { - Py_DECREF(key); - return NULL; - } - result = PyObject_Call(self->func, args, kwds); - if (!result) { - Py_DECREF(key); - return NULL; - } - if (self->full && self->root.next != &self->root) { - /* Use the oldest item to store the new key and result. */ - PyObject *oldkey, *oldresult; - /* Extricate the oldest item. */ - link = self->root.next; - lru_cache_extricate_link(link); - /* Remove it from the cache. - The cache dict holds one reference to the link, - and the linked list holds yet one reference to it. */ - if (PyDict_DelItem(self->cache, link->key) < 0) { - lru_cache_append_link(self, link); - Py_DECREF(key); - Py_DECREF(result); - return NULL; - } - /* Keep a reference to the old key and old result to - prevent their ref counts from going to zero during the - update. That will prevent potentially arbitrary object - clean-up code (i.e. __del__) from running while we're - still adjusting the links. */ - oldkey = link->key; - oldresult = link->result; - - link->key = key; - link->result = result; - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { - Py_DECREF(link); - Py_DECREF(oldkey); - Py_DECREF(oldresult); - return NULL; - } - lru_cache_append_link(self, link); - Py_INCREF(result); /* for return */ - Py_DECREF(oldkey); - Py_DECREF(oldresult); - } else { - /* Put result in a new link at the front of the queue. */ - link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, - &lru_list_elem_type); - if (link == NULL) { - Py_DECREF(key); - Py_DECREF(result); - return NULL; - } - - link->key = key; - link->result = result; - _PyObject_GC_TRACK(link); - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { - Py_DECREF(link); - return NULL; - } - lru_cache_append_link(self, link); - Py_INCREF(result); /* for return */ - self->full = (PyDict_Size(self->cache) >= self->maxsize); - } - self->misses++; - return result; -} - -static PyObject * -lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *func, *maxsize_O, *cache_info_type; - int typed; - lru_cache_object *obj; - Py_ssize_t maxsize; - PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); - static char *keywords[] = {"user_function", "maxsize", "typed", - "cache_info_type", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, - &func, &maxsize_O, &typed, - &cache_info_type)) { - return NULL; - } - - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, - "the first argument must be callable"); - return NULL; - } - - /* select the caching function, and make/inc maxsize_O */ - if (maxsize_O == Py_None) { - wrapper = infinite_lru_cache_wrapper; - /* use this only to initialize lru_cache_object attribute maxsize */ - maxsize = -1; - } else if (PyIndex_Check(maxsize_O)) { - maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); - if (maxsize == -1 && PyErr_Occurred()) - return NULL; - if (maxsize == 0) - wrapper = uncached_lru_cache_wrapper; - else - wrapper = bounded_lru_cache_wrapper; - } else { - PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); - return NULL; - } - - obj = (lru_cache_object *)type->tp_alloc(type, 0); - if (obj == NULL) - return NULL; - - if (!(obj->cache = PyDict_New())) { - Py_DECREF(obj); - return NULL; - } - - obj->root.prev = &obj->root; - obj->root.next = &obj->root; - obj->maxsize = maxsize; - Py_INCREF(maxsize_O); - obj->maxsize_O = maxsize_O; - Py_INCREF(func); - obj->func = func; - obj->wrapper = wrapper; - obj->misses = obj->hits = 0; - obj->typed = typed; - Py_INCREF(cache_info_type); - obj->cache_info_type = cache_info_type; - - return (PyObject *)obj; -} - -static lru_list_elem * -lru_cache_unlink_list(lru_cache_object *self) -{ - lru_list_elem *root = &self->root; - lru_list_elem *link = root->next; - if (link == root) - return NULL; - root->prev->next = NULL; - root->next = root->prev = root; - return link; -} - -static void -lru_cache_clear_list(lru_list_elem *link) -{ - while (link != NULL) { - lru_list_elem *next = link->next; - Py_DECREF(link); - link = next; - } -} - -static void -lru_cache_dealloc(lru_cache_object *obj) -{ - lru_list_elem *list = lru_cache_unlink_list(obj); - Py_XDECREF(obj->maxsize_O); - Py_XDECREF(obj->func); - Py_XDECREF(obj->cache); - Py_XDECREF(obj->dict); - Py_XDECREF(obj->cache_info_type); - lru_cache_clear_list(list); - Py_TYPE(obj)->tp_free(obj); -} - -static PyObject * -lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) -{ - return self->wrapper(self, args, kwds); -} - -static PyObject * -lru_cache_cache_info(lru_cache_object *self, PyObject *unused) -{ - return PyObject_CallFunction(self->cache_info_type, "nnOn", - self->hits, self->misses, self->maxsize_O, - PyDict_Size(self->cache)); -} - -static PyObject * -lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) -{ - lru_list_elem *list = lru_cache_unlink_list(self); - self->hits = self->misses = 0; - self->full = 0; - PyDict_Clear(self->cache); - lru_cache_clear_list(list); - Py_RETURN_NONE; -} - -static int -lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) -{ - lru_list_elem *link = self->root.next; - while (link != &self->root) { - lru_list_elem *next = link->next; - Py_VISIT(link); - link = next; - } - Py_VISIT(self->maxsize_O); - Py_VISIT(self->func); - Py_VISIT(self->cache); - Py_VISIT(self->cache_info_type); - Py_VISIT(self->dict); - return 0; -} - -static int -lru_cache_tp_clear(lru_cache_object *self) -{ - lru_list_elem *list = lru_cache_unlink_list(self); - Py_CLEAR(self->maxsize_O); - Py_CLEAR(self->func); - Py_CLEAR(self->cache); - Py_CLEAR(self->cache_info_type); - Py_CLEAR(self->dict); - lru_cache_clear_list(list); - return 0; -} - - -PyDoc_STRVAR(lru_cache_doc, -"Create a cached callable that wraps another function.\n\ -\n\ -user_function: the function being cached\n\ -\n\ -maxsize: 0 for no caching\n\ - None for unlimited cache size\n\ - n for a bounded cache\n\ -\n\ -typed: False cache f(3) and f(3.0) as identical calls\n\ - True cache f(3) and f(3.0) as distinct calls\n\ -\n\ -cache_info_type: namedtuple class with the fields:\n\ - hits misses currsize maxsize\n" -); - -static PyMethodDef lru_cache_methods[] = { - {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, - {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, - {NULL} -}; - -static PyGetSetDef lru_cache_getsetlist[] = { - {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, - {NULL} -}; - -static PyTypeObject lru_cache_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "functools._lru_cache_wrapper", /* tp_name */ - sizeof(lru_cache_object), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_cache_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 */ - (ternaryfunc)lru_cache_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - lru_cache_doc, /* tp_doc */ - (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ - (inquiry)lru_cache_tp_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - lru_cache_methods, /* tp_methods */ - 0, /* tp_members */ - lru_cache_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(lru_cache_object, dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - lru_cache_new, /* tp_new */ -}; - /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -1135,11 +602,6 @@ {NULL, NULL} /* sentinel */ }; -static void -module_free(void *m) -{ - Py_CLEAR(kwd_mark); -} static struct PyModuleDef _functoolsmodule = { PyModuleDef_HEAD_INIT, @@ -1150,7 +612,7 @@ NULL, NULL, NULL, - module_free, + NULL }; PyMODINIT_FUNC @@ -1161,7 +623,6 @@ char *name; PyTypeObject *typelist[] = { &partial_type, - &lru_cache_type, NULL }; @@ -1169,12 +630,6 @@ if (m == NULL) return NULL; - kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL); - if (!kwd_mark) { - Py_DECREF(m); - return NULL; - } - for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) { Py_DECREF(m); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:16:43 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 22:16:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Add_pointer_to?= =?utf-8?q?_IDLE_what=27s_new_file=2E?= Message-ID: <20150523221643.96192.76144@psf.io> https://hg.python.org/cpython/rev/4d59c96971ea changeset: 96261:4d59c96971ea branch: 3.4 parent: 96255:e8cab5bef4f1 user: Terry Jan Reedy date: Sat May 23 18:13:14 2015 -0400 summary: Add pointer to IDLE what's new file. files: Doc/whatsnew/3.4.rst | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -967,6 +967,16 @@ (Contributed by Malte Swart in :issue:`17764`.) +idlelib and IDLE +---------------- + +Since idlelib implements the IDLE shell and editor and is not intended for +import by other programs, it gets improvements with every release. See +:file:`Lib/idlelib/NEWS.txt` for a cumulative list of changes since 3.3.0, +as well as changes made in future 3.4.x releases. This file is also available +from the IDLE Help -> About Idle dialog. + + importlib --------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:16:43 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 22:16:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_whitespace?= Message-ID: <20150523221643.96198.93414@psf.io> https://hg.python.org/cpython/rev/161d08bd1605 changeset: 96263:161d08bd1605 branch: 3.4 parent: 96261:4d59c96971ea user: Terry Jan Reedy date: Sat May 23 18:15:18 2015 -0400 summary: whitespace files: Doc/whatsnew/3.4.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -974,7 +974,7 @@ import by other programs, it gets improvements with every release. See :file:`Lib/idlelib/NEWS.txt` for a cumulative list of changes since 3.3.0, as well as changes made in future 3.4.x releases. This file is also available -from the IDLE Help -> About Idle dialog. +from the IDLE Help -> About Idle dialog. importlib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:16:43 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 22:16:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150523221643.70427.11070@psf.io> https://hg.python.org/cpython/rev/e4f15eb8e471 changeset: 96262:e4f15eb8e471 parent: 96260:423546c86416 parent: 96261:4d59c96971ea user: Terry Jan Reedy date: Sat May 23 18:13:31 2015 -0400 summary: Merge with 3.4 files: Doc/whatsnew/3.4.rst | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -967,6 +967,16 @@ (Contributed by Malte Swart in :issue:`17764`.) +idlelib and IDLE +---------------- + +Since idlelib implements the IDLE shell and editor and is not intended for +import by other programs, it gets improvements with every release. See +:file:`Lib/idlelib/NEWS.txt` for a cumulative list of changes since 3.3.0, +as well as changes made in future 3.4.x releases. This file is also available +from the IDLE Help -> About Idle dialog. + + importlib --------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:16:43 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 22:16:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <20150523221643.16695.62856@psf.io> https://hg.python.org/cpython/rev/6c208ce96789 changeset: 96264:6c208ce96789 parent: 96262:e4f15eb8e471 parent: 96263:161d08bd1605 user: Terry Jan Reedy date: Sat May 23 18:15:41 2015 -0400 summary: Merge with 3.4 files: Doc/whatsnew/3.4.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -974,7 +974,7 @@ import by other programs, it gets improvements with every release. See :file:`Lib/idlelib/NEWS.txt` for a cumulative list of changes since 3.3.0, as well as changes made in future 3.4.x releases. This file is also available -from the IDLE Help -> About Idle dialog. +from the IDLE Help -> About Idle dialog. importlib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:20:05 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 23 May 2015 22:20:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_pointer_to_IDLE_what?= =?utf-8?q?=27s_new_file=2E?= Message-ID: <20150523222004.27955.63966@psf.io> https://hg.python.org/cpython/rev/a2d08ac0b821 changeset: 96265:a2d08ac0b821 user: Terry Jan Reedy date: Sat May 23 18:19:42 2015 -0400 summary: Add pointer to IDLE what's new file. files: Doc/whatsnew/3.5.rst | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -437,6 +437,15 @@ subdirectories using the "``**``" pattern. (Contributed by Serhiy Storchaka in :issue:`13968`.) + idlelib and IDLE +---------------- + +Since idlelib implements the IDLE shell and editor and is not intended for +import by other programs, it gets improvements with every release. See +:file:`Lib/idlelib/NEWS.txt` for a cumulative list of changes since 3.4.0, +as well as changes made in future 3.5.x releases. This file is also available +from the IDLE Help -> About Idle dialog. + imaplib ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 00:28:01 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 23 May 2015 22:28:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_bad_indent_in_whatsnew?= =?utf-8?b?LzMuNS5yc3Qu?= Message-ID: <20150523222801.45375.9628@psf.io> https://hg.python.org/cpython/rev/a36c5850c730 changeset: 96266:a36c5850c730 user: Guido van Rossum date: Sat May 23 15:27:51 2015 -0700 summary: Fix bad indent in whatsnew/3.5.rst. files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -437,7 +437,7 @@ subdirectories using the "``**``" pattern. (Contributed by Serhiy Storchaka in :issue:`13968`.) - idlelib and IDLE +idlelib and IDLE ---------------- Since idlelib implements the IDLE shell and editor and is not intended for -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 02:35:00 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 24 May 2015 00:35:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixes_handling_of_long_val?= =?utf-8?q?ues_of_PYTHONPATH_on_Windows=2E?= Message-ID: <20150524003500.126972.49825@psf.io> https://hg.python.org/cpython/rev/3dde95d1ddfb changeset: 96267:3dde95d1ddfb user: Steve Dower date: Sat May 23 17:34:50 2015 -0700 summary: Fixes handling of long values of PYTHONPATH on Windows. files: PC/getpathp.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/PC/getpathp.c b/PC/getpathp.c --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -620,21 +620,21 @@ if (*p == DELIM) bufsz++; /* number of DELIM plus one */ } - bufsz *= wcsnlen_s(pythonhome, MAXPATHLEN+1); + bufsz *= wcslen(pythonhome); } else bufsz = 0; - bufsz += wcsnlen_s(PYTHONPATH, MAXPATHLEN+1) + 1; - bufsz += wcsnlen_s(argv0_path, MAXPATHLEN+1) + 1; + bufsz += wcslen(PYTHONPATH) + 1; + bufsz += wcslen(argv0_path) + 1; #ifdef MS_WINDOWS if (!applocal && userpath) - bufsz += wcsnlen_s(userpath, MAXPATHLEN+1) + 1; + bufsz += wcslen(userpath) + 1; if (!applocal && machinepath) - bufsz += wcsnlen_s(machinepath, MAXPATHLEN+1) + 1; - bufsz += wcsnlen_s(zip_path, MAXPATHLEN+1) + 1; + bufsz += wcslen(machinepath) + 1; + bufsz += wcslen(zip_path) + 1; #endif if (envpath != NULL) - bufsz += wcsnlen_s(envpath, MAXPATHLEN+1) + 1; + bufsz += wcslen(envpath) + 1; module_search_path = buf = PyMem_RawMalloc(bufsz*sizeof(wchar_t)); if (buf == NULL) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 02:52:29 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 24 May 2015 00:52:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Prevents_attempt_to_sign_Z?= =?utf-8?q?IP_file_when_building_embeddable_version=2E?= Message-ID: <20150524005229.45371.248@psf.io> https://hg.python.org/cpython/rev/310e70f2bede changeset: 96269:310e70f2bede user: Steve Dower date: Sat May 23 17:52:20 2015 -0700 summary: Prevents attempt to sign ZIP file when building embeddable version. files: Tools/msi/make_zip.proj | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj --- a/Tools/msi/make_zip.proj +++ b/Tools/msi/make_zip.proj @@ -4,6 +4,7 @@ {10487945-15D1-4092-A214-338395C4116B} python + false -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 02:52:29 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 24 May 2015 00:52:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324268=3A_Adds_PCB?= =?utf-8?q?uild_project_to_build_=5Ftestmultiphase_module=2E?= Message-ID: <20150524005229.27951.42401@psf.io> https://hg.python.org/cpython/rev/42ec976f627e changeset: 96268:42ec976f627e user: Steve Dower date: Sat May 23 17:51:54 2015 -0700 summary: Issue #24268: Adds PCBuild project to build _testmultiphase module. files: PCbuild/_testmultiphase.vcxproj | 80 +++++++++++++ PCbuild/_testmultiphase.vcxproj.filters | 22 +++ PCbuild/pcbuild.proj | 2 +- PCbuild/pcbuild.sln | 16 ++ Tools/msi/test/test_files.wxs | 12 + 5 files changed, 131 insertions(+), 1 deletions(-) diff --git a/PCbuild/_testmultiphase.vcxproj b/PCbuild/_testmultiphase.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/_testmultiphase.vcxproj @@ -0,0 +1,80 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {16BFE6F0-22EF-40B5-B831-7E937119EF10} + Win32Proj + _testmultiphase + false + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + + _CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + \ No newline at end of file diff --git a/PCbuild/_testmultiphase.vcxproj.filters b/PCbuild/_testmultiphase.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/_testmultiphase.vcxproj.filters @@ -0,0 +1,22 @@ +? + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -46,7 +46,7 @@ - + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -72,6 +72,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testembed", "_testembed.vcxproj", "{6DAC66D9-E703-4624-BE03-49112AB5AA62}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testmultiphase", "_testmultiphase.vcxproj", "{16BFE6F0-22EF-40B5-B831-7E937119EF10}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcl", "tcl.vcxproj", "{B5FD6F1D-129E-4BFF-9340-03606FAC7283}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tix", "tix.vcxproj", "{C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}" @@ -588,6 +590,20 @@ {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|Win32.Build.0 = Release|Win32 {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|x64.ActiveCfg = Release|x64 {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|x64.Build.0 = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|Win32.ActiveCfg = Debug|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|Win32.Build.0 = Debug|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|x64.ActiveCfg = Debug|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|x64.Build.0 = Debug|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGInstrument|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|Win32.Build.0 = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|x64.Build.0 = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|Win32.Build.0 = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.Build.0 = Release|x64 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.ActiveCfg = Debug|Win32 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.Build.0 = Debug|Win32 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/Tools/msi/test/test_files.wxs b/Tools/msi/test/test_files.wxs --- a/Tools/msi/test/test_files.wxs +++ b/Tools/msi/test/test_files.wxs @@ -14,6 +14,9 @@ + + + @@ -31,6 +34,9 @@ + + + @@ -48,6 +54,9 @@ + + + @@ -60,6 +69,9 @@ + + + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 03:09:04 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 24 May 2015 01:09:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Exclude_=5Ftestmultiphase?= =?utf-8?q?=2Epyd_from_embeddable_ZIP_file=2E?= Message-ID: <20150524010904.21238.63949@psf.io> https://hg.python.org/cpython/rev/2df7c958974e changeset: 96270:2df7c958974e user: Steve Dower date: Sat May 23 18:08:55 2015 -0700 summary: Exclude _testmultiphase.pyd from embeddable ZIP file. files: Tools/msi/make_zip.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -25,6 +25,7 @@ '_testbuffer.pyd', '_testcapi.pyd', '_testimportmultiple.pyd', + '_testmultiphase.pyd', 'xxlimited.pyd', } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun May 24 10:50:18 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 24 May 2015 08:50:18 +0000 Subject: [Python-checkins] Daily reference leaks (2df7c958974e): sum=226 Message-ID: <20150524085018.126980.25514@psf.io> results for 2df7c958974e on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogDMx2BS', '--timeout', '7200'] From python-checkins at python.org Sun May 24 20:38:42 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 24 May 2015 18:38:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324276=3A_Fixed_op?= =?utf-8?q?timization_of_property_descriptor_getter=2E?= Message-ID: <20150524183842.70409.81174@psf.io> https://hg.python.org/cpython/rev/5dbf3d932a59 changeset: 96271:5dbf3d932a59 user: Serhiy Storchaka date: Sun May 24 21:38:06 2015 +0300 summary: Issue #24276: Fixed optimization of property descriptor getter. files: Misc/NEWS | 2 ++ Objects/descrobject.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24276: Fixed optimization of property descriptor getter. + - Issue #24268: PEP 489: Multi-phase extension module initialization - Issue #23955: Add pyvenv.cfg option to suppress registry/environment diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1372,7 +1372,8 @@ static PyObject * property_descr_get(PyObject *self, PyObject *obj, PyObject *type) { - static PyObject *args = NULL; + static PyObject * volatile cached_args = NULL; + PyObject *args; PyObject *ret; propertyobject *gs = (propertyobject *)self; @@ -1384,12 +1385,28 @@ PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); return NULL; } - if (!args && !(args = PyTuple_New(1))) { - return NULL; + args = cached_args; + if (!args || Py_REFCNT(args) != 1) { + Py_CLEAR(cached_args); + if (!(cached_args = args = PyTuple_New(1))) + return NULL; } + Py_INCREF(args); + assert (Py_REFCNT(args) == 2); + Py_INCREF(obj); PyTuple_SET_ITEM(args, 0, obj); ret = PyObject_Call(gs->prop_get, args, NULL); - PyTuple_SET_ITEM(args, 0, NULL); + if (args == cached_args) { + if (Py_REFCNT(args) == 2) { + obj = PyTuple_GET_ITEM(args, 0); + PyTuple_SET_ITEM(args, 0, NULL); + Py_XDECREF(obj); + } + else { + Py_CLEAR(cached_args); + } + } + Py_DECREF(args); return ret; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 24 22:30:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 24 May 2015 20:30:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset=3A_b0?= =?utf-8?q?a0b9b59012?= Message-ID: <20150524203004.16311.8398@psf.io> https://hg.python.org/cpython/rev/cb30db9cc029 changeset: 96272:cb30db9cc029 user: Serhiy Storchaka date: Sun May 24 21:53:49 2015 +0300 summary: Backed out changeset: b0a0b9b59012 files: Lib/functools.py | 203 ++++---- Lib/test/test_functools.py | 109 ++++- Misc/NEWS | 3 + Modules/_functoolsmodule.c | 547 ++++++++++++++++++++++++- 4 files changed, 747 insertions(+), 115 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -419,120 +419,129 @@ if maxsize is not None and not isinstance(maxsize, int): raise TypeError('Expected maxsize to be an integer or None') + def decorating_function(user_function): + wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) + return update_wrapper(wrapper, user_function) + + return decorating_function + +def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): # Constants shared by all lru cache instances: sentinel = object() # unique object used to signal cache misses make_key = _make_key # build a key from the function arguments PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - def decorating_function(user_function): - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self - if maxsize == 0: + if maxsize == 0: - def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call - nonlocal misses - result = user_function(*args, **kwds) - misses += 1 + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result + + elif maxsize is None: + + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: + hits += 1 return result + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result - elif maxsize is None: + else: - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root hits += 1 return result - result = user_function(*args, **kwds) - cache[key] = result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + full = (len(cache) >= maxsize) misses += 1 - return result + return result - else: + def cache_info(): + """Report cache statistics""" + with lock: + return _CacheInfo(hits, misses, maxsize, len(cache)) - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - hits += 1 - return result - result = user_function(*args, **kwds) - with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) >= maxsize) - misses += 1 - return result + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return update_wrapper(wrapper, user_function) - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False - - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return update_wrapper(wrapper, user_function) - - return decorating_function +try: + from _functools import _lru_cache_wrapper +except ImportError: + pass ################################################################################ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -7,6 +7,10 @@ from test import support import unittest from weakref import proxy +try: + import threading +except ImportError: + threading = None import functools @@ -912,12 +916,12 @@ return self.value == other.value -class TestLRU(unittest.TestCase): +class TestLRU: def test_lru(self): def orig(x, y): return 3 * x + y - f = functools.lru_cache(maxsize=20)(orig) + f = self.module.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) self.assertEqual(currsize, 0) @@ -955,7 +959,7 @@ self.assertEqual(currsize, 1) # test size zero (which means "never-cache") - @functools.lru_cache(0) + @self.module.lru_cache(0) def f(): nonlocal f_cnt f_cnt += 1 @@ -971,7 +975,7 @@ self.assertEqual(currsize, 0) # test size one - @functools.lru_cache(1) + @self.module.lru_cache(1) def f(): nonlocal f_cnt f_cnt += 1 @@ -987,7 +991,7 @@ self.assertEqual(currsize, 1) # test size two - @functools.lru_cache(2) + @self.module.lru_cache(2) def f(x): nonlocal f_cnt f_cnt += 1 @@ -1004,7 +1008,7 @@ self.assertEqual(currsize, 2) def test_lru_with_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1012,17 +1016,26 @@ self.assertEqual([fib(n) for n in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_with_maxsize_negative(self): + @self.module.lru_cache(maxsize=-10) + def eq(n): + return n + for i in (0, 1): + self.assertEqual([eq(n) for n in range(150)], list(range(150))) + self.assertEqual(eq.cache_info(), + self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): - @functools.lru_cache(maxsize) + @self.module.lru_cache(maxsize) def func(i): return 'abc'[i] self.assertEqual(func(0), 'a') @@ -1035,7 +1048,7 @@ def test_lru_with_types(self): for maxsize in (None, 128): - @functools.lru_cache(maxsize=maxsize, typed=True) + @self.module.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x self.assertEqual(square(3), 9) @@ -1050,7 +1063,7 @@ self.assertEqual(square.cache_info().misses, 4) def test_lru_with_keyword_args(self): - @functools.lru_cache() + @self.module.lru_cache() def fib(n): if n < 2: return n @@ -1060,13 +1073,13 @@ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] ) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) def test_lru_with_keyword_args_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1074,15 +1087,71 @@ self.assertEqual([fib(n=number) for number in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_cache_decoration(self): + def f(zomg: 'zomg_annotation'): + """f doc string""" + return 42 + g = self.module.lru_cache()(f) + for attr in self.module.WRAPPER_ASSIGNMENTS: + self.assertEqual(getattr(g, attr), getattr(f, attr)) + + @unittest.skipUnless(threading, 'This test requires threading.') + def test_lru_cache_threaded(self): + def orig(x, y): + return 3 * x + y + f = self.module.lru_cache(maxsize=20)(orig) + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(currsize, 0) + + def full(f, *args): + for _ in range(10): + f(*args) + + def clear(f): + for _ in range(10): + f.cache_clear() + + orig_si = sys.getswitchinterval() + sys.setswitchinterval(1e-6) + try: + # create 5 threads in order to fill cache + threads = [] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(hits, 45) + self.assertEqual(misses, 5) + self.assertEqual(currsize, 5) + + # create 5 threads in order to fill cache and 1 to clear it + cleaner = threading.Thread(target=clear, args=[f]) + cleaner.start() + threads = [cleaner] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + finally: + sys.setswitchinterval(orig_si) def test_need_for_rlock(self): # This will deadlock on an LRU cache that uses a regular lock - @functools.lru_cache(maxsize=10) + @self.module.lru_cache(maxsize=10) def test_func(x): 'Used to demonstrate a reentrant lru_cache call within a single thread' return x @@ -1110,6 +1179,12 @@ def f(): pass +class TestLRUC(TestLRU, unittest.TestCase): + module = c_functools + +class TestLRUPy(TestLRU, unittest.TestCase): + module = py_functools + class TestSingleDispatch(unittest.TestCase): def test_simple_overloads(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -65,6 +65,9 @@ Library ------- +- Issue #14373: Added C implementation of functools.lru_cache(). Based on + patches by Matt Joiner and Alexey Kachayev. + - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -590,6 +590,539 @@ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); +/* lru_cache object **********************************************************/ + +/* this object is used delimit args and keywords in the cache keys */ +static PyObject *kwd_mark = NULL; + +struct lru_list_elem; +struct lru_cache_object; + +typedef struct lru_list_elem { + PyObject_HEAD + struct lru_list_elem *prev, *next; /* borrowed links */ + PyObject *key, *result; +} lru_list_elem; + +static void +lru_list_elem_dealloc(lru_list_elem *link) +{ + _PyObject_GC_UNTRACK(link); + Py_XDECREF(link->key); + Py_XDECREF(link->result); + PyObject_GC_Del(link); +} + +static int +lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg) +{ + Py_VISIT(link->key); + Py_VISIT(link->result); + return 0; +} + +static int +lru_list_elem_clear(lru_list_elem *link) +{ + Py_CLEAR(link->key); + Py_CLEAR(link->result); + return 0; +} + +static PyTypeObject lru_list_elem_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "functools._lru_list_elem", /* tp_name */ + sizeof(lru_list_elem), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_list_elem_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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)lru_list_elem_traverse, /* tp_traverse */ + (inquiry)lru_list_elem_clear, /* tp_clear */ +}; + + +typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); + +typedef struct lru_cache_object { + lru_list_elem root; /* includes PyObject_HEAD */ + Py_ssize_t maxsize; + PyObject *maxsize_O; + PyObject *func; + lru_cache_ternaryfunc wrapper; + PyObject *cache; + PyObject *cache_info_type; + Py_ssize_t misses, hits; + int typed; + PyObject *dict; + int full; +} lru_cache_object; + +static PyTypeObject lru_cache_type; + +static PyObject * +lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) +{ + PyObject *key, *sorted_items; + Py_ssize_t key_size, pos, key_pos; + + /* short path, key will match args anyway, which is a tuple */ + if (!typed && !kwds) { + Py_INCREF(args); + return args; + } + + if (kwds && PyDict_Size(kwds) > 0) { + sorted_items = PyDict_Items(kwds); + if (!sorted_items) + return NULL; + if (PyList_Sort(sorted_items) < 0) { + Py_DECREF(sorted_items); + return NULL; + } + } else + sorted_items = NULL; + + key_size = PyTuple_GET_SIZE(args); + if (sorted_items) + key_size += PyList_GET_SIZE(sorted_items); + if (typed) + key_size *= 2; + if (sorted_items) + key_size++; + + key = PyTuple_New(key_size); + if (key == NULL) + goto done; + + key_pos = 0; + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = PyTuple_GET_ITEM(args, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + Py_INCREF(kwd_mark); + PyTuple_SET_ITEM(key, key_pos++, kwd_mark); + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *item = PyList_GET_ITEM(sorted_items, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + if (typed) { + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + } + assert(key_pos == key_size); + +done: + if (sorted_items) + Py_DECREF(sorted_items); + return key; +} + +static PyObject * +uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result = PyObject_Call(self->func, args, kwds); + if (!result) + return NULL; + self->misses++; + return result; +} + +static PyObject * +infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result; + PyObject *key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + result = PyDict_GetItemWithError(self->cache, key); + if (result) { + Py_INCREF(result); + self->hits++; + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (PyDict_SetItem(self->cache, key, result) < 0) { + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + Py_DECREF(key); + self->misses++; + return result; +} + +static void +lru_cache_extricate_link(lru_list_elem *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static void +lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) +{ + lru_list_elem *root = &self->root; + lru_list_elem *last = root->prev; + last->next = root->prev = link; + link->prev = last; + link->next = root; +} + +static PyObject * +bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + lru_list_elem *link; + PyObject *key, *result; + + key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); + if (link) { + lru_cache_extricate_link(link); + lru_cache_append_link(self, link); + self->hits++; + result = link->result; + Py_INCREF(result); + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (self->full && self->root.next != &self->root) { + /* Use the oldest item to store the new key and result. */ + PyObject *oldkey, *oldresult; + /* Extricate the oldest item. */ + link = self->root.next; + lru_cache_extricate_link(link); + /* Remove it from the cache. + The cache dict holds one reference to the link, + and the linked list holds yet one reference to it. */ + if (PyDict_DelItem(self->cache, link->key) < 0) { + lru_cache_append_link(self, link); + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + /* Keep a reference to the old key and old result to + prevent their ref counts from going to zero during the + update. That will prevent potentially arbitrary object + clean-up code (i.e. __del__) from running while we're + still adjusting the links. */ + oldkey = link->key; + oldresult = link->result; + + link->key = key; + link->result = result; + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + Py_DECREF(oldkey); + Py_DECREF(oldresult); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + Py_DECREF(oldkey); + Py_DECREF(oldresult); + } else { + /* Put result in a new link at the front of the queue. */ + link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, + &lru_list_elem_type); + if (link == NULL) { + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + + link->key = key; + link->result = result; + _PyObject_GC_TRACK(link); + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + self->full = (PyDict_Size(self->cache) >= self->maxsize); + } + self->misses++; + return result; +} + +static PyObject * +lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) +{ + PyObject *func, *maxsize_O, *cache_info_type; + int typed; + lru_cache_object *obj; + Py_ssize_t maxsize; + PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); + static char *keywords[] = {"user_function", "maxsize", "typed", + "cache_info_type", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, + &func, &maxsize_O, &typed, + &cache_info_type)) { + return NULL; + } + + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "the first argument must be callable"); + return NULL; + } + + /* select the caching function, and make/inc maxsize_O */ + if (maxsize_O == Py_None) { + wrapper = infinite_lru_cache_wrapper; + /* use this only to initialize lru_cache_object attribute maxsize */ + maxsize = -1; + } else if (PyIndex_Check(maxsize_O)) { + maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); + if (maxsize == -1 && PyErr_Occurred()) + return NULL; + if (maxsize == 0) + wrapper = uncached_lru_cache_wrapper; + else + wrapper = bounded_lru_cache_wrapper; + } else { + PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); + return NULL; + } + + obj = (lru_cache_object *)type->tp_alloc(type, 0); + if (obj == NULL) + return NULL; + + if (!(obj->cache = PyDict_New())) { + Py_DECREF(obj); + return NULL; + } + + obj->root.prev = &obj->root; + obj->root.next = &obj->root; + obj->maxsize = maxsize; + Py_INCREF(maxsize_O); + obj->maxsize_O = maxsize_O; + Py_INCREF(func); + obj->func = func; + obj->wrapper = wrapper; + obj->misses = obj->hits = 0; + obj->typed = typed; + Py_INCREF(cache_info_type); + obj->cache_info_type = cache_info_type; + + return (PyObject *)obj; +} + +static lru_list_elem * +lru_cache_unlink_list(lru_cache_object *self) +{ + lru_list_elem *root = &self->root; + lru_list_elem *link = root->next; + if (link == root) + return NULL; + root->prev->next = NULL; + root->next = root->prev = root; + return link; +} + +static void +lru_cache_clear_list(lru_list_elem *link) +{ + while (link != NULL) { + lru_list_elem *next = link->next; + Py_DECREF(link); + link = next; + } +} + +static void +lru_cache_dealloc(lru_cache_object *obj) +{ + lru_list_elem *list = lru_cache_unlink_list(obj); + Py_XDECREF(obj->maxsize_O); + Py_XDECREF(obj->func); + Py_XDECREF(obj->cache); + Py_XDECREF(obj->dict); + Py_XDECREF(obj->cache_info_type); + lru_cache_clear_list(list); + Py_TYPE(obj)->tp_free(obj); +} + +static PyObject * +lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + return self->wrapper(self, args, kwds); +} + +static PyObject * +lru_cache_cache_info(lru_cache_object *self, PyObject *unused) +{ + return PyObject_CallFunction(self->cache_info_type, "nnOn", + self->hits, self->misses, self->maxsize_O, + PyDict_Size(self->cache)); +} + +static PyObject * +lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + self->hits = self->misses = 0; + self->full = 0; + PyDict_Clear(self->cache); + lru_cache_clear_list(list); + Py_RETURN_NONE; +} + +static int +lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) +{ + lru_list_elem *link = self->root.next; + while (link != &self->root) { + lru_list_elem *next = link->next; + Py_VISIT(link); + link = next; + } + Py_VISIT(self->maxsize_O); + Py_VISIT(self->func); + Py_VISIT(self->cache); + Py_VISIT(self->cache_info_type); + Py_VISIT(self->dict); + return 0; +} + +static int +lru_cache_tp_clear(lru_cache_object *self) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + Py_CLEAR(self->maxsize_O); + Py_CLEAR(self->func); + Py_CLEAR(self->cache); + Py_CLEAR(self->cache_info_type); + Py_CLEAR(self->dict); + lru_cache_clear_list(list); + return 0; +} + + +PyDoc_STRVAR(lru_cache_doc, +"Create a cached callable that wraps another function.\n\ +\n\ +user_function: the function being cached\n\ +\n\ +maxsize: 0 for no caching\n\ + None for unlimited cache size\n\ + n for a bounded cache\n\ +\n\ +typed: False cache f(3) and f(3.0) as identical calls\n\ + True cache f(3) and f(3.0) as distinct calls\n\ +\n\ +cache_info_type: namedtuple class with the fields:\n\ + hits misses currsize maxsize\n" +); + +static PyMethodDef lru_cache_methods[] = { + {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, + {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, + {NULL} +}; + +static PyGetSetDef lru_cache_getsetlist[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + +static PyTypeObject lru_cache_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "functools._lru_cache_wrapper", /* tp_name */ + sizeof(lru_cache_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_cache_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 */ + (ternaryfunc)lru_cache_call, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + lru_cache_doc, /* tp_doc */ + (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ + (inquiry)lru_cache_tp_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lru_cache_methods, /* tp_methods */ + 0, /* tp_members */ + lru_cache_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(lru_cache_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + lru_cache_new, /* tp_new */ +}; + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -602,6 +1135,11 @@ {NULL, NULL} /* sentinel */ }; +static void +module_free(void *m) +{ + Py_CLEAR(kwd_mark); +} static struct PyModuleDef _functoolsmodule = { PyModuleDef_HEAD_INIT, @@ -612,7 +1150,7 @@ NULL, NULL, NULL, - NULL + module_free, }; PyMODINIT_FUNC @@ -623,6 +1161,7 @@ char *name; PyTypeObject *typelist[] = { &partial_type, + &lru_cache_type, NULL }; @@ -630,6 +1169,12 @@ if (m == NULL) return NULL; + kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL); + if (!kwd_mark) { + Py_DECREF(m); + return NULL; + } + for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) { Py_DECREF(m); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:58 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Version_bump_for_3=2E5=2E0?= =?utf-8?b?YjEu?= Message-ID: <20150524234358.16723.56783@psf.io> https://hg.python.org/cpython/rev/071fefbb5e3d changeset: 96275:071fefbb5e3d tag: v3.5.0b1 user: Larry Hastings date: Sat May 23 17:43:05 2015 -0700 summary: Version bump for 3.5.0b1. files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- README | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 4 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.5.0a4+" +#define PY_VERSION "3.5.0b1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.5.0a4" +__version__ = "3.5.0b1" #--end constants-- diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.5.0 alpha 4 -==================================== +This is Python version 3.5.0 beta 1 +=================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:58 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_SOURCE=5FURI_to_ref?= =?utf-8?q?lect_that_we=27re_branching_3=2E5_now=2E?= Message-ID: <20150524234358.16287.48876@psf.io> https://hg.python.org/cpython/rev/c7faf8ee3c2c changeset: 96274:c7faf8ee3c2c user: Larry Hastings date: Sat May 23 17:41:13 2015 -0700 summary: Update SOURCE_URI to reflect that we're branching 3.5 now. files: Doc/tools/extensions/pyspecific.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -34,7 +34,7 @@ ISSUE_URI = 'https://bugs.python.org/issue%s' -SOURCE_URI = 'https://hg.python.org/cpython/file/default/%s' +SOURCE_URI = 'https://hg.python.org/cpython/file/3.5/%s' # monkey-patch reST parser to disable alphabetic and roman enumerated lists from docutils.parsers.rst.states import Body -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:58 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_tag_v3=2E5=2E0b1_for?= =?utf-8?q?_changeset_071fefbb5e3d?= Message-ID: <20150524234358.126968.34866@psf.io> https://hg.python.org/cpython/rev/72eccc7c98e6 changeset: 96276:72eccc7c98e6 user: Larry Hastings date: Sat May 23 17:43:19 2015 -0700 summary: Added tag v3.5.0b1 for changeset 071fefbb5e3d files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -148,3 +148,4 @@ 0337bd7ebcb6559d69679bc7025059ad1ce4f432 v3.5.0a2 82656e28b5e5c4ae48d8dd8b5f0d7968908a82b6 v3.5.0a3 413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 +071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:58 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Post-release_fixes_for_3?= =?utf-8?b?LjUuMGIxLg==?= Message-ID: <20150524234358.17935.3862@psf.io> https://hg.python.org/cpython/rev/8c70691e51cf changeset: 96277:8c70691e51cf user: Larry Hastings date: Sun May 24 16:40:45 2015 -0700 summary: Post-release fixes for 3.5.0b1. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.5.0b1" +#define PY_VERSION "3.5.0b1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 beta 2? +================================== + +Release date: 2015-07-05 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 1? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:59 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogQ3JlYXRlIDMuNSBi?= =?utf-8?q?ranch=2E?= Message-ID: <20150524234359.17931.18029@psf.io> https://hg.python.org/cpython/rev/78986c99dd6c changeset: 96279:78986c99dd6c branch: 3.5 user: Larry Hastings date: Sun May 24 16:42:42 2015 -0700 summary: Create 3.5 branch. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:59 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <20150524234359.45383.3484@psf.io> https://hg.python.org/cpython/rev/0d0989359bbb changeset: 96278:0d0989359bbb parent: 96277:8c70691e51cf parent: 96272:cb30db9cc029 user: Larry Hastings date: Sun May 24 16:41:42 2015 -0700 summary: Merge. files: Lib/functools.py | 203 ++-- Lib/test/test_functools.py | 109 ++- Misc/NEWS | 5 + Modules/_functoolsmodule.c | 547 +++++++++++- Objects/descrobject.c | 25 +- PCbuild/_testmultiphase.vcxproj | 80 + PCbuild/_testmultiphase.vcxproj.filters | 22 + PCbuild/pcbuild.proj | 2 +- PCbuild/pcbuild.sln | 16 + Tools/msi/make_zip.proj | 1 + Tools/msi/make_zip.py | 1 + Tools/msi/test/test_files.wxs | 12 + 12 files changed, 903 insertions(+), 120 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -419,120 +419,129 @@ if maxsize is not None and not isinstance(maxsize, int): raise TypeError('Expected maxsize to be an integer or None') + def decorating_function(user_function): + wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) + return update_wrapper(wrapper, user_function) + + return decorating_function + +def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): # Constants shared by all lru cache instances: sentinel = object() # unique object used to signal cache misses make_key = _make_key # build a key from the function arguments PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - def decorating_function(user_function): - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self - if maxsize == 0: + if maxsize == 0: - def wrapper(*args, **kwds): - # No caching -- just a statistics update after a successful call - nonlocal misses - result = user_function(*args, **kwds) - misses += 1 + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result + + elif maxsize is None: + + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: + hits += 1 return result + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result - elif maxsize is None: + else: - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root hits += 1 return result - result = user_function(*args, **kwds) - cache[key] = result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + full = (len(cache) >= maxsize) misses += 1 - return result + return result - else: + def cache_info(): + """Report cache statistics""" + with lock: + return _CacheInfo(hits, misses, maxsize, len(cache)) - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - hits += 1 - return result - result = user_function(*args, **kwds) - with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - full = (len(cache) >= maxsize) - misses += 1 - return result + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, len(cache)) + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return update_wrapper(wrapper, user_function) - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False - - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return update_wrapper(wrapper, user_function) - - return decorating_function +try: + from _functools import _lru_cache_wrapper +except ImportError: + pass ################################################################################ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -7,6 +7,10 @@ from test import support import unittest from weakref import proxy +try: + import threading +except ImportError: + threading = None import functools @@ -912,12 +916,12 @@ return self.value == other.value -class TestLRU(unittest.TestCase): +class TestLRU: def test_lru(self): def orig(x, y): return 3 * x + y - f = functools.lru_cache(maxsize=20)(orig) + f = self.module.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) self.assertEqual(currsize, 0) @@ -955,7 +959,7 @@ self.assertEqual(currsize, 1) # test size zero (which means "never-cache") - @functools.lru_cache(0) + @self.module.lru_cache(0) def f(): nonlocal f_cnt f_cnt += 1 @@ -971,7 +975,7 @@ self.assertEqual(currsize, 0) # test size one - @functools.lru_cache(1) + @self.module.lru_cache(1) def f(): nonlocal f_cnt f_cnt += 1 @@ -987,7 +991,7 @@ self.assertEqual(currsize, 1) # test size two - @functools.lru_cache(2) + @self.module.lru_cache(2) def f(x): nonlocal f_cnt f_cnt += 1 @@ -1004,7 +1008,7 @@ self.assertEqual(currsize, 2) def test_lru_with_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1012,17 +1016,26 @@ self.assertEqual([fib(n) for n in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_with_maxsize_negative(self): + @self.module.lru_cache(maxsize=-10) + def eq(n): + return n + for i in (0, 1): + self.assertEqual([eq(n) for n in range(150)], list(range(150))) + self.assertEqual(eq.cache_info(), + self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): - @functools.lru_cache(maxsize) + @self.module.lru_cache(maxsize) def func(i): return 'abc'[i] self.assertEqual(func(0), 'a') @@ -1035,7 +1048,7 @@ def test_lru_with_types(self): for maxsize in (None, 128): - @functools.lru_cache(maxsize=maxsize, typed=True) + @self.module.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x self.assertEqual(square(3), 9) @@ -1050,7 +1063,7 @@ self.assertEqual(square.cache_info().misses, 4) def test_lru_with_keyword_args(self): - @functools.lru_cache() + @self.module.lru_cache() def fib(n): if n < 2: return n @@ -1060,13 +1073,13 @@ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] ) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) def test_lru_with_keyword_args_maxsize_none(self): - @functools.lru_cache(maxsize=None) + @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n @@ -1074,15 +1087,71 @@ self.assertEqual([fib(n=number) for number in range(16)], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) fib.cache_clear() self.assertEqual(fib.cache_info(), - functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + + def test_lru_cache_decoration(self): + def f(zomg: 'zomg_annotation'): + """f doc string""" + return 42 + g = self.module.lru_cache()(f) + for attr in self.module.WRAPPER_ASSIGNMENTS: + self.assertEqual(getattr(g, attr), getattr(f, attr)) + + @unittest.skipUnless(threading, 'This test requires threading.') + def test_lru_cache_threaded(self): + def orig(x, y): + return 3 * x + y + f = self.module.lru_cache(maxsize=20)(orig) + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(currsize, 0) + + def full(f, *args): + for _ in range(10): + f(*args) + + def clear(f): + for _ in range(10): + f.cache_clear() + + orig_si = sys.getswitchinterval() + sys.setswitchinterval(1e-6) + try: + # create 5 threads in order to fill cache + threads = [] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + + hits, misses, maxsize, currsize = f.cache_info() + self.assertEqual(hits, 45) + self.assertEqual(misses, 5) + self.assertEqual(currsize, 5) + + # create 5 threads in order to fill cache and 1 to clear it + cleaner = threading.Thread(target=clear, args=[f]) + cleaner.start() + threads = [cleaner] + for k in range(5): + t = threading.Thread(target=full, args=[f, k, k]) + t.start() + threads.append(t) + + for t in threads: + t.join() + finally: + sys.setswitchinterval(orig_si) def test_need_for_rlock(self): # This will deadlock on an LRU cache that uses a regular lock - @functools.lru_cache(maxsize=10) + @self.module.lru_cache(maxsize=10) def test_func(x): 'Used to demonstrate a reentrant lru_cache call within a single thread' return x @@ -1110,6 +1179,12 @@ def f(): pass +class TestLRUC(TestLRU, unittest.TestCase): + module = c_functools + +class TestLRUPy(TestLRU, unittest.TestCase): + module = py_functools + class TestSingleDispatch(unittest.TestCase): def test_simple_overloads(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Core and Builtins ----------------- +- Issue #24276: Fixed optimization of property descriptor getter. + - Issue #24268: PEP 489: Multi-phase extension module initialization - Issue #23955: Add pyvenv.cfg option to suppress registry/environment @@ -75,6 +77,9 @@ Library ------- +- Issue #14373: Added C implementation of functools.lru_cache(). Based on + patches by Matt Joiner and Alexey Kachayev. + - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -590,6 +590,539 @@ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); +/* lru_cache object **********************************************************/ + +/* this object is used delimit args and keywords in the cache keys */ +static PyObject *kwd_mark = NULL; + +struct lru_list_elem; +struct lru_cache_object; + +typedef struct lru_list_elem { + PyObject_HEAD + struct lru_list_elem *prev, *next; /* borrowed links */ + PyObject *key, *result; +} lru_list_elem; + +static void +lru_list_elem_dealloc(lru_list_elem *link) +{ + _PyObject_GC_UNTRACK(link); + Py_XDECREF(link->key); + Py_XDECREF(link->result); + PyObject_GC_Del(link); +} + +static int +lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg) +{ + Py_VISIT(link->key); + Py_VISIT(link->result); + return 0; +} + +static int +lru_list_elem_clear(lru_list_elem *link) +{ + Py_CLEAR(link->key); + Py_CLEAR(link->result); + return 0; +} + +static PyTypeObject lru_list_elem_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "functools._lru_list_elem", /* tp_name */ + sizeof(lru_list_elem), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_list_elem_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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)lru_list_elem_traverse, /* tp_traverse */ + (inquiry)lru_list_elem_clear, /* tp_clear */ +}; + + +typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); + +typedef struct lru_cache_object { + lru_list_elem root; /* includes PyObject_HEAD */ + Py_ssize_t maxsize; + PyObject *maxsize_O; + PyObject *func; + lru_cache_ternaryfunc wrapper; + PyObject *cache; + PyObject *cache_info_type; + Py_ssize_t misses, hits; + int typed; + PyObject *dict; + int full; +} lru_cache_object; + +static PyTypeObject lru_cache_type; + +static PyObject * +lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) +{ + PyObject *key, *sorted_items; + Py_ssize_t key_size, pos, key_pos; + + /* short path, key will match args anyway, which is a tuple */ + if (!typed && !kwds) { + Py_INCREF(args); + return args; + } + + if (kwds && PyDict_Size(kwds) > 0) { + sorted_items = PyDict_Items(kwds); + if (!sorted_items) + return NULL; + if (PyList_Sort(sorted_items) < 0) { + Py_DECREF(sorted_items); + return NULL; + } + } else + sorted_items = NULL; + + key_size = PyTuple_GET_SIZE(args); + if (sorted_items) + key_size += PyList_GET_SIZE(sorted_items); + if (typed) + key_size *= 2; + if (sorted_items) + key_size++; + + key = PyTuple_New(key_size); + if (key == NULL) + goto done; + + key_pos = 0; + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = PyTuple_GET_ITEM(args, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + Py_INCREF(kwd_mark); + PyTuple_SET_ITEM(key, key_pos++, kwd_mark); + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *item = PyList_GET_ITEM(sorted_items, pos); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + if (typed) { + for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + if (sorted_items) { + for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { + PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); + PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); + Py_INCREF(item); + PyTuple_SET_ITEM(key, key_pos++, item); + } + } + } + assert(key_pos == key_size); + +done: + if (sorted_items) + Py_DECREF(sorted_items); + return key; +} + +static PyObject * +uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result = PyObject_Call(self->func, args, kwds); + if (!result) + return NULL; + self->misses++; + return result; +} + +static PyObject * +infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + PyObject *result; + PyObject *key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + result = PyDict_GetItemWithError(self->cache, key); + if (result) { + Py_INCREF(result); + self->hits++; + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (PyDict_SetItem(self->cache, key, result) < 0) { + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + Py_DECREF(key); + self->misses++; + return result; +} + +static void +lru_cache_extricate_link(lru_list_elem *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static void +lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) +{ + lru_list_elem *root = &self->root; + lru_list_elem *last = root->prev; + last->next = root->prev = link; + link->prev = last; + link->next = root; +} + +static PyObject * +bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + lru_list_elem *link; + PyObject *key, *result; + + key = lru_cache_make_key(args, kwds, self->typed); + if (!key) + return NULL; + link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); + if (link) { + lru_cache_extricate_link(link); + lru_cache_append_link(self, link); + self->hits++; + result = link->result; + Py_INCREF(result); + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } + result = PyObject_Call(self->func, args, kwds); + if (!result) { + Py_DECREF(key); + return NULL; + } + if (self->full && self->root.next != &self->root) { + /* Use the oldest item to store the new key and result. */ + PyObject *oldkey, *oldresult; + /* Extricate the oldest item. */ + link = self->root.next; + lru_cache_extricate_link(link); + /* Remove it from the cache. + The cache dict holds one reference to the link, + and the linked list holds yet one reference to it. */ + if (PyDict_DelItem(self->cache, link->key) < 0) { + lru_cache_append_link(self, link); + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + /* Keep a reference to the old key and old result to + prevent their ref counts from going to zero during the + update. That will prevent potentially arbitrary object + clean-up code (i.e. __del__) from running while we're + still adjusting the links. */ + oldkey = link->key; + oldresult = link->result; + + link->key = key; + link->result = result; + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + Py_DECREF(oldkey); + Py_DECREF(oldresult); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + Py_DECREF(oldkey); + Py_DECREF(oldresult); + } else { + /* Put result in a new link at the front of the queue. */ + link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, + &lru_list_elem_type); + if (link == NULL) { + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + + link->key = key; + link->result = result; + _PyObject_GC_TRACK(link); + if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { + Py_DECREF(link); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + self->full = (PyDict_Size(self->cache) >= self->maxsize); + } + self->misses++; + return result; +} + +static PyObject * +lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) +{ + PyObject *func, *maxsize_O, *cache_info_type; + int typed; + lru_cache_object *obj; + Py_ssize_t maxsize; + PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); + static char *keywords[] = {"user_function", "maxsize", "typed", + "cache_info_type", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, + &func, &maxsize_O, &typed, + &cache_info_type)) { + return NULL; + } + + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "the first argument must be callable"); + return NULL; + } + + /* select the caching function, and make/inc maxsize_O */ + if (maxsize_O == Py_None) { + wrapper = infinite_lru_cache_wrapper; + /* use this only to initialize lru_cache_object attribute maxsize */ + maxsize = -1; + } else if (PyIndex_Check(maxsize_O)) { + maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); + if (maxsize == -1 && PyErr_Occurred()) + return NULL; + if (maxsize == 0) + wrapper = uncached_lru_cache_wrapper; + else + wrapper = bounded_lru_cache_wrapper; + } else { + PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); + return NULL; + } + + obj = (lru_cache_object *)type->tp_alloc(type, 0); + if (obj == NULL) + return NULL; + + if (!(obj->cache = PyDict_New())) { + Py_DECREF(obj); + return NULL; + } + + obj->root.prev = &obj->root; + obj->root.next = &obj->root; + obj->maxsize = maxsize; + Py_INCREF(maxsize_O); + obj->maxsize_O = maxsize_O; + Py_INCREF(func); + obj->func = func; + obj->wrapper = wrapper; + obj->misses = obj->hits = 0; + obj->typed = typed; + Py_INCREF(cache_info_type); + obj->cache_info_type = cache_info_type; + + return (PyObject *)obj; +} + +static lru_list_elem * +lru_cache_unlink_list(lru_cache_object *self) +{ + lru_list_elem *root = &self->root; + lru_list_elem *link = root->next; + if (link == root) + return NULL; + root->prev->next = NULL; + root->next = root->prev = root; + return link; +} + +static void +lru_cache_clear_list(lru_list_elem *link) +{ + while (link != NULL) { + lru_list_elem *next = link->next; + Py_DECREF(link); + link = next; + } +} + +static void +lru_cache_dealloc(lru_cache_object *obj) +{ + lru_list_elem *list = lru_cache_unlink_list(obj); + Py_XDECREF(obj->maxsize_O); + Py_XDECREF(obj->func); + Py_XDECREF(obj->cache); + Py_XDECREF(obj->dict); + Py_XDECREF(obj->cache_info_type); + lru_cache_clear_list(list); + Py_TYPE(obj)->tp_free(obj); +} + +static PyObject * +lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) +{ + return self->wrapper(self, args, kwds); +} + +static PyObject * +lru_cache_cache_info(lru_cache_object *self, PyObject *unused) +{ + return PyObject_CallFunction(self->cache_info_type, "nnOn", + self->hits, self->misses, self->maxsize_O, + PyDict_Size(self->cache)); +} + +static PyObject * +lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + self->hits = self->misses = 0; + self->full = 0; + PyDict_Clear(self->cache); + lru_cache_clear_list(list); + Py_RETURN_NONE; +} + +static int +lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) +{ + lru_list_elem *link = self->root.next; + while (link != &self->root) { + lru_list_elem *next = link->next; + Py_VISIT(link); + link = next; + } + Py_VISIT(self->maxsize_O); + Py_VISIT(self->func); + Py_VISIT(self->cache); + Py_VISIT(self->cache_info_type); + Py_VISIT(self->dict); + return 0; +} + +static int +lru_cache_tp_clear(lru_cache_object *self) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + Py_CLEAR(self->maxsize_O); + Py_CLEAR(self->func); + Py_CLEAR(self->cache); + Py_CLEAR(self->cache_info_type); + Py_CLEAR(self->dict); + lru_cache_clear_list(list); + return 0; +} + + +PyDoc_STRVAR(lru_cache_doc, +"Create a cached callable that wraps another function.\n\ +\n\ +user_function: the function being cached\n\ +\n\ +maxsize: 0 for no caching\n\ + None for unlimited cache size\n\ + n for a bounded cache\n\ +\n\ +typed: False cache f(3) and f(3.0) as identical calls\n\ + True cache f(3) and f(3.0) as distinct calls\n\ +\n\ +cache_info_type: namedtuple class with the fields:\n\ + hits misses currsize maxsize\n" +); + +static PyMethodDef lru_cache_methods[] = { + {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, + {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, + {NULL} +}; + +static PyGetSetDef lru_cache_getsetlist[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + +static PyTypeObject lru_cache_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "functools._lru_cache_wrapper", /* tp_name */ + sizeof(lru_cache_object), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lru_cache_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 */ + (ternaryfunc)lru_cache_call, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + /* tp_flags */ + lru_cache_doc, /* tp_doc */ + (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ + (inquiry)lru_cache_tp_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lru_cache_methods, /* tp_methods */ + 0, /* tp_members */ + lru_cache_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(lru_cache_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + lru_cache_new, /* tp_new */ +}; + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -602,6 +1135,11 @@ {NULL, NULL} /* sentinel */ }; +static void +module_free(void *m) +{ + Py_CLEAR(kwd_mark); +} static struct PyModuleDef _functoolsmodule = { PyModuleDef_HEAD_INIT, @@ -612,7 +1150,7 @@ NULL, NULL, NULL, - NULL + module_free, }; PyMODINIT_FUNC @@ -623,6 +1161,7 @@ char *name; PyTypeObject *typelist[] = { &partial_type, + &lru_cache_type, NULL }; @@ -630,6 +1169,12 @@ if (m == NULL) return NULL; + kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL); + if (!kwd_mark) { + Py_DECREF(m); + return NULL; + } + for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) { Py_DECREF(m); diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1372,7 +1372,8 @@ static PyObject * property_descr_get(PyObject *self, PyObject *obj, PyObject *type) { - static PyObject *args = NULL; + static PyObject * volatile cached_args = NULL; + PyObject *args; PyObject *ret; propertyobject *gs = (propertyobject *)self; @@ -1384,12 +1385,28 @@ PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); return NULL; } - if (!args && !(args = PyTuple_New(1))) { - return NULL; + args = cached_args; + if (!args || Py_REFCNT(args) != 1) { + Py_CLEAR(cached_args); + if (!(cached_args = args = PyTuple_New(1))) + return NULL; } + Py_INCREF(args); + assert (Py_REFCNT(args) == 2); + Py_INCREF(obj); PyTuple_SET_ITEM(args, 0, obj); ret = PyObject_Call(gs->prop_get, args, NULL); - PyTuple_SET_ITEM(args, 0, NULL); + if (args == cached_args) { + if (Py_REFCNT(args) == 2) { + obj = PyTuple_GET_ITEM(args, 0); + PyTuple_SET_ITEM(args, 0, NULL); + Py_XDECREF(obj); + } + else { + Py_CLEAR(cached_args); + } + } + Py_DECREF(args); return ret; } diff --git a/PCbuild/_testmultiphase.vcxproj b/PCbuild/_testmultiphase.vcxproj new file mode 100644 --- /dev/null +++ b/PCbuild/_testmultiphase.vcxproj @@ -0,0 +1,80 @@ +? + + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + Win32 + + + Release + x64 + + + + {16BFE6F0-22EF-40B5-B831-7E937119EF10} + Win32Proj + _testmultiphase + false + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + + _CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + \ No newline at end of file diff --git a/PCbuild/_testmultiphase.vcxproj.filters b/PCbuild/_testmultiphase.vcxproj.filters new file mode 100644 --- /dev/null +++ b/PCbuild/_testmultiphase.vcxproj.filters @@ -0,0 +1,22 @@ +? + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -46,7 +46,7 @@ - + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -72,6 +72,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testembed", "_testembed.vcxproj", "{6DAC66D9-E703-4624-BE03-49112AB5AA62}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testmultiphase", "_testmultiphase.vcxproj", "{16BFE6F0-22EF-40B5-B831-7E937119EF10}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcl", "tcl.vcxproj", "{B5FD6F1D-129E-4BFF-9340-03606FAC7283}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tix", "tix.vcxproj", "{C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}" @@ -588,6 +590,20 @@ {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|Win32.Build.0 = Release|Win32 {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|x64.ActiveCfg = Release|x64 {6DAC66D9-E703-4624-BE03-49112AB5AA62}.Release|x64.Build.0 = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|Win32.ActiveCfg = Debug|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|Win32.Build.0 = Debug|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|x64.ActiveCfg = Debug|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Debug|x64.Build.0 = Debug|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGInstrument|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|Win32.Build.0 = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.PGUpdate|x64.Build.0 = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|Win32.ActiveCfg = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|Win32.Build.0 = Release|Win32 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.ActiveCfg = Release|x64 + {16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.Build.0 = Release|x64 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.ActiveCfg = Debug|Win32 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|Win32.Build.0 = Debug|Win32 {B5FD6F1D-129E-4BFF-9340-03606FAC7283}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj --- a/Tools/msi/make_zip.proj +++ b/Tools/msi/make_zip.proj @@ -4,6 +4,7 @@ {10487945-15D1-4092-A214-338395C4116B} python + false diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -25,6 +25,7 @@ '_testbuffer.pyd', '_testcapi.pyd', '_testimportmultiple.pyd', + '_testmultiphase.pyd', 'xxlimited.pyd', } diff --git a/Tools/msi/test/test_files.wxs b/Tools/msi/test/test_files.wxs --- a/Tools/msi/test/test_files.wxs +++ b/Tools/msi/test/test_files.wxs @@ -14,6 +14,9 @@ + + + @@ -31,6 +34,9 @@ + + + @@ -48,6 +54,9 @@ + + + @@ -60,6 +69,9 @@ + + + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 01:43:58 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 24 May 2015 23:43:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updated_topics_=28and_susp?= =?utf-8?q?-ignored=29_for_Python_3=2E5=2E0b1=2E?= Message-ID: <20150524234358.17933.46582@psf.io> https://hg.python.org/cpython/rev/b0b556c7c647 changeset: 96273:b0b556c7c647 parent: 96267:3dde95d1ddfb user: Larry Hastings date: Sat May 23 17:39:42 2015 -0700 summary: Updated topics (and susp-ignored) for Python 3.5.0b1. files: Doc/tools/susp-ignored.csv | 2 +- Lib/pydoc_data/topics.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -289,4 +289,4 @@ library/zipapp,31,:main,"$ python -m zipapp myapp -m ""myapp:main""" library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a" library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing" -library/stdtypes,3720,::,>>> m[::2].tolist() +library/stdtypes,3767,::,>>> m[::2].tolist() diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Apr 19 13:44:03 2015 +# Autogenerated by Sphinx on Sat May 23 17:38:41 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -17,9 +17,9 @@ 'break': u'\nThe "break" statement\n*********************\n\n break_stmt ::= "break"\n\n"break" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition within that\nloop.\n\nIt terminates the nearest enclosing loop, skipping the optional "else"\nclause if the loop has one.\n\nIf a "for" loop is terminated by "break", the loop control target\nkeeps its current value.\n\nWhen "break" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nloop.\n', 'callable-types': u'\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n', 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', - 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n', 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', - 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*.) "await" expressions, "async for" and "async\nwith" can only be used in their bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in coroutines.\n\nNew in version 3.5.\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nNew in version 3.5.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nNew in version 3.5.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', 'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works as follows:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string as a\nleft argument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', @@ -27,10 +27,10 @@ 'debugger': u'\n"pdb" --- The Python Debugger\n*****************************\n\n**Source code:** Lib/pdb.py\n\n======================================================================\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the "readline" module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the "p" command.\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: "pdb.py" now accepts a "-c" option that executes\ncommands as if given in a ".pdbrc" file, see *Debugger Commands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "continue" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type "continue", or you can\n step through the statement using "step" or "next" (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module "__main__" is used. (See the\n explanation of the built-in "exec()" or "eval()" functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When "runeval()" returns, it returns the\n value of the expression. Otherwise this function is similar to\n "run()".\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n "continue" command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n"h(elp)" means that either "h" or "help" can be used to enter the help\ncommand (but not "he" or "hel", nor "H" or "Help" or "HELP").\nArguments to commands must be separated by whitespace (spaces or\ntabs). Optional arguments are enclosed in square brackets ("[]") in\nthe command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n("|").\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a "list" command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint ("!"). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by ";;".\n(A single ";" is not used as it is the separator for multiple commands\nin a line that is passed to the Python parser.) No intelligence is\napplied to separating the commands; the input is split at the first\n";;" pair, even if it is in the middle of a quoted string.\n\nIf a file ".pdbrc" exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ".pdbrc" can now contain commands that\ncontinue debugging, such as "continue" or "next". Previously, these\ncommands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. "help pdb"\n displays the full documentation (the docstring of the "pdb"\n module). Since the *command* argument must be an identifier, "help\n exec" must be entered to get help on the "!" command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on "sys.path". Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for "break".\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just "end" to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) p some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with "end"; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between "next" and "step"\n is that "step" stops inside a called function, while "next"\n executes called functions at (nearly) full speed, only stopping at\n the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a "for" loop or out\n of a "finally" clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With "." as argument, list 11 lines around the current line. With\n one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by "->". If an\n exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ">>", if it differs\n from the current line.\n\n New in version 3.2: The ">>" marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for "list".\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\n Note: "print()" can also be used, but is not a debugger command\n --- this executes the Python "print()" function.\n\npp expression\n\n Like the "p" command, except the value of the expression is pretty-\n printed using the "pprint" module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the "code" module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by "%1", "%2", and so on, while "%*" is replaced by all\n the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ".pdbrc" file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n "global" statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with "shlex" and the result is used as the new\n "sys.argv". History, breakpoints, actions and debugger options are\n preserved. "restart" is an alias for "run".\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module\n is determined by the "__name__" in the frame globals.\n', 'del': u'\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', - 'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', 'else': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', 'exceptions': u'\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', - 'execmodel': u'\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'execmodel': u'\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', 'exprlists': u'\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n', 'floating': u'\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, "077e010" is legal, and denotes the same number\nas "77e10". The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n', 'for': u'\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', @@ -43,30 +43,30 @@ 'imaginary': u'\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules are\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause, loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is stored in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe wild card form of import --- "from module import *" --- is only\nallowed at the module level. Attempting to use it in class or\nfunction definitions will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine dynamically the modules to be loaded.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python where the feature\nbecomes standard.\n\nThe future statement is intended to ease migration to future versions\nof Python that introduce incompatible changes to the language. It\nallows use of the new features on a per-module basis before the\nrelease in which the feature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', 'in': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', - 'integers': u'\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0x100000000\n 79228162514264337593543950336 0xdeadbeef\n', + 'integers': u'\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0xdeadbeef\n', 'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) are used to create\nanonymous functions. The expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n', - 'naming': u'\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'naming': u'\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', 'nonlocal': u'\nThe "nonlocal" statement\n************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe "nonlocal" statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope excluding\nglobals. This is important because the default behavior for binding is\nto search the local namespace first. The statement allows\nencapsulated code to rebind variables outside of the local scope\nbesides the global (module) scope.\n\nNames listed in a "nonlocal" statement, unlike those listed in a\n"global" statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a "nonlocal" statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also: **PEP 3104** - Access to Names in Outer Scopes\n\n The specification for the "nonlocal" statement.\n', 'numbers': u'\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', 'numeric-types': u'\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n', 'objects': u'\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, "id(x)" is the memory\naddress where "x" is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The "type()" function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (so\nyou should always close files explicitly).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement and the \'"with"\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n', - 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedence in Python, from\nlowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for exponentiation, which\ngroups from right to left).\n\nNote that comparisons, membership tests, and identity tests, all have\nthe same precedence and have a left-to-right chaining feature as\ndescribed in the *Comparisons* section.\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "@", "/", "//", "%" | Multiplication, matrix multiplication |\n| | division, remainder [5] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0327\\u0043"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', + 'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedence in Python, from\nlowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for exponentiation, which\ngroups from right to left).\n\nNote that comparisons, membership tests, and identity tests, all have\nthe same precedence and have a left-to-right chaining feature as\ndescribed in the *Comparisons* section.\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "@", "/", "//", "%" | Multiplication, matrix multiplication |\n| | division, remainder [5] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "await" "x" | Await expression |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0327\\u0043"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', 'pass': u'\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', - 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n', + 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= await ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n', 'raise': u'\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "RuntimeError" exception is raised indicating\nthat this is an error.\n\nOtherwise, "raise" evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n"BaseException". If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the "__traceback__" attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the "with_traceback()" exception method (which returns\nthe same exception instance, with its traceback set to its argument),\nlike so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe "from" clause is used for exception chaining: if given, the second\n*expression* must be another exception class or instance, which will\nthen be attached to the raised exception as the "__cause__" attribute\n(which is writable). If the raised exception is not handled, both\nexceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler or a "finally" clause: the previous exception is\nthen attached as the new exception\'s "__context__" attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', 'return': u'\nThe "return" statement\n**********************\n\n return_stmt ::= "return" [expression_list]\n\n"return" may only occur syntactically nested in a function definition,\nnot within a nested class definition.\n\nIf an expression list is present, it is evaluated, else "None" is\nsubstituted.\n\n"return" leaves the current function call with the expression list (or\n"None") as return value.\n\nWhen "return" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nfunction.\n\nIn a generator function, the "return" statement indicates that the\ngenerator is done and will cause "StopIteration" to be raised. The\nreturned value (if any) is used as an argument to construct\n"StopIteration" and becomes the "StopIteration.value" attribute.\n', 'sequence-types': u'\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n', 'shifting': u'\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', 'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary is indexed\n(using the same "__getitem__()" method as normal subscription) with a\nkey that is constructed from the slice list, as follows. If the slice\nlist contains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n"start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n', 'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n', - 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', - 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', + 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__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\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n', + 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n The outermost leading and trailing *chars* argument values are\n stripped from the string. Characters are removed from the leading\n end until reaching a string character that is not contained in the\n set of characters in *chars*. A similar action takes place on the\n trailing end. For example:\n\n >>> comment_string = \'#....... Section 3.2.1 Issue #32 .......\'\n >>> comment_string.strip(\'.#! \')\n \'Section 3.2.1 Issue #32\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', 'strings': u'\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix string literals with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\nNew in version 3.3: The "\'rb\'" prefix of raw bytes literals has been\nadded as a synonym of "\'br\'".\n\nNew in version 3.3: Support for the unicode legacy literal\n("u\'value\'") was reintroduced to simplify the maintenance of dual\nPython 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted literals, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the literal. (A "quote" is the character used to open the\nliteral, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in string\nand bytes literals are interpreted according to rules similar to those\nused by Standard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the result*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw literal, quotes can be escaped with a backslash, but the\nbackslash remains in the result; for example, "r"\\""" is a valid\nstring literal consisting of two characters: a backslash and a double\nquote; "r"\\"" is not a valid string literal (even a raw string cannot\nend in an odd number of backslashes). Specifically, *a raw literal\ncannot end in a single backslash* (since the backslash would escape\nthe following quote character). Note also that a single backslash\nfollowed by a newline is interpreted as those two characters as part\nof the literal, *not* as a line continuation.\n', 'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription\n(lists or dictionaries for example). User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', 'try': u'\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods\n should return this value if they do not implement the operation for\n the operands provided. (The interpreter will then try the\n reflected operation, or some other fallback, depending on the\n operator.) Its truth value is true.\n\n See *Implementing the arithmetic operations* for more details.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode code\n points. All the code points in the range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "char"\n type; instead, every code point in the string is represented\n as a string object with length "1". The built-in function\n "ord()" converts a code point from its string form to an\n integer in the range "0 - 10FFFF"; "chr()" converts an\n integer in the range "0 - 10FFFF" to the corresponding length\n "1" string object. "str.encode()" can be used to convert a\n "str" to "bytes" using the given text encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable; not inherited by | |\n | | subclasses | |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value | |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | | contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | and "\'return\'" for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Frame objects support one method:\n\n frame.clear()\n\n This method clears all references to local variables held by\n the frame. Also, if the frame belonged to a generator, the\n generator is finalized. This helps break reference cycles\n involving frame objects (for example when catching an\n exception and storing its traceback for later use).\n\n "RuntimeError" is raised if the frame is currently executing.\n\n 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 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 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 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 the\n precise instruction. The line number and last instruction 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\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', + 'types': u'\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods\n should return this value if they do not implement the operation for\n the operands provided. (The interpreter will then try the\n reflected operation, or some other fallback, depending on the\n operator.) Its truth value is true.\n\n See *Implementing the arithmetic operations* for more details.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these are\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode code\n points. All the code points in the range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "char"\n type; instead, every code point in the string is represented\n as a string object with length "1". The built-in function\n "ord()" converts a code point from its string form to an\n integer in the range "0 - 10FFFF"; "chr()" converts an\n integer in the range "0 - 10FFFF" to the corresponding length\n "1" string object. "str.encode()" can be used to convert a\n "str" to "bytes" using the given text encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n | | string, or "None" if | |\n | | unavailable; not inherited by | |\n | | subclasses | |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n | | function was defined in, or | |\n | | "None" if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or "None" if no arguments have | |\n | | a default value | |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n | | contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | and "\'return\'" for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Coroutine functions\n A function or method which is defined using "async def" is\n called a *coroutine function*. Such a function, when called,\n returns a *coroutine* object. It may contain "await"\n expressions, as well as "async with" and "async for" statements.\n See also *Coroutines* section.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n https://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Frame objects support one method:\n\n frame.clear()\n\n This method clears all references to local variables held by\n the frame. Also, if the frame belonged to a generator, the\n generator is finalized. This helps break reference cycles\n involving frame objects (for example when catching an\n exception and storing its traceback for later use).\n\n "RuntimeError" is raised if the frame is currently executing.\n\n 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 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 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 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 the\n precise instruction. The line number and last instruction 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\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', 'typesfunctions': u'\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', 'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()" and *key*\n is not present, the "d[key]" operation calls that method with\n the key *key* as argument. The "d[key]" operation then returns\n or raises whatever is returned or raised by the\n "__missing__(key)" call. No other operations or methods invoke\n "__missing__()". If "__missing__()" is not defined, "KeyError"\n is raised. "__missing__()" must be a method; it cannot be an\n instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n The example above shows part of the implementation of\n "collections.Counter". A different "__missing__" method is used\n by "collections.defaultdict".\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', 'typesmethods': u'\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the "self"\nargument to the argument list. Bound methods have two special read-\nonly attributes: "m.__self__" is the object on which the method\noperates, and "m.__func__" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)".\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.__func__"), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an "AttributeError" being raised. In\norder to set a method attribute, you need to explicitly set it on the\nunderlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon May 25 10:52:38 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 25 May 2015 08:52:38 +0000 Subject: [Python-checkins] Daily reference leaks (0d0989359bbb): sum=226 Message-ID: <20150525085238.17929.54125@psf.io> results for 0d0989359bbb on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog1TfRZX', '--timeout', '7200'] From python-checkins at python.org Mon May 25 11:34:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 25 May 2015 09:34:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Remove_UTF-8_B?= =?utf-8?q?OMs=2E?= Message-ID: <20150525093406.16703.40057@psf.io> https://hg.python.org/cpython/rev/ab6c4e462977 changeset: 96281:ab6c4e462977 branch: 2.7 parent: 96254:1c4e89d1ae90 user: Serhiy Storchaka date: Mon May 25 12:27:39 2015 +0300 summary: Remove UTF-8 BOMs. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -?+++++++++++ ++++++++++++ Python News +++++++++++ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 11:34:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 25 May 2015 09:34:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Remove_UTF-8_B?= =?utf-8?q?OMs=2E?= Message-ID: <20150525093406.96180.11622@psf.io> https://hg.python.org/cpython/rev/a1bb4b18e3b5 changeset: 96280:a1bb4b18e3b5 branch: 3.4 parent: 96263:161d08bd1605 user: Serhiy Storchaka date: Mon May 25 12:27:39 2015 +0300 summary: Remove UTF-8 BOMs. files: Doc/tutorial/introduction.rst | 2 +- Misc/NEWS | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -1,4 +1,4 @@ -?.. _tut-informal: +.. _tut-informal: ********************************** An Informal Introduction to Python diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -?+++++++++++ ++++++++++++ Python News +++++++++++ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 11:34:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 25 May 2015 09:34:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Remove_UTF-8_BOMs=2E?= Message-ID: <20150525093406.45385.28383@psf.io> https://hg.python.org/cpython/rev/26a9d1fd78fc changeset: 96282:26a9d1fd78fc branch: 3.5 parent: 96279:78986c99dd6c parent: 96280:a1bb4b18e3b5 user: Serhiy Storchaka date: Mon May 25 12:29:53 2015 +0300 summary: Remove UTF-8 BOMs. files: Doc/tutorial/introduction.rst | 2 +- Misc/NEWS | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -1,4 +1,4 @@ -?.. _tut-informal: +.. _tut-informal: ********************************** An Informal Introduction to Python diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -?+++++++++++ ++++++++++++ Python News +++++++++++ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 11:34:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 25 May 2015 09:34:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Remove_UTF-8_BOMs=2E?= Message-ID: <20150525093406.126972.76760@psf.io> https://hg.python.org/cpython/rev/7255af1a1c50 changeset: 96283:7255af1a1c50 parent: 96278:0d0989359bbb parent: 96282:26a9d1fd78fc user: Serhiy Storchaka date: Mon May 25 12:32:20 2015 +0300 summary: Remove UTF-8 BOMs. files: Doc/tutorial/introduction.rst | 2 +- Misc/NEWS | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -1,4 +1,4 @@ -?.. _tut-informal: +.. _tut-informal: ********************************** An Informal Introduction to Python diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -?+++++++++++ ++++++++++++ Python News +++++++++++ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon May 25 15:56:42 2015 From: python-checkins at python.org (chris.angelico) Date: Mon, 25 May 2015 13:56:42 +0000 Subject: [Python-checkins] =?utf-8?q?test=3A_Provide_a_sequel_hook=2E=2E?= =?utf-8?q?=2E_okay=2C_just_testing_Mercurial_and_CPython_on_the?= Message-ID: <20150525135642.21236.99690@psf.io> https://hg.python.org/test/rev/3ff2ec2a6532 changeset: 223:3ff2ec2a6532 user: Chris Angelico date: Mon May 25 23:56:35 2015 +1000 summary: Provide a sequel hook... okay, just testing Mercurial and CPython on the reinstall files: Lenalede | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lenalede b/Lenalede --- a/Lenalede +++ b/Lenalede @@ -13,3 +13,4 @@ Originally from Camembert Canyon Campaign. +Stay tuned for more thrilling heroics from Soyutlanma, the isolated kingdom! -- Repository URL: https://hg.python.org/test From python-checkins at python.org Mon May 25 22:05:54 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 25 May 2015 20:05:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_a_section_for_news_i?= =?utf-8?q?tems_for_3=2E6=2E?= Message-ID: <20150525200553.27935.87124@psf.io> https://hg.python.org/cpython/rev/cf7e905ef5dd changeset: 96284:cf7e905ef5dd user: Larry Hastings date: Mon May 25 13:05:48 2015 -0700 summary: Added a section for news items for 3.6. files: Misc/NEWS | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.6.0 alpha 1? +=================================== + +Release date: XXXX-XX-XX + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 2? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 00:37:03 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 25 May 2015 22:37:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_480=3A_retarget_to_Python?= =?utf-8?q?_3=2E6?= Message-ID: <20150525223703.21256.48887@psf.io> https://hg.python.org/peps/rev/811ed3686956 changeset: 5878:811ed3686956 user: Victor Stinner date: Tue May 26 00:36:58 2015 +0200 summary: PEP 480: retarget to Python 3.6 files: pep-0490.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0490.txt b/pep-0490.txt --- a/pep-0490.txt +++ b/pep-0490.txt @@ -7,7 +7,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 25-March-2015 -Python-Version: 3.5 +Python-Version: 3.6 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 26 00:49:31 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 25 May 2015 22:49:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODQw?= =?utf-8?q?=3A_tokenize=2Eopen=28=29_now_closes_the_temporary_binary_file_?= =?utf-8?q?on_error_to?= Message-ID: <20150525224931.126980.95819@psf.io> https://hg.python.org/cpython/rev/623e07ea43df changeset: 96285:623e07ea43df branch: 3.4 parent: 96280:a1bb4b18e3b5 user: Victor Stinner date: Tue May 26 00:43:58 2015 +0200 summary: Issue #23840: tokenize.open() now closes the temporary binary file on error to fix a resource warning. files: Lib/test/test_tokenize.py | 10 +++++++++- Lib/tokenize.py | 14 +++++++++----- Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -646,7 +646,7 @@ STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, open as tokenize_open, Untokenizer) from io import BytesIO -from unittest import TestCase +from unittest import TestCase, mock import os, sys, glob import token @@ -1058,6 +1058,14 @@ ins = Bunk(lines, path) detect_encoding(ins.readline) + def test_open_error(self): + # Issue #23840: open() must close the binary file on error + m = BytesIO(b'#coding:xxx') + with mock.patch('tokenize._builtin_open', return_value=m): + self.assertRaises(SyntaxError, tokenize_open, 'foobar') + self.assertTrue(m.closed) + + class TestTokenize(TestCase): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -435,11 +435,15 @@ detect_encoding(). """ buffer = _builtin_open(filename, 'rb') - encoding, lines = detect_encoding(buffer.readline) - buffer.seek(0) - text = TextIOWrapper(buffer, encoding, line_buffering=True) - text.mode = 'r' - return text + try: + encoding, lines = detect_encoding(buffer.readline) + buffer.seek(0) + text = TextIOWrapper(buffer, encoding, line_buffering=True) + text.mode = 'r' + return text + except: + buffer.close() + raise def tokenize(readline): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -59,6 +59,9 @@ Library ------- +- Issue #23840: tokenize.open() now closes the temporary binary file on error + to fix a resource warning. + - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 00:49:32 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 25 May 2015 22:49:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_=28Merge_3=2E5=29_Issue_=2323840=3A_tokenize=2Eopen=28=29_now_?= =?utf-8?q?closes_the_temporary_binary_file?= Message-ID: <20150525224931.27937.18902@psf.io> https://hg.python.org/cpython/rev/a640d268ba97 changeset: 96286:a640d268ba97 branch: 3.5 parent: 96282:26a9d1fd78fc parent: 96285:623e07ea43df user: Victor Stinner date: Tue May 26 00:46:44 2015 +0200 summary: (Merge 3.5) Issue #23840: tokenize.open() now closes the temporary binary file on error to fix a resource warning. files: Lib/test/test_tokenize.py | 10 +++++++++- Lib/tokenize.py | 14 +++++++++----- Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -834,7 +834,7 @@ STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, open as tokenize_open, Untokenizer) from io import BytesIO -from unittest import TestCase +from unittest import TestCase, mock import os, sys, glob import token @@ -1246,6 +1246,14 @@ ins = Bunk(lines, path) detect_encoding(ins.readline) + def test_open_error(self): + # Issue #23840: open() must close the binary file on error + m = BytesIO(b'#coding:xxx') + with mock.patch('tokenize._builtin_open', return_value=m): + self.assertRaises(SyntaxError, tokenize_open, 'foobar') + self.assertTrue(m.closed) + + class TestTokenize(TestCase): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -435,11 +435,15 @@ detect_encoding(). """ buffer = _builtin_open(filename, 'rb') - encoding, lines = detect_encoding(buffer.readline) - buffer.seek(0) - text = TextIOWrapper(buffer, encoding, line_buffering=True) - text.mode = 'r' - return text + try: + encoding, lines = detect_encoding(buffer.readline) + buffer.seek(0) + text = TextIOWrapper(buffer, encoding, line_buffering=True) + text.mode = 'r' + return text + except: + buffer.close() + raise def tokenize(readline): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -323,6 +323,9 @@ Library ------- +- Issue #23840: tokenize.open() now closes the temporary binary file on error + to fix a resource warning. + - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 00:49:32 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 25 May 2015 22:49:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogKE1lcmdlIDMuNikgSXNzdWUgIzIzODQwOiB0b2tlbml6ZS5vcGVuKCkg?= =?utf-8?q?now_closes_the_temporary_binary_file?= Message-ID: <20150525224931.96188.52166@psf.io> https://hg.python.org/cpython/rev/c5cfd6353b4b changeset: 96287:c5cfd6353b4b parent: 96284:cf7e905ef5dd parent: 96286:a640d268ba97 user: Victor Stinner date: Tue May 26 00:49:14 2015 +0200 summary: (Merge 3.6) Issue #23840: tokenize.open() now closes the temporary binary file on error to fix a resource warning. files: Lib/test/test_tokenize.py | 10 +++++++++- Lib/tokenize.py | 14 +++++++++----- Misc/NEWS | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -834,7 +834,7 @@ STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, open as tokenize_open, Untokenizer) from io import BytesIO -from unittest import TestCase +from unittest import TestCase, mock import os, sys, glob import token @@ -1246,6 +1246,14 @@ ins = Bunk(lines, path) detect_encoding(ins.readline) + def test_open_error(self): + # Issue #23840: open() must close the binary file on error + m = BytesIO(b'#coding:xxx') + with mock.patch('tokenize._builtin_open', return_value=m): + self.assertRaises(SyntaxError, tokenize_open, 'foobar') + self.assertTrue(m.closed) + + class TestTokenize(TestCase): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -435,11 +435,15 @@ detect_encoding(). """ buffer = _builtin_open(filename, 'rb') - encoding, lines = detect_encoding(buffer.readline) - buffer.seek(0) - text = TextIOWrapper(buffer, encoding, line_buffering=True) - text.mode = 'r' - return text + try: + encoding, lines = detect_encoding(buffer.readline) + buffer.seek(0) + text = TextIOWrapper(buffer, encoding, line_buffering=True) + text.mode = 'r' + return text + except: + buffer.close() + raise def tokenize(readline): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -335,6 +335,9 @@ Library ------- +- Issue #23840: tokenize.open() now closes the temporary binary file on error + to fix a resource warning. + - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 01:49:20 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 25 May 2015 23:49:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Version_bump_for_trunk_to_?= =?utf-8?q?3=2E6=2E0a0=2E__Welcome_to_the_future!?= Message-ID: <20150525234920.17931.70766@psf.io> https://hg.python.org/cpython/rev/10d6ae57d071 changeset: 96288:10d6ae57d071 user: Larry Hastings date: Mon May 25 16:49:01 2015 -0700 summary: Version bump for trunk to 3.6.0a0. Welcome to the future! files: Include/patchlevel.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -17,13 +17,13 @@ /* Version parsed out into numeric values */ /*--start constants--*/ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 5 +#define PY_MINOR_VERSION 6 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.5.0b1+" +#define PY_VERSION "3.6.0a0" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:28:57 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:28:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150526022857.16697.22269@psf.io> https://hg.python.org/cpython/rev/9e2a191b243d changeset: 96292:9e2a191b243d branch: 3.5 parent: 96286:a640d268ba97 parent: 96291:3ccfd62e4da8 user: Benjamin Peterson date: Mon May 25 21:25:09 2015 -0500 summary: merge 3.4 files: Lib/distutils/__init__.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,10 +8,6 @@ setup (...) """ -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "3.5.0b1" -#--end constants-- +import sys + +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:28:57 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:28:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3?= Message-ID: <20150526022857.16285.8401@psf.io> https://hg.python.org/cpython/rev/3ccfd62e4da8 changeset: 96291:3ccfd62e4da8 branch: 3.4 parent: 96285:623e07ea43df parent: 96290:c361e38f6576 user: Benjamin Peterson date: Mon May 25 21:24:48 2015 -0500 summary: merge 3.3 files: Lib/distutils/__init__.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,10 +8,6 @@ setup (...) """ -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "3.4.3" -#--end constants-- +import sys + +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:28:57 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:28:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_keep_distutils?= =?utf-8?q?_version_in_sync_with_python_version_automatically?= Message-ID: <20150526022857.96180.8964@psf.io> https://hg.python.org/cpython/rev/0cb037bb0f9a changeset: 96289:0cb037bb0f9a branch: 3.2 parent: 96230:710cdba13323 user: Benjamin Peterson date: Mon May 25 21:24:00 2015 -0500 summary: keep distutils version in sync with python version automatically files: Lib/distutils/__init__.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,10 +8,6 @@ setup (...) """ -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "3.2.6" -#--end constants-- +import sys + +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:28:57 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:28:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_merge_3=2E2?= Message-ID: <20150526022857.26094.18980@psf.io> https://hg.python.org/cpython/rev/c361e38f6576 changeset: 96290:c361e38f6576 branch: 3.3 parent: 96231:c7b3a50a2f01 parent: 96289:0cb037bb0f9a user: Benjamin Peterson date: Mon May 25 21:24:26 2015 -0500 summary: merge 3.2 files: Lib/distutils/__init__.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,10 +8,6 @@ setup (...) """ -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "3.3.6" -#--end constants-- +import sys + +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:29:02 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:29:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_keep_distutils?= =?utf-8?q?_version_in_sync_with_python_version_automatically?= Message-ID: <20150526022902.17935.43660@psf.io> https://hg.python.org/cpython/rev/245c5f5e515c changeset: 96294:245c5f5e515c branch: 2.7 parent: 96281:ab6c4e462977 user: Benjamin Peterson date: Mon May 25 21:24:00 2015 -0500 summary: keep distutils version in sync with python version automatically files: Lib/distutils/__init__.py | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,12 +8,6 @@ setup (...) """ -__revision__ = "$Id$" +import sys -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "2.7.10" -#--end constants-- +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:29:03 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:29:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150526022902.27939.37052@psf.io> https://hg.python.org/cpython/rev/f16ae8ec5553 changeset: 96293:f16ae8ec5553 parent: 96288:10d6ae57d071 parent: 96292:9e2a191b243d user: Benjamin Peterson date: Mon May 25 21:25:27 2015 -0500 summary: Merge 3.5 files: Lib/distutils/__init__.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -8,10 +8,6 @@ setup (...) """ -# Distutils version -# -# Updated automatically by the Python release process. -# -#--start constants-- -__version__ = "3.5.0b1" -#--end constants-- +import sys + +__version__ = sys.version[:sys.version.index(' ')] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 04:29:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 26 May 2015 02:29:28 +0000 Subject: [Python-checkins] =?utf-8?q?release=3A_stop_updating_distutils_ve?= =?utf-8?q?rsion?= Message-ID: <20150526022927.96204.54047@psf.io> https://hg.python.org/release/rev/ef78c3131416 changeset: 96:ef78c3131416 user: Benjamin Peterson date: Mon May 25 21:29:19 2015 -0500 summary: stop updating distutils version files: release.py | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) diff --git a/release.py b/release.py --- a/release.py +++ b/release.py @@ -138,11 +138,6 @@ tweak_patchlevel(tag) - print('Updating Lib/distutils/__init__.py...', end=' ') - new = '__version__ = "%s"' % tag.text - constant_replace('Lib/distutils/__init__.py', new, '#', '') - print('done') - extra_work = False other_files = ['README', 'Misc/NEWS'] if tag.patch == 0 and tag.level == "a" and tag.serial == 0: -- Repository URL: https://hg.python.org/release From tjreedy at udel.edu Tue May 26 06:26:14 2015 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 26 May 2015 00:26:14 -0400 Subject: [Python-checkins] cpython (3.4): Issue #23840: tokenize.open() now closes the temporary binary file on error to In-Reply-To: <20150525224931.126980.95819@psf.io> References: <20150525224931.126980.95819@psf.io> Message-ID: <5563F5E6.3080705@udel.edu> On 5/25/2015 6:49 PM, victor.stinner wrote: > https://hg.python.org/cpython/rev/623e07ea43df > changeset: 96285:623e07ea43df > branch: 3.4 > parent: 96280:a1bb4b18e3b5 > user: Victor Stinner > date: Tue May 26 00:43:58 2015 +0200 > summary: > Issue #23840: tokenize.open() now closes the temporary binary file on error to > fix a resource warning. > > files: > Lib/test/test_tokenize.py | 10 +++++++++- > Lib/tokenize.py | 14 +++++++++----- > Misc/NEWS | 3 +++ > 3 files changed, 21 insertions(+), 6 deletions(-) > > > diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py > --- a/Lib/test/test_tokenize.py > +++ b/Lib/test/test_tokenize.py > @@ -646,7 +646,7 @@ > STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, > open as tokenize_open, Untokenizer) > from io import BytesIO > -from unittest import TestCase > +from unittest import TestCase, mock > import os, sys, glob > import token > > @@ -1058,6 +1058,14 @@ > ins = Bunk(lines, path) > detect_encoding(ins.readline) > > + def test_open_error(self): > + # Issue #23840: open() must close the binary file on error > + m = BytesIO(b'#coding:xxx') > + with mock.patch('tokenize._builtin_open', return_value=m): > + self.assertRaises(SyntaxError, tokenize_open, 'foobar') > + self.assertTrue(m.closed) > + > + > > class TestTokenize(TestCase): > > diff --git a/Lib/tokenize.py b/Lib/tokenize.py > --- a/Lib/tokenize.py > +++ b/Lib/tokenize.py > @@ -435,11 +435,15 @@ > detect_encoding(). > """ > buffer = _builtin_open(filename, 'rb') > - encoding, lines = detect_encoding(buffer.readline) > - buffer.seek(0) > - text = TextIOWrapper(buffer, encoding, line_buffering=True) > - text.mode = 'r' > - return text > + try: > + encoding, lines = detect_encoding(buffer.readline) > + buffer.seek(0) > + text = TextIOWrapper(buffer, encoding, line_buffering=True) > + text.mode = 'r' > + return text > + except: > + buffer.close() > + raise Please do not add bare 'except:'. If you mean 'except BaseException:', say so. tjr From victor.stinner at gmail.com Tue May 26 08:20:01 2015 From: victor.stinner at gmail.com (Victor Stinner) Date: Tue, 26 May 2015 08:20:01 +0200 Subject: [Python-checkins] [Python-Dev] cpython (3.4): Issue #23840: tokenize.open() now closes the temporary binary file on error to In-Reply-To: <556405BA.3090201@gmail.com> References: <20150525224931.126980.95819@psf.io> <5563F5E6.3080705@udel.edu> <556405BA.3090201@gmail.com> Message-ID: What is wrong with "except:" in this specific case? Victor Le mardi 26 mai 2015, Yury Selivanov a ?crit : > > > On 2015-05-26 12:26 AM, Terry Reedy wrote: > >> + try: >>> + encoding, lines = detect_encoding(buffer.readline) >>> + buffer.seek(0) >>> + text = TextIOWrapper(buffer, encoding, line_buffering=True) >>> + text.mode = 'r' >>> + return text >>> + except: >>> + buffer.close() >>> + raise >>> >> >> Please do not add bare 'except:'. If you mean 'except BaseException:', >> say so. >> > > try..finally would be even better. > > Yury > _______________________________________________ > Python-Dev mailing list > Python-Dev at python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/victor.stinner%40gmail.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: From yselivanov.ml at gmail.com Tue May 26 07:33:46 2015 From: yselivanov.ml at gmail.com (Yury Selivanov) Date: Tue, 26 May 2015 01:33:46 -0400 Subject: [Python-checkins] cpython (3.4): Issue #23840: tokenize.open() now closes the temporary binary file on error to In-Reply-To: <5563F5E6.3080705@udel.edu> References: <20150525224931.126980.95819@psf.io> <5563F5E6.3080705@udel.edu> Message-ID: <556405BA.3090201@gmail.com> On 2015-05-26 12:26 AM, Terry Reedy wrote: >> + try: >> + encoding, lines = detect_encoding(buffer.readline) >> + buffer.seek(0) >> + text = TextIOWrapper(buffer, encoding, line_buffering=True) >> + text.mode = 'r' >> + return text >> + except: >> + buffer.close() >> + raise > > Please do not add bare 'except:'. If you mean 'except > BaseException:', say so. try..finally would be even better. Yury From python-checkins at python.org Tue May 26 09:28:01 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 26 May 2015 07:28:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Moved_Misc/NEW?= =?utf-8?q?S_entries_to_correct_section_and_fix_formatting=2E?= Message-ID: <20150526072800.96192.4553@psf.io> https://hg.python.org/cpython/rev/5a9901c21213 changeset: 96296:5a9901c21213 branch: 3.4 parent: 96291:3ccfd62e4da8 user: Serhiy Storchaka date: Tue May 26 10:20:32 2015 +0300 summary: Moved Misc/NEWS entries to correct section and fix formatting. files: Misc/NEWS | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,9 +21,6 @@ - Issue #24102: Fixed exception type checking in standard error handlers. -- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three - METH_VARARGS methods on _sqlite.Connection. - - Issue #23757: PySequence_Tuple() incorrectly called the concrete list API when the data was a list subclass. @@ -85,6 +82,9 @@ - Issue #22931: Allow '[' and ']' in cookie values. +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #24094: Fix possible crash in json.encode with poorly behaved dict subclasses. @@ -271,7 +271,7 @@ - asyncio: async() function is deprecated in favour of ensure_future(). -- Issue 23898: Fix inspect.classify_class_attrs() to support attributes +- Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. IDLE @@ -2437,7 +2437,7 @@ - Issue #19782: imaplib now supports SSLContext.check_hostname and server name indication for TLS/SSL connections. -- Issue 20123: Fix pydoc.synopsis() for "binary" modules. +- Issue #20123: Fix pydoc.synopsis() for "binary" modules. - Issue #19834: Support unpickling of exceptions pickled by Python 2. @@ -5703,7 +5703,7 @@ - Issue #15940: Specify effect of locale on time functions. -- Issue 17538: Document XML vulnerabilties +- Issue #17538: Document XML vulnerabilties - Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte @@ -9707,7 +9707,7 @@ - Issue #13218: Fix test_ssl failures on Debian/Ubuntu. - Re-enable lib2to3's test_parser.py tests, though with an expected failure - (see issue 13125). + (see issue #13125). - Issue #12656: Add tests for IPv6 and Unix sockets to test_asyncore. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 09:28:01 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 26 May 2015 07:28:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Moved_Misc/NEWS_entries_to_correct_section_and_fix_forma?= =?utf-8?q?tting=2E?= Message-ID: <20150526072800.26124.60548@psf.io> https://hg.python.org/cpython/rev/3ac1a8bb7563 changeset: 96298:3ac1a8bb7563 parent: 96293:f16ae8ec5553 parent: 96297:2f59747dba6c user: Serhiy Storchaka date: Tue May 26 10:26:53 2015 +0300 summary: Moved Misc/NEWS entries to correct section and fix formatting. files: Misc/NEWS | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,12 +57,6 @@ - Issue #23290: Optimize set_merge() for cases where the target is empty. (Contributed by Serhiy Storchaka.) -- Issue #20274: When calling a _sqlite.Connection, it now complains if passed - any keyword arguments. Previously it silently ignored them. - -- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three - METH_VARARGS methods on _sqlite.Connection. - - Issue #2292: PEP 448: Additional Unpacking Generalizations. - Issue #24096: Make warnings.warn_explicit more robust against mutation of the @@ -187,6 +181,12 @@ (utf8/internationalized email) and automatically encodes non-ASCII usernames and passwords to UTF8. +- Issue #20274: When calling a _sqlite.Connection, it now complains if passed + any keyword arguments. Previously it silently ignored them. + +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks now emits a deprecation warning when callable is None or keyword arguments except msg is passed in the context manager mode. @@ -3527,7 +3527,7 @@ - Issue #19782: imaplib now supports SSLContext.check_hostname and server name indication for TLS/SSL connections. -- Issue 20123: Fix pydoc.synopsis() for "binary" modules. +- Issue #20123: Fix pydoc.synopsis() for "binary" modules. - Issue #19834: Support unpickling of exceptions pickled by Python 2. @@ -6797,7 +6797,7 @@ - Issue #15940: Specify effect of locale on time functions. -- Issue 17538: Document XML vulnerabilties +- Issue #17538: Document XML vulnerabilties - Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 09:28:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 26 May 2015 07:28:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Moved_Misc/NEWS_entries_to_correct_section_and_fix_formatting?= =?utf-8?q?=2E?= Message-ID: <20150526072800.16301.12430@psf.io> https://hg.python.org/cpython/rev/2f59747dba6c changeset: 96297:2f59747dba6c branch: 3.5 parent: 96292:9e2a191b243d parent: 96296:5a9901c21213 user: Serhiy Storchaka date: Tue May 26 10:25:48 2015 +0300 summary: Moved Misc/NEWS entries to correct section and fix formatting. files: Misc/NEWS | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,12 +45,6 @@ - Issue #23290: Optimize set_merge() for cases where the target is empty. (Contributed by Serhiy Storchaka.) -- Issue #20274: When calling a _sqlite.Connection, it now complains if passed - any keyword arguments. Previously it silently ignored them. - -- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three - METH_VARARGS methods on _sqlite.Connection. - - Issue #2292: PEP 448: Additional Unpacking Generalizations. - Issue #24096: Make warnings.warn_explicit more robust against mutation of the @@ -175,6 +169,12 @@ (utf8/internationalized email) and automatically encodes non-ASCII usernames and passwords to UTF8. +- Issue #20274: When calling a _sqlite.Connection, it now complains if passed + any keyword arguments. Previously it silently ignored them. + +- Issue #20274: Remove ignored and erroneous "kwargs" parameters from three + METH_VARARGS methods on _sqlite.Connection. + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and assertWarnsRegex() checks now emits a deprecation warning when callable is None or keyword arguments except msg is passed in the context manager mode. @@ -3515,7 +3515,7 @@ - Issue #19782: imaplib now supports SSLContext.check_hostname and server name indication for TLS/SSL connections. -- Issue 20123: Fix pydoc.synopsis() for "binary" modules. +- Issue #20123: Fix pydoc.synopsis() for "binary" modules. - Issue #19834: Support unpickling of exceptions pickled by Python 2. @@ -6785,7 +6785,7 @@ - Issue #15940: Specify effect of locale on time functions. -- Issue 17538: Document XML vulnerabilties +- Issue #17538: Document XML vulnerabilties - Issue #16642: sched.scheduler timefunc initial default is time.monotonic. Patch by Ramchandra Apte -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 09:28:01 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 26 May 2015 07:28:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Moved_Misc/NEW?= =?utf-8?q?S_entries_to_correct_section_and_fix_formatting=2E?= Message-ID: <20150526072800.45363.36520@psf.io> https://hg.python.org/cpython/rev/e7a0ad6e4054 changeset: 96295:e7a0ad6e4054 branch: 2.7 user: Serhiy Storchaka date: Tue May 26 10:20:11 2015 +0300 summary: Moved Misc/NEWS entries to correct section and fix formatting. files: Misc/NEWS | 38 +++++++++++++++++++------------------- 1 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,7 +48,7 @@ - Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for decoding unicode literals. - + Documentation ------------- @@ -74,30 +74,30 @@ Core and Builtins ----------------- +- Issue #23971: Fix underestimated presizing in dict.fromkeys(). + +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API + when the data was a list subclass. + +- Issue #23629: Fix the default __sizeof__ implementation for variable-sized + objects. + +- Issue #23055: Fixed a buffer overflow in PyUnicode_FromFormatV. Analysis + and fix by Guido Vranken. + +- Issue #23048: Fix jumping out of an infinite while loop in the pdb. + +Library +------- + +- The keywords attribute of functools.partial is now always a dictionary. + - Issue #20274: When calling a _sqlite.Connection, it now complains if passed any keyword arguments. Previously it silently ignored them. -- Issue #23971: Fix underestimated presizing in dict.fromkeys(). - -- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API - when the data was a list subclass. - - Issue #20274: Remove ignored and erroneous "kwargs" parameters from three METH_VARARGS methods on _sqlite.Connection. -- Issue #23629: Fix the default __sizeof__ implementation for variable-sized - objects. - -- Issue #23055: Fixed a buffer overflow in PyUnicode_FromFormatV. Analysis - and fix by Guido Vranken. - -- Issue #23048: Fix jumping out of an infinite while loop in the pdb. - -Library -------- - -- The keywords attribute of functools.partial is now always a dictionary. - - Issue #24134: assertRaises() and assertRaisesRegexp() checks are not longer successful if the callable is None. -- Repository URL: https://hg.python.org/cpython From victor.stinner at gmail.com Tue May 26 09:54:49 2015 From: victor.stinner at gmail.com (Victor Stinner) Date: Tue, 26 May 2015 09:54:49 +0200 Subject: [Python-checkins] [Python-Dev] cpython (3.4): Issue #23840: tokenize.open() now closes the temporary binary file on error to In-Reply-To: References: <20150525224931.126980.95819@psf.io> <5563F5E6.3080705@udel.edu> <556405BA.3090201@gmail.com> Message-ID: 2015-05-26 8:44 GMT+02:00 Serhiy Storchaka : > No, finally is not correct there. buffer shouldn't be closed if no exception > is raised. Yep. The binary file must only be closed in case of error, as written in the commit message. > And this is one of the cases in which bare 'except:' is absolutely legal. The "except: ; raise" is common in the Python stdlib. Victor From python-checkins at python.org Tue May 26 10:36:22 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 26 May 2015 08:36:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Mjg2?= =?utf-8?q?=3A_Register_dict_views_with_the_MappingView_ABCs=2E?= Message-ID: <20150526083622.17945.83091@psf.io> https://hg.python.org/cpython/rev/9213c70c67d2 changeset: 96299:9213c70c67d2 branch: 2.7 parent: 96295:e7a0ad6e4054 user: Raymond Hettinger date: Tue May 26 01:35:54 2015 -0700 summary: Issue #24286: Register dict views with the MappingView ABCs. files: Lib/_abcoll.py | 3 +++ Lib/test/test_collections.py | 4 ++++ Lib/test/test_dictviews.py | 20 ++++++++++++++++++++ Misc/NEWS | 4 ++++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/Lib/_abcoll.py b/Lib/_abcoll.py --- a/Lib/_abcoll.py +++ b/Lib/_abcoll.py @@ -453,6 +453,7 @@ for key in self._mapping: yield key +KeysView.register(type({}.viewkeys())) class ItemsView(MappingView, Set): @@ -473,6 +474,7 @@ for key in self._mapping: yield (key, self._mapping[key]) +ItemsView.register(type({}.viewitems())) class ValuesView(MappingView): @@ -486,6 +488,7 @@ for key in self._mapping: yield self._mapping[key] +ValuesView.register(type({}.viewvalues())) class MutableMapping(Mapping): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1286,6 +1286,10 @@ self.assertEqual(list(od.viewvalues()), [None for k in s]) self.assertEqual(list(od.viewitems()), [(k, None) for k in s]) + # See http://bugs.python.org/issue24286 + self.assertEqual(od.viewkeys(), dict(od).viewkeys()) + self.assertEqual(od.viewitems(), dict(od).viewitems()) + def test_override_update(self): # Verify that subclasses can override update() without breaking __init__() class MyOD(OrderedDict): diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,4 +1,5 @@ import unittest +import collections from test import test_support class DictSetTest(unittest.TestCase): @@ -164,7 +165,26 @@ d[42] = d.viewvalues() self.assertRaises(RuntimeError, repr, d) + def test_abc_registry(self): + d = dict(a=1) + self.assertIsInstance(d.viewkeys(), collections.KeysView) + self.assertIsInstance(d.viewkeys(), collections.MappingView) + self.assertIsInstance(d.viewkeys(), collections.Set) + self.assertIsInstance(d.viewkeys(), collections.Sized) + self.assertIsInstance(d.viewkeys(), collections.Iterable) + self.assertIsInstance(d.viewkeys(), collections.Container) + + self.assertIsInstance(d.viewvalues(), collections.ValuesView) + self.assertIsInstance(d.viewvalues(), collections.MappingView) + self.assertIsInstance(d.viewvalues(), collections.Sized) + + self.assertIsInstance(d.viewitems(), collections.ItemsView) + self.assertIsInstance(d.viewitems(), collections.MappingView) + self.assertIsInstance(d.viewitems(), collections.Set) + self.assertIsInstance(d.viewitems(), collections.Sized) + self.assertIsInstance(d.viewitems(), collections.Iterable) + self.assertIsInstance(d.viewitems(), collections.Container) def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,10 @@ - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. +- Issue #24286: Dict view were not registered with the MappingView abstract + base classes. This caused key and item views in OrderedDict to not be equal + to their regular dict counterparts. + - Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again when a directory with the chosen name already exists on Windows as well as on Unix. tempfile.mkstemp() now fails early if parent directory is not -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 10:48:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 26 May 2015 08:48:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324286=3A__Forward?= =?utf-8?q?_port_dict_view_abstract_base_class_tests=2E?= Message-ID: <20150526084807.96200.76092@psf.io> https://hg.python.org/cpython/rev/ff8b603ee51e changeset: 96300:ff8b603ee51e parent: 96298:3ac1a8bb7563 user: Raymond Hettinger date: Tue May 26 01:47:58 2015 -0700 summary: Issue #24286: Forward port dict view abstract base class tests. files: Lib/test/test_collections.py | 7 +++++++ Lib/test/test_dictviews.py | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1867,6 +1867,13 @@ od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) + def test_views(self): + # See http://bugs.python.org/issue24286 + s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() + od = OrderedDict.fromkeys(s) + self.assertEqual(od.keys(), dict(od).keys()) + self.assertEqual(od.items(), dict(od).items()) + def test_override_update(self): # Verify that subclasses can override update() without breaking __init__() class MyOD(OrderedDict): diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,3 +1,4 @@ +import collections import unittest class DictSetTest(unittest.TestCase): @@ -197,6 +198,27 @@ d[42] = d.values() self.assertRaises(RuntimeError, repr, d) + def test_abc_registry(self): + d = dict(a=1) + + self.assertIsInstance(d.keys(), collections.KeysView) + self.assertIsInstance(d.keys(), collections.MappingView) + self.assertIsInstance(d.keys(), collections.Set) + self.assertIsInstance(d.keys(), collections.Sized) + self.assertIsInstance(d.keys(), collections.Iterable) + self.assertIsInstance(d.keys(), collections.Container) + + self.assertIsInstance(d.values(), collections.ValuesView) + self.assertIsInstance(d.values(), collections.MappingView) + self.assertIsInstance(d.values(), collections.Sized) + + self.assertIsInstance(d.items(), collections.ItemsView) + self.assertIsInstance(d.items(), collections.MappingView) + self.assertIsInstance(d.items(), collections.Set) + self.assertIsInstance(d.items(), collections.Sized) + self.assertIsInstance(d.items(), collections.Iterable) + self.assertIsInstance(d.items(), collections.Container) + if __name__ == "__main__": unittest.main() -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue May 26 10:54:04 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 26 May 2015 08:54:04 +0000 Subject: [Python-checkins] Daily reference leaks (f16ae8ec5553): sum=226 Message-ID: <20150526085404.96198.81946@psf.io> results for f16ae8ec5553 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogmONOvE', '--timeout', '7200'] From python-checkins at python.org Tue May 26 13:57:40 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 26 May 2015 11:57:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjg1?= =?utf-8?q?=3A_fix_importing_extensions_from_packages?= Message-ID: <20150526115740.21246.91936@psf.io> https://hg.python.org/cpython/rev/55e6f3f94b99 changeset: 96301:55e6f3f94b99 branch: 3.5 parent: 96297:2f59747dba6c user: Nick Coghlan date: Tue May 26 21:48:17 2015 +1000 summary: Issue #24285: fix importing extensions from packages files: Lib/test/test_importlib/extension/test_loader.py | 7 +++++++ Misc/NEWS | 6 +++++- Python/importdl.c | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -170,6 +170,13 @@ loader.exec_module(module) return module + def test_load_submodule(self): + '''Test loading a simulated submodule''' + module = self.load_module_by_name('pkg.' + self.name) + self.assertIsInstance(module, types.ModuleType) + self.assertEqual(module.__name__, 'pkg.' + self.name) + self.assertEqual(module.str_const, 'something different') + def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' module1 = self.load_module_by_name(self.name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24285: Fixed regression that prevented importing extension modules + from inside packages. Patch by Petr Viktorin. + Library ------- @@ -24,7 +27,8 @@ - Issue #24276: Fixed optimization of property descriptor getter. -- Issue #24268: PEP 489: Multi-phase extension module initialization +- Issue #24268: PEP 489: Multi-phase extension module initialization. + Patch by Petr Viktorin. - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -45,7 +45,7 @@ if (lastdot < -1) { return NULL; } else if (lastdot >= 0) { - tmp = PyUnicode_Substring(name, lastdot, name_len); + tmp = PyUnicode_Substring(name, lastdot + 1, name_len); if (tmp == NULL) return NULL; name = tmp; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 13:57:41 2015 From: python-checkins at python.org (nick.coghlan) Date: Tue, 26 May 2015 11:57:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_fix_for_issue_=2324285_from_3=2E5?= Message-ID: <20150526115740.96196.42348@psf.io> https://hg.python.org/cpython/rev/32ee7b9d58c9 changeset: 96302:32ee7b9d58c9 parent: 96300:ff8b603ee51e parent: 96301:55e6f3f94b99 user: Nick Coghlan date: Tue May 26 21:57:16 2015 +1000 summary: Merge fix for issue #24285 from 3.5 files: Lib/test/test_importlib/extension/test_loader.py | 7 +++++++ Misc/NEWS | 6 +++++- Python/importdl.c | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -170,6 +170,13 @@ loader.exec_module(module) return module + def test_load_submodule(self): + '''Test loading a simulated submodule''' + module = self.load_module_by_name('pkg.' + self.name) + self.assertIsInstance(module, types.ModuleType) + self.assertEqual(module.__name__, 'pkg.' + self.name) + self.assertEqual(module.str_const, 'something different') + def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' module1 = self.load_module_by_name(self.name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Core and Builtins ----------------- +- Issue #24285: Fixed regression that prevented importing extension modules + from inside packages. Patch by Petr Viktorin. + Library ------- @@ -36,7 +39,8 @@ - Issue #24276: Fixed optimization of property descriptor getter. -- Issue #24268: PEP 489: Multi-phase extension module initialization +- Issue #24268: PEP 489: Multi-phase extension module initialization. + Patch by Petr Viktorin. - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -45,7 +45,7 @@ if (lastdot < -1) { return NULL; } else if (lastdot >= 0) { - tmp = PyUnicode_Substring(name, lastdot, name_len); + tmp = PyUnicode_Substring(name, lastdot + 1, name_len); if (tmp == NULL) return NULL; name = tmp; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue May 26 16:05:57 2015 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 26 May 2015 14:05:57 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Typo_fix_=28thanks_Yuval_G=2E?= =?utf-8?b?KS4=?= Message-ID: <20150526140554.27955.88250@psf.io> https://hg.python.org/peps/rev/601ff038d2fc changeset: 5879:601ff038d2fc user: Guido van Rossum date: Tue May 26 07:05:50 2015 -0700 summary: Typo fix (thanks Yuval G.). files: pep-0484.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -1484,7 +1484,7 @@ class Node: """Binary tree node.""" - def __init__(self, left: Node, right: None): + def __init__(self, left: Node, right: Node): self.left = left self.right = right -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue May 26 19:35:23 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 26 May 2015 17:35:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323509=3A_Speed_up?= =?utf-8?q?_Counter_operators?= Message-ID: <20150526173522.21266.38272@psf.io> https://hg.python.org/cpython/rev/5780ee2c18e1 changeset: 96303:5780ee2c18e1 user: Raymond Hettinger date: Tue May 26 10:35:15 2015 -0700 summary: Issue #23509: Speed up Counter operators (Based on patch by Serhiy Storchaka.) files: Lib/collections/__init__.py | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -736,14 +736,22 @@ def __pos__(self): 'Adds an empty counter, effectively stripping negative and zero counts' - return self + Counter() + result = Counter() + for elem, count in self.items(): + if count > 0: + result[elem] = count + return result def __neg__(self): '''Subtracts from an empty counter. Strips positive and zero counts, and flips the sign on negative counts. ''' - return Counter() - self + result = Counter() + for elem, count in self.items(): + if count < 0: + result[elem] = 0 - count + return result def _keep_positive(self): '''Internal method to strip elements with a negative or zero count''' -- Repository URL: https://hg.python.org/cpython From rdmurray at bitdance.com Tue May 26 23:12:49 2015 From: rdmurray at bitdance.com (R. David Murray) Date: Tue, 26 May 2015 17:12:49 -0400 Subject: [Python-checkins] [Python-Dev] cpython (3.4): Issue #23840: tokenize.open() now closes the temporary binary file on error to In-Reply-To: References: <20150525224931.126980.95819@psf.io> <5563F5E6.3080705@udel.edu> <556405BA.3090201@gmail.com> Message-ID: <20150526211249.5C4E1250DE6@webabinitio.net> On Tue, 26 May 2015 08:20:01 +0200, Victor Stinner wrote: > What is wrong with "except:" in this specific case? Nothing is wrong with it from a technical standpoint. However, if we use 'except BaseException' that makes it clear that someone has thought about it and decided that all exceptions should be caught, as opposed to it being legacy code or a programming mistake. > > On 2015-05-26 12:26 AM, Terry Reedy wrote: > > > >>> + try: > >>> + encoding, lines = detect_encoding(buffer.readline) > >>> + buffer.seek(0) > >>> + text = TextIOWrapper(buffer, encoding, line_buffering=True) > >>> + text.mode = 'r' > >>> + return text > >>> + except: > >>> + buffer.close() > >>> + raise > >>> > >> > >> Please do not add bare 'except:'. If you mean 'except BaseException:', > >> say so. From python-checkins at python.org Wed May 27 04:40:40 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 02:40:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150527024040.79687.97506@psf.io> https://hg.python.org/cpython/rev/c8d66b13c2e7 changeset: 96305:c8d66b13c2e7 parent: 96303:5780ee2c18e1 parent: 96304:6d340bae6de1 user: Benjamin Peterson date: Tue May 26 21:40:35 2015 -0500 summary: Merge 3.5 files: Doc/whatsnew/3.5.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -253,13 +253,13 @@ --------------------------------- :pep:`488` does away with the concept of ``.pyo`` files. This means that -``.pyc`` files represent both unoptimized and optimized bytecode. To prevent -the need to constantly regenerate bytecode files, ``.pyc`` files now have an -optional ``opt-`` tag in their name when the bytecode is optimized. This has -the side-effect of no more bytecode file name clashes when running under either -``-O`` or ``-OO``, thus allowing unoptimized, ``-O``, and ``-OO`` bytecode files -to all exist simultaneously. :func:`importlib.util.cache_from_source` has an -updated API to help with this change. +``.pyc`` files represent both unoptimized and optimized bytecode. To prevent the +need to constantly regenerate bytecode files, ``.pyc`` files now have an +optional ``opt-`` tag in their name when the bytecode is optimized. This has the +side-effect of no more bytecode file name clashes when running under either +``-O`` or ``-OO``. Consequently, bytecode files generated from ``-O``, and +``-OO`` may now exist simultaneously. :func:`importlib.util.cache_from_source` +has an updated API to help with this change. .. seealso:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 04:40:39 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 02:40:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_rephrase?= Message-ID: <20150527024039.16459.3411@psf.io> https://hg.python.org/cpython/rev/6d340bae6de1 changeset: 96304:6d340bae6de1 branch: 3.5 parent: 96301:55e6f3f94b99 user: Benjamin Peterson date: Tue May 26 21:40:28 2015 -0500 summary: rephrase files: Doc/whatsnew/3.5.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -253,13 +253,13 @@ --------------------------------- :pep:`488` does away with the concept of ``.pyo`` files. This means that -``.pyc`` files represent both unoptimized and optimized bytecode. To prevent -the need to constantly regenerate bytecode files, ``.pyc`` files now have an -optional ``opt-`` tag in their name when the bytecode is optimized. This has -the side-effect of no more bytecode file name clashes when running under either -``-O`` or ``-OO``, thus allowing unoptimized, ``-O``, and ``-OO`` bytecode files -to all exist simultaneously. :func:`importlib.util.cache_from_source` has an -updated API to help with this change. +``.pyc`` files represent both unoptimized and optimized bytecode. To prevent the +need to constantly regenerate bytecode files, ``.pyc`` files now have an +optional ``opt-`` tag in their name when the bytecode is optimized. This has the +side-effect of no more bytecode file name clashes when running under either +``-O`` or ``-OO``. Consequently, bytecode files generated from ``-O``, and +``-OO`` may now exist simultaneously. :func:`importlib.util.cache_from_source` +has an updated API to help with this change. .. seealso:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 05:46:43 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 27 May 2015 03:46:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324293=3A_Fixes_installer_colors_to_use_system_s?= =?utf-8?q?ettings_throughout=2E?= Message-ID: <20150527034643.29845.87440@psf.io> https://hg.python.org/cpython/rev/37ed61b1234a changeset: 96307:37ed61b1234a parent: 96305:c8d66b13c2e7 parent: 96306:a77214dbf1f3 user: Steve Dower date: Tue May 26 20:46:29 2015 -0700 summary: Issue #24293: Fixes installer colors to use system settings throughout. files: Tools/msi/bundle/Default.thm | 16 +++++----- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 4 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -1,12 +1,12 @@ - #(loc.Caption) - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI #(loc.HelpHeader) @@ -74,7 +74,7 @@ #(loc.CustomLocationLabel) - #(loc.CustomLocationHelpLabel) + #(loc.CustomLocationHelpLabel) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -371,7 +371,7 @@ hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); - ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, checked ? SW_HIDE : SW_SHOW); + ThemeControlEnable(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked); ThemeGetTextControl(_theme, ID_TARGETDIR_EDITBOX, &targetDir); if (targetDir) { // Check the current value against the default to see @@ -1489,7 +1489,7 @@ wc.hInstance = _hModule; wc.hIcon = hIcon; wc.hCursor = ::LoadCursorW(nullptr, (LPCWSTR)IDC_ARROW); - wc.hbrBackground = _theme->rgFonts[_theme->dwFontId].hBackground; + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = nullptr; wc.lpszClassName = PYBA_WINDOW_CLASS; if (!::RegisterClassW(&wc)) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 05:46:43 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 27 May 2015 03:46:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjkz?= =?utf-8?q?=3A_Fixes_installer_colors_to_use_system_settings_throughout=2E?= Message-ID: <20150527034643.5079.10620@psf.io> https://hg.python.org/cpython/rev/a77214dbf1f3 changeset: 96306:a77214dbf1f3 branch: 3.5 parent: 96304:6d340bae6de1 user: Steve Dower date: Tue May 26 20:46:11 2015 -0700 summary: Issue #24293: Fixes installer colors to use system settings throughout. files: Tools/msi/bundle/Default.thm | 16 +++++----- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 4 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -1,12 +1,12 @@ - #(loc.Caption) - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI - Segoe UI + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI #(loc.HelpHeader) @@ -74,7 +74,7 @@ #(loc.CustomLocationLabel) - #(loc.CustomLocationHelpLabel) + #(loc.CustomLocationHelpLabel) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -371,7 +371,7 @@ hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); - ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, checked ? SW_HIDE : SW_SHOW); + ThemeControlEnable(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, !checked); ThemeGetTextControl(_theme, ID_TARGETDIR_EDITBOX, &targetDir); if (targetDir) { // Check the current value against the default to see @@ -1489,7 +1489,7 @@ wc.hInstance = _hModule; wc.hIcon = hIcon; wc.hCursor = ::LoadCursorW(nullptr, (LPCWSTR)IDC_ARROW); - wc.hbrBackground = _theme->rgFonts[_theme->dwFontId].hBackground; + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = nullptr; wc.lpszClassName = PYBA_WINDOW_CLASS; if (!::RegisterClassW(&wc)) { -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed May 27 11:09:34 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 27 May 2015 09:09:34 +0000 Subject: [Python-checkins] Daily reference leaks (37ed61b1234a): sum=226 Message-ID: <20150527090934.114208.55555@psf.io> results for 37ed61b1234a on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogUhEnQ8', '--timeout', '7200'] From python-checkins at python.org Wed May 27 13:08:50 2015 From: python-checkins at python.org (lars.gustaebel) Date: Wed, 27 May 2015 11:08:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogdGFyZmlsZS5vcGVu?= =?utf-8?q?=28=29_with_mode_=27x=27_created_files_without_an_end_of_archiv?= =?utf-8?q?e_marker=2E?= Message-ID: <20150527110849.29827.50899@psf.io> https://hg.python.org/cpython/rev/d91367e63ebd changeset: 96308:d91367e63ebd branch: 3.5 parent: 96306:a77214dbf1f3 user: Lars Gust?bel date: Wed May 27 12:53:44 2015 +0200 summary: tarfile.open() with mode 'x' created files without an end of archive marker. files: Lib/tarfile.py | 4 ++-- Lib/test/test_tarfile.py | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1484,7 +1484,7 @@ except HeaderError as e: raise ReadError(str(e)) - if self.mode in "aw": + if self.mode in ("a", "w", "x"): self._loaded = True if self.pax_headers: @@ -1716,7 +1716,7 @@ self.closed = True try: - if self.mode in "aw": + if self.mode in ("a", "w", "x"): self.fileobj.write(NUL * (BLOCKSIZE * 2)) self.offset += (BLOCKSIZE * 2) # fill up the end with zero-blocks diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -982,6 +982,19 @@ self.assertFalse(fobj.closed) self.assertEqual(data, fobj.getvalue()) + def test_eof_marker(self): + # Make sure an end of archive marker is written (two zero blocks). + # tarfile insists on aligning archives to a 20 * 512 byte recordsize. + # So, we create an archive that has exactly 10240 bytes without the + # marker, and has 20480 bytes once the marker is written. + with tarfile.open(tmpname, self.mode) as tar: + t = tarfile.TarInfo("foo") + t.size = tarfile.RECORDSIZE - tarfile.BLOCKSIZE + tar.addfile(t, io.BytesIO(b"a" * t.size)) + + with self.open(tmpname, "rb") as fobj: + self.assertEqual(len(fobj.read()), tarfile.RECORDSIZE * 2) + class WriteTest(WriteTestBase, unittest.TestCase): @@ -1431,7 +1444,7 @@ ("longlnk/" * 127) + "longlink_") -class CreateTest(TarTest, unittest.TestCase): +class CreateTest(WriteTestBase, unittest.TestCase): prefix = "x:" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 13:08:51 2015 From: python-checkins at python.org (lars.gustaebel) Date: Wed, 27 May 2015 11:08:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5=3A_tarfile=2Eopen=28=29_with_mode_=27x?= =?utf-8?q?=27_created_files_without_an_end_of?= Message-ID: <20150527110850.114230.18882@psf.io> https://hg.python.org/cpython/rev/268b16080501 changeset: 96309:268b16080501 parent: 96307:37ed61b1234a parent: 96308:d91367e63ebd user: Lars Gust?bel date: Wed May 27 13:05:30 2015 +0200 summary: Merge with 3.5: tarfile.open() with mode 'x' created files without an end of archive marker. files: Lib/tarfile.py | 4 ++-- Lib/test/test_tarfile.py | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1484,7 +1484,7 @@ except HeaderError as e: raise ReadError(str(e)) - if self.mode in "aw": + if self.mode in ("a", "w", "x"): self._loaded = True if self.pax_headers: @@ -1716,7 +1716,7 @@ self.closed = True try: - if self.mode in "aw": + if self.mode in ("a", "w", "x"): self.fileobj.write(NUL * (BLOCKSIZE * 2)) self.offset += (BLOCKSIZE * 2) # fill up the end with zero-blocks diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -982,6 +982,19 @@ self.assertFalse(fobj.closed) self.assertEqual(data, fobj.getvalue()) + def test_eof_marker(self): + # Make sure an end of archive marker is written (two zero blocks). + # tarfile insists on aligning archives to a 20 * 512 byte recordsize. + # So, we create an archive that has exactly 10240 bytes without the + # marker, and has 20480 bytes once the marker is written. + with tarfile.open(tmpname, self.mode) as tar: + t = tarfile.TarInfo("foo") + t.size = tarfile.RECORDSIZE - tarfile.BLOCKSIZE + tar.addfile(t, io.BytesIO(b"a" * t.size)) + + with self.open(tmpname, "rb") as fobj: + self.assertEqual(len(fobj.read()), tarfile.RECORDSIZE * 2) + class WriteTest(WriteTestBase, unittest.TestCase): @@ -1431,7 +1444,7 @@ ("longlnk/" * 127) + "longlink_") -class CreateTest(TarTest, unittest.TestCase): +class CreateTest(WriteTestBase, unittest.TestCase): prefix = "x:" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 17:10:12 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 27 May 2015 15:10:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24297=3A_Update_symbol=2Epy=2E_See_also_issue_2401?= =?utf-8?q?7=2E?= Message-ID: <20150527151011.5087.74898@psf.io> https://hg.python.org/cpython/rev/87509d71653b changeset: 96311:87509d71653b parent: 96309:268b16080501 parent: 96310:843fe7e831a8 user: Yury Selivanov date: Wed May 27 11:08:46 2015 -0400 summary: Issue 24297: Update symbol.py. See also issue 24017. files: Lib/symbol.py | 155 +++++++++++++++++++------------------ 1 files changed, 79 insertions(+), 76 deletions(-) diff --git a/Lib/symbol.py b/Lib/symbol.py --- a/Lib/symbol.py +++ b/Lib/symbol.py @@ -16,82 +16,85 @@ decorator = 259 decorators = 260 decorated = 261 -funcdef = 262 -parameters = 263 -typedargslist = 264 -tfpdef = 265 -varargslist = 266 -vfpdef = 267 -stmt = 268 -simple_stmt = 269 -small_stmt = 270 -expr_stmt = 271 -testlist_star_expr = 272 -augassign = 273 -del_stmt = 274 -pass_stmt = 275 -flow_stmt = 276 -break_stmt = 277 -continue_stmt = 278 -return_stmt = 279 -yield_stmt = 280 -raise_stmt = 281 -import_stmt = 282 -import_name = 283 -import_from = 284 -import_as_name = 285 -dotted_as_name = 286 -import_as_names = 287 -dotted_as_names = 288 -dotted_name = 289 -global_stmt = 290 -nonlocal_stmt = 291 -assert_stmt = 292 -compound_stmt = 293 -if_stmt = 294 -while_stmt = 295 -for_stmt = 296 -try_stmt = 297 -with_stmt = 298 -with_item = 299 -except_clause = 300 -suite = 301 -test = 302 -test_nocond = 303 -lambdef = 304 -lambdef_nocond = 305 -or_test = 306 -and_test = 307 -not_test = 308 -comparison = 309 -comp_op = 310 -star_expr = 311 -expr = 312 -xor_expr = 313 -and_expr = 314 -shift_expr = 315 -arith_expr = 316 -term = 317 -factor = 318 -power = 319 -atom = 320 -testlist_comp = 321 -trailer = 322 -subscriptlist = 323 -subscript = 324 -sliceop = 325 -exprlist = 326 -testlist = 327 -dictorsetmaker = 328 -classdef = 329 -arglist = 330 -argument = 331 -comp_iter = 332 -comp_for = 333 -comp_if = 334 -encoding_decl = 335 -yield_expr = 336 -yield_arg = 337 +async_funcdef = 262 +funcdef = 263 +parameters = 264 +typedargslist = 265 +tfpdef = 266 +varargslist = 267 +vfpdef = 268 +stmt = 269 +simple_stmt = 270 +small_stmt = 271 +expr_stmt = 272 +testlist_star_expr = 273 +augassign = 274 +del_stmt = 275 +pass_stmt = 276 +flow_stmt = 277 +break_stmt = 278 +continue_stmt = 279 +return_stmt = 280 +yield_stmt = 281 +raise_stmt = 282 +import_stmt = 283 +import_name = 284 +import_from = 285 +import_as_name = 286 +dotted_as_name = 287 +import_as_names = 288 +dotted_as_names = 289 +dotted_name = 290 +global_stmt = 291 +nonlocal_stmt = 292 +assert_stmt = 293 +compound_stmt = 294 +async_stmt = 295 +if_stmt = 296 +while_stmt = 297 +for_stmt = 298 +try_stmt = 299 +with_stmt = 300 +with_item = 301 +except_clause = 302 +suite = 303 +test = 304 +test_nocond = 305 +lambdef = 306 +lambdef_nocond = 307 +or_test = 308 +and_test = 309 +not_test = 310 +comparison = 311 +comp_op = 312 +star_expr = 313 +expr = 314 +xor_expr = 315 +and_expr = 316 +shift_expr = 317 +arith_expr = 318 +term = 319 +factor = 320 +power = 321 +atom_expr = 322 +atom = 323 +testlist_comp = 324 +trailer = 325 +subscriptlist = 326 +subscript = 327 +sliceop = 328 +exprlist = 329 +testlist = 330 +dictorsetmaker = 331 +classdef = 332 +arglist = 333 +argument = 334 +comp_iter = 335 +comp_for = 336 +comp_if = 337 +encoding_decl = 338 +yield_expr = 339 +yield_arg = 340 #--end constants-- sym_name = {} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 17:10:14 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 27 May 2015 15:10:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQyOTc6?= =?utf-8?q?_Update_symbol=2Epy=2E_See_also_issue_24017=2E?= Message-ID: <20150527151011.79705.88195@psf.io> https://hg.python.org/cpython/rev/843fe7e831a8 changeset: 96310:843fe7e831a8 branch: 3.5 parent: 96308:d91367e63ebd user: Yury Selivanov date: Wed May 27 11:08:19 2015 -0400 summary: Issue 24297: Update symbol.py. See also issue 24017. files: Lib/symbol.py | 155 +++++++++++++++++++------------------ 1 files changed, 79 insertions(+), 76 deletions(-) diff --git a/Lib/symbol.py b/Lib/symbol.py --- a/Lib/symbol.py +++ b/Lib/symbol.py @@ -16,82 +16,85 @@ decorator = 259 decorators = 260 decorated = 261 -funcdef = 262 -parameters = 263 -typedargslist = 264 -tfpdef = 265 -varargslist = 266 -vfpdef = 267 -stmt = 268 -simple_stmt = 269 -small_stmt = 270 -expr_stmt = 271 -testlist_star_expr = 272 -augassign = 273 -del_stmt = 274 -pass_stmt = 275 -flow_stmt = 276 -break_stmt = 277 -continue_stmt = 278 -return_stmt = 279 -yield_stmt = 280 -raise_stmt = 281 -import_stmt = 282 -import_name = 283 -import_from = 284 -import_as_name = 285 -dotted_as_name = 286 -import_as_names = 287 -dotted_as_names = 288 -dotted_name = 289 -global_stmt = 290 -nonlocal_stmt = 291 -assert_stmt = 292 -compound_stmt = 293 -if_stmt = 294 -while_stmt = 295 -for_stmt = 296 -try_stmt = 297 -with_stmt = 298 -with_item = 299 -except_clause = 300 -suite = 301 -test = 302 -test_nocond = 303 -lambdef = 304 -lambdef_nocond = 305 -or_test = 306 -and_test = 307 -not_test = 308 -comparison = 309 -comp_op = 310 -star_expr = 311 -expr = 312 -xor_expr = 313 -and_expr = 314 -shift_expr = 315 -arith_expr = 316 -term = 317 -factor = 318 -power = 319 -atom = 320 -testlist_comp = 321 -trailer = 322 -subscriptlist = 323 -subscript = 324 -sliceop = 325 -exprlist = 326 -testlist = 327 -dictorsetmaker = 328 -classdef = 329 -arglist = 330 -argument = 331 -comp_iter = 332 -comp_for = 333 -comp_if = 334 -encoding_decl = 335 -yield_expr = 336 -yield_arg = 337 +async_funcdef = 262 +funcdef = 263 +parameters = 264 +typedargslist = 265 +tfpdef = 266 +varargslist = 267 +vfpdef = 268 +stmt = 269 +simple_stmt = 270 +small_stmt = 271 +expr_stmt = 272 +testlist_star_expr = 273 +augassign = 274 +del_stmt = 275 +pass_stmt = 276 +flow_stmt = 277 +break_stmt = 278 +continue_stmt = 279 +return_stmt = 280 +yield_stmt = 281 +raise_stmt = 282 +import_stmt = 283 +import_name = 284 +import_from = 285 +import_as_name = 286 +dotted_as_name = 287 +import_as_names = 288 +dotted_as_names = 289 +dotted_name = 290 +global_stmt = 291 +nonlocal_stmt = 292 +assert_stmt = 293 +compound_stmt = 294 +async_stmt = 295 +if_stmt = 296 +while_stmt = 297 +for_stmt = 298 +try_stmt = 299 +with_stmt = 300 +with_item = 301 +except_clause = 302 +suite = 303 +test = 304 +test_nocond = 305 +lambdef = 306 +lambdef_nocond = 307 +or_test = 308 +and_test = 309 +not_test = 310 +comparison = 311 +comp_op = 312 +star_expr = 313 +expr = 314 +xor_expr = 315 +and_expr = 316 +shift_expr = 317 +arith_expr = 318 +term = 319 +factor = 320 +power = 321 +atom_expr = 322 +atom = 323 +testlist_comp = 324 +trailer = 325 +subscriptlist = 326 +subscript = 327 +sliceop = 328 +exprlist = 329 +testlist = 330 +dictorsetmaker = 331 +classdef = 332 +arglist = 333 +argument = 334 +comp_iter = 335 +comp_for = 336 +comp_if = 337 +encoding_decl = 338 +yield_expr = 339 +yield_arg = 340 #--end constants-- sym_name = {} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 18:08:41 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 16:08:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_update_url_=28https=3A//githu?= =?utf-8?q?b=2Ecom/python/pythondotorg/issues/765=29?= Message-ID: <20150527160839.81984.24827@psf.io> https://hg.python.org/peps/rev/18d29aceb6f3 changeset: 5880:18d29aceb6f3 user: Benjamin Peterson date: Wed May 27 11:08:36 2015 -0500 summary: update url (https://github.com/python/pythondotorg/issues/765) files: pep-0440.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0440.txt b/pep-0440.txt --- a/pep-0440.txt +++ b/pep-0440.txt @@ -1525,7 +1525,7 @@ https://github.com/pypa/packaging/blob/master/tasks/check.py .. [3] Pessimistic version constraint - http://docs.rubygems.org/read/chapter/16 + http://guides.rubygems.org/patterns/ .. [4] File URIs in Windows http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed May 27 19:37:29 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 27 May 2015 17:37:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323359=3A_Speciali?= =?utf-8?q?ze_set=5Flookkey_intoa_lookup_function_and_an_insert?= Message-ID: <20150527173726.29821.9@psf.io> https://hg.python.org/cpython/rev/cd1e1715becd changeset: 96312:cd1e1715becd user: Raymond Hettinger date: Wed May 27 10:37:20 2015 -0700 summary: Issue #23359: Specialize set_lookkey intoa lookup function and an insert function. files: Misc/NEWS | 3 + Objects/setobject.c | 145 ++++++++++++++++++++++--------- 2 files changed, 107 insertions(+), 41 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ - Issue #24268: PEP 489: Multi-phase extension module initialization. Patch by Petr Viktorin. +- Issue #23359: Optimize set object internals by specializing the + hash table search into a lookup function and an insert function. + - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -52,7 +52,6 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; - setentry *freeslot = NULL; setentry *entry; size_t perturb = hash; size_t mask = so->mask; @@ -86,14 +85,12 @@ return entry; mask = so->mask; /* help avoid a register spill */ } - if (entry->hash == -1 && freeslot == NULL) - freeslot = entry; if (i + LINEAR_PROBES <= mask) { for (j = 0 ; j < LINEAR_PROBES ; j++) { entry++; - if (entry->key == NULL) - goto found_null; + if (entry->hash == 0 && entry->key == NULL) + return entry; if (entry->hash == hash) { PyObject *startkey = entry->key; assert(startkey != dummy); @@ -114,6 +111,89 @@ return entry; mask = so->mask; } + } + } + + perturb >>= PERTURB_SHIFT; + i = (i * 5 + 1 + perturb) & mask; + + entry = &table[i]; + if (entry->hash == 0 && entry->key == NULL) + return entry; + } +} + +/* +Internal routine to insert a new key into the table. +Used by the public insert routine. +Eats a reference to key. +*/ +static int +set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) +{ + setentry *table = so->table; + setentry *freeslot = NULL; + setentry *entry; + size_t perturb = hash; + size_t mask = so->mask; + size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */ + size_t j; + int cmp; + + entry = &table[i]; + if (entry->key == NULL) + goto found_null; + + while (1) { + if (entry->hash == hash) { + PyObject *startkey = entry->key; + /* startkey cannot be a dummy because the dummy hash field is -1 */ + assert(startkey != dummy); + if (startkey == key) + goto found_active; + if (PyUnicode_CheckExact(startkey) + && PyUnicode_CheckExact(key) + && unicode_eq(startkey, key)) + goto found_active; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) /* unlikely */ + return -1; + if (table != so->table || entry->key != startkey) /* unlikely */ + return set_insert_key(so, key, hash); + if (cmp > 0) /* likely */ + goto found_active; + mask = so->mask; /* help avoid a register spill */ + } + if (entry->hash == -1 && freeslot == NULL) + freeslot = entry; + + if (i + LINEAR_PROBES <= mask) { + for (j = 0 ; j < LINEAR_PROBES ; j++) { + entry++; + if (entry->hash == 0 && entry->key == NULL) + goto found_null; + if (entry->hash == hash) { + PyObject *startkey = entry->key; + assert(startkey != dummy); + if (startkey == key) + goto found_active; + if (PyUnicode_CheckExact(startkey) + && PyUnicode_CheckExact(key) + && unicode_eq(startkey, key)) + goto found_active; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) + return -1; + if (table != so->table || entry->key != startkey) + return set_insert_key(so, key, hash); + if (cmp > 0) + goto found_active; + mask = so->mask; + } if (entry->hash == -1 && freeslot == NULL) freeslot = entry; } @@ -123,11 +203,26 @@ i = (i * 5 + 1 + perturb) & mask; entry = &table[i]; - if (entry->key == NULL) + if (entry->hash == 0 && entry->key == NULL) goto found_null; } + found_null: - return freeslot == NULL ? entry : freeslot; + if (freeslot == NULL) { + /* UNUSED */ + so->fill++; + } else { + /* DUMMY */ + entry = freeslot; + } + so->used++; + entry->key = key; + entry->hash = hash; + return 0; + + found_active: + Py_DECREF(key); + return 0; } /* @@ -172,38 +267,6 @@ /* ======== End logic for probing the hash table ========================== */ /* ======================================================================== */ - -/* -Internal routine to insert a new key into the table. -Used by the public insert routine. -Eats a reference to key. -*/ -static int -set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) -{ - setentry *entry; - - entry = set_lookkey(so, key, hash); - if (entry == NULL) - return -1; - if (entry->key == NULL) { - /* UNUSED */ - entry->key = key; - entry->hash = hash; - so->fill++; - so->used++; - } else if (entry->key == dummy) { - /* DUMMY */ - entry->key = key; - entry->hash = hash; - so->used++; - } else { - /* ACTIVE */ - Py_DECREF(key); - } - return 0; -} - /* Restructure the table by allocating a new table and reinserting all keys again. When entries have been deleted, the new table may @@ -345,7 +408,7 @@ entry = set_lookkey(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; - if (entry->key == NULL || entry->key == dummy) + if (entry->key == NULL) return DISCARD_NOTFOUND; old_key = entry->key; entry->key = dummy; @@ -623,7 +686,7 @@ if (lu_entry == NULL) return -1; key = lu_entry->key; - return key != NULL && key != dummy; + return key != NULL; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 20:32:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 27 May 2015 18:32:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjg4?= =?utf-8?q?=3A_Generated_opcode=2Eh_no_longer_contains_trailing_spaces_and?= =?utf-8?q?_tabs=2E?= Message-ID: <20150527183215.81984.50773@psf.io> https://hg.python.org/cpython/rev/055834bb3685 changeset: 96313:055834bb3685 branch: 3.5 parent: 96310:843fe7e831a8 user: Serhiy Storchaka date: Wed May 27 21:31:33 2015 +0300 summary: Issue #24288: Generated opcode.h no longer contains trailing spaces and tabs. files: Include/opcode.h | 230 ++++++++-------- Tools/scripts/generate_opcode_h.py | 4 +- 2 files changed, 117 insertions(+), 117 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -7,121 +7,121 @@ /* Instruction opcodes for compiled code */ -#define POP_TOP 1 -#define ROT_TWO 2 -#define ROT_THREE 3 -#define DUP_TOP 4 -#define DUP_TOP_TWO 5 -#define NOP 9 -#define UNARY_POSITIVE 10 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define BINARY_MATRIX_MULTIPLY 16 -#define INPLACE_MATRIX_MULTIPLY 17 -#define BINARY_POWER 19 -#define BINARY_MULTIPLY 20 -#define BINARY_MODULO 22 -#define BINARY_ADD 23 -#define BINARY_SUBTRACT 24 -#define BINARY_SUBSCR 25 -#define BINARY_FLOOR_DIVIDE 26 -#define BINARY_TRUE_DIVIDE 27 -#define INPLACE_FLOOR_DIVIDE 28 -#define INPLACE_TRUE_DIVIDE 29 -#define GET_AITER 50 -#define GET_ANEXT 51 -#define BEFORE_ASYNC_WITH 52 -#define STORE_MAP 54 -#define INPLACE_ADD 55 -#define INPLACE_SUBTRACT 56 -#define INPLACE_MULTIPLY 57 -#define INPLACE_MODULO 59 -#define STORE_SUBSCR 60 -#define DELETE_SUBSCR 61 -#define BINARY_LSHIFT 62 -#define BINARY_RSHIFT 63 -#define BINARY_AND 64 -#define BINARY_XOR 65 -#define BINARY_OR 66 -#define INPLACE_POWER 67 -#define GET_ITER 68 -#define PRINT_EXPR 70 -#define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 -#define GET_AWAITABLE 73 -#define INPLACE_LSHIFT 75 -#define INPLACE_RSHIFT 76 -#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 -#define IMPORT_STAR 84 -#define YIELD_VALUE 86 -#define POP_BLOCK 87 -#define END_FINALLY 88 -#define POP_EXCEPT 89 -#define HAVE_ARGUMENT 90 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 -#define LOAD_CONST 100 -#define LOAD_NAME 101 -#define BUILD_TUPLE 102 -#define BUILD_LIST 103 -#define BUILD_SET 104 -#define BUILD_MAP 105 -#define LOAD_ATTR 106 -#define COMPARE_OP 107 -#define IMPORT_NAME 108 -#define IMPORT_FROM 109 -#define JUMP_FORWARD 110 -#define JUMP_IF_FALSE_OR_POP 111 -#define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 -#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 -#define DELETE_FAST 126 -#define RAISE_VARARGS 130 -#define CALL_FUNCTION 131 -#define MAKE_FUNCTION 132 -#define BUILD_SLICE 133 -#define MAKE_CLOSURE 134 -#define LOAD_CLOSURE 135 -#define LOAD_DEREF 136 -#define STORE_DEREF 137 -#define DELETE_DEREF 138 -#define CALL_FUNCTION_VAR 140 -#define CALL_FUNCTION_KW 141 -#define CALL_FUNCTION_VAR_KW 142 -#define SETUP_WITH 143 -#define EXTENDED_ARG 144 -#define LIST_APPEND 145 -#define SET_ADD 146 -#define MAP_ADD 147 -#define LOAD_CLASSDEREF 148 -#define BUILD_LIST_UNPACK 149 -#define BUILD_MAP_UNPACK 150 -#define BUILD_MAP_UNPACK_WITH_CALL 151 -#define BUILD_TUPLE_UNPACK 152 -#define BUILD_SET_UNPACK 153 -#define SETUP_ASYNC_WITH 154 +#define POP_TOP 1 +#define ROT_TWO 2 +#define ROT_THREE 3 +#define DUP_TOP 4 +#define DUP_TOP_TWO 5 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_MATRIX_MULTIPLY 16 +#define INPLACE_MATRIX_MULTIPLY 17 +#define BINARY_POWER 19 +#define BINARY_MULTIPLY 20 +#define BINARY_MODULO 22 +#define BINARY_ADD 23 +#define BINARY_SUBTRACT 24 +#define BINARY_SUBSCR 25 +#define BINARY_FLOOR_DIVIDE 26 +#define BINARY_TRUE_DIVIDE 27 +#define INPLACE_FLOOR_DIVIDE 28 +#define INPLACE_TRUE_DIVIDE 29 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define STORE_MAP 54 +#define INPLACE_ADD 55 +#define INPLACE_SUBTRACT 56 +#define INPLACE_MULTIPLY 57 +#define INPLACE_MODULO 59 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define BINARY_LSHIFT 62 +#define BINARY_RSHIFT 63 +#define BINARY_AND 64 +#define BINARY_XOR 65 +#define BINARY_OR 66 +#define INPLACE_POWER 67 +#define GET_ITER 68 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define YIELD_FROM 72 +#define GET_AWAITABLE 73 +#define INPLACE_LSHIFT 75 +#define INPLACE_RSHIFT 76 +#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 +#define IMPORT_STAR 84 +#define YIELD_VALUE 86 +#define POP_BLOCK 87 +#define END_FINALLY 88 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 +#define LOAD_CONST 100 +#define LOAD_NAME 101 +#define BUILD_TUPLE 102 +#define BUILD_LIST 103 +#define BUILD_SET 104 +#define BUILD_MAP 105 +#define LOAD_ATTR 106 +#define COMPARE_OP 107 +#define IMPORT_NAME 108 +#define IMPORT_FROM 109 +#define JUMP_FORWARD 110 +#define JUMP_IF_FALSE_OR_POP 111 +#define JUMP_IF_TRUE_OR_POP 112 +#define JUMP_ABSOLUTE 113 +#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 +#define DELETE_FAST 126 +#define RAISE_VARARGS 130 +#define CALL_FUNCTION 131 +#define MAKE_FUNCTION 132 +#define BUILD_SLICE 133 +#define MAKE_CLOSURE 134 +#define LOAD_CLOSURE 135 +#define LOAD_DEREF 136 +#define STORE_DEREF 137 +#define DELETE_DEREF 138 +#define CALL_FUNCTION_VAR 140 +#define CALL_FUNCTION_KW 141 +#define CALL_FUNCTION_VAR_KW 142 +#define SETUP_WITH 143 +#define EXTENDED_ARG 144 +#define LIST_APPEND 145 +#define SET_ADD 146 +#define MAP_ADD 147 +#define LOAD_CLASSDEREF 148 +#define BUILD_LIST_UNPACK 149 +#define BUILD_MAP_UNPACK 150 +#define BUILD_MAP_UNPACK_WITH_CALL 151 +#define BUILD_TUPLE_UNPACK 152 +#define BUILD_SET_UNPACK 153 +#define SETUP_ASYNC_WITH 154 /* 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/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py --- a/Tools/scripts/generate_opcode_h.py +++ b/Tools/scripts/generate_opcode_h.py @@ -43,9 +43,9 @@ fobj.write(header) for name in opcode['opname']: if name in opmap: - fobj.write("#define %-20s\t%-3s\n" % (name, opmap[name])) + fobj.write("#define %-23s %3s\n" % (name, opmap[name])) if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT - fobj.write("#define %-20s\t%-3d\n" % + fobj.write("#define %-23s %3d\n" % ('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT'])) fobj.write(footer) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed May 27 20:32:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 27 May 2015 18:32:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324288=3A_Generated_opcode=2Eh_no_longer_contain?= =?utf-8?q?s_trailing_spaces_and_tabs=2E?= Message-ID: <20150527183215.5071.72164@psf.io> https://hg.python.org/cpython/rev/9d9438cac3db changeset: 96314:9d9438cac3db parent: 96312:cd1e1715becd parent: 96313:055834bb3685 user: Serhiy Storchaka date: Wed May 27 21:31:50 2015 +0300 summary: Issue #24288: Generated opcode.h no longer contains trailing spaces and tabs. files: Include/opcode.h | 230 ++++++++-------- Tools/scripts/generate_opcode_h.py | 4 +- 2 files changed, 117 insertions(+), 117 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -7,121 +7,121 @@ /* Instruction opcodes for compiled code */ -#define POP_TOP 1 -#define ROT_TWO 2 -#define ROT_THREE 3 -#define DUP_TOP 4 -#define DUP_TOP_TWO 5 -#define NOP 9 -#define UNARY_POSITIVE 10 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define BINARY_MATRIX_MULTIPLY 16 -#define INPLACE_MATRIX_MULTIPLY 17 -#define BINARY_POWER 19 -#define BINARY_MULTIPLY 20 -#define BINARY_MODULO 22 -#define BINARY_ADD 23 -#define BINARY_SUBTRACT 24 -#define BINARY_SUBSCR 25 -#define BINARY_FLOOR_DIVIDE 26 -#define BINARY_TRUE_DIVIDE 27 -#define INPLACE_FLOOR_DIVIDE 28 -#define INPLACE_TRUE_DIVIDE 29 -#define GET_AITER 50 -#define GET_ANEXT 51 -#define BEFORE_ASYNC_WITH 52 -#define STORE_MAP 54 -#define INPLACE_ADD 55 -#define INPLACE_SUBTRACT 56 -#define INPLACE_MULTIPLY 57 -#define INPLACE_MODULO 59 -#define STORE_SUBSCR 60 -#define DELETE_SUBSCR 61 -#define BINARY_LSHIFT 62 -#define BINARY_RSHIFT 63 -#define BINARY_AND 64 -#define BINARY_XOR 65 -#define BINARY_OR 66 -#define INPLACE_POWER 67 -#define GET_ITER 68 -#define PRINT_EXPR 70 -#define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 -#define GET_AWAITABLE 73 -#define INPLACE_LSHIFT 75 -#define INPLACE_RSHIFT 76 -#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 -#define IMPORT_STAR 84 -#define YIELD_VALUE 86 -#define POP_BLOCK 87 -#define END_FINALLY 88 -#define POP_EXCEPT 89 -#define HAVE_ARGUMENT 90 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 -#define LOAD_CONST 100 -#define LOAD_NAME 101 -#define BUILD_TUPLE 102 -#define BUILD_LIST 103 -#define BUILD_SET 104 -#define BUILD_MAP 105 -#define LOAD_ATTR 106 -#define COMPARE_OP 107 -#define IMPORT_NAME 108 -#define IMPORT_FROM 109 -#define JUMP_FORWARD 110 -#define JUMP_IF_FALSE_OR_POP 111 -#define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 -#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 -#define DELETE_FAST 126 -#define RAISE_VARARGS 130 -#define CALL_FUNCTION 131 -#define MAKE_FUNCTION 132 -#define BUILD_SLICE 133 -#define MAKE_CLOSURE 134 -#define LOAD_CLOSURE 135 -#define LOAD_DEREF 136 -#define STORE_DEREF 137 -#define DELETE_DEREF 138 -#define CALL_FUNCTION_VAR 140 -#define CALL_FUNCTION_KW 141 -#define CALL_FUNCTION_VAR_KW 142 -#define SETUP_WITH 143 -#define EXTENDED_ARG 144 -#define LIST_APPEND 145 -#define SET_ADD 146 -#define MAP_ADD 147 -#define LOAD_CLASSDEREF 148 -#define BUILD_LIST_UNPACK 149 -#define BUILD_MAP_UNPACK 150 -#define BUILD_MAP_UNPACK_WITH_CALL 151 -#define BUILD_TUPLE_UNPACK 152 -#define BUILD_SET_UNPACK 153 -#define SETUP_ASYNC_WITH 154 +#define POP_TOP 1 +#define ROT_TWO 2 +#define ROT_THREE 3 +#define DUP_TOP 4 +#define DUP_TOP_TWO 5 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_MATRIX_MULTIPLY 16 +#define INPLACE_MATRIX_MULTIPLY 17 +#define BINARY_POWER 19 +#define BINARY_MULTIPLY 20 +#define BINARY_MODULO 22 +#define BINARY_ADD 23 +#define BINARY_SUBTRACT 24 +#define BINARY_SUBSCR 25 +#define BINARY_FLOOR_DIVIDE 26 +#define BINARY_TRUE_DIVIDE 27 +#define INPLACE_FLOOR_DIVIDE 28 +#define INPLACE_TRUE_DIVIDE 29 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define STORE_MAP 54 +#define INPLACE_ADD 55 +#define INPLACE_SUBTRACT 56 +#define INPLACE_MULTIPLY 57 +#define INPLACE_MODULO 59 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define BINARY_LSHIFT 62 +#define BINARY_RSHIFT 63 +#define BINARY_AND 64 +#define BINARY_XOR 65 +#define BINARY_OR 66 +#define INPLACE_POWER 67 +#define GET_ITER 68 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define YIELD_FROM 72 +#define GET_AWAITABLE 73 +#define INPLACE_LSHIFT 75 +#define INPLACE_RSHIFT 76 +#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 +#define IMPORT_STAR 84 +#define YIELD_VALUE 86 +#define POP_BLOCK 87 +#define END_FINALLY 88 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 +#define LOAD_CONST 100 +#define LOAD_NAME 101 +#define BUILD_TUPLE 102 +#define BUILD_LIST 103 +#define BUILD_SET 104 +#define BUILD_MAP 105 +#define LOAD_ATTR 106 +#define COMPARE_OP 107 +#define IMPORT_NAME 108 +#define IMPORT_FROM 109 +#define JUMP_FORWARD 110 +#define JUMP_IF_FALSE_OR_POP 111 +#define JUMP_IF_TRUE_OR_POP 112 +#define JUMP_ABSOLUTE 113 +#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 +#define DELETE_FAST 126 +#define RAISE_VARARGS 130 +#define CALL_FUNCTION 131 +#define MAKE_FUNCTION 132 +#define BUILD_SLICE 133 +#define MAKE_CLOSURE 134 +#define LOAD_CLOSURE 135 +#define LOAD_DEREF 136 +#define STORE_DEREF 137 +#define DELETE_DEREF 138 +#define CALL_FUNCTION_VAR 140 +#define CALL_FUNCTION_KW 141 +#define CALL_FUNCTION_VAR_KW 142 +#define SETUP_WITH 143 +#define EXTENDED_ARG 144 +#define LIST_APPEND 145 +#define SET_ADD 146 +#define MAP_ADD 147 +#define LOAD_CLASSDEREF 148 +#define BUILD_LIST_UNPACK 149 +#define BUILD_MAP_UNPACK 150 +#define BUILD_MAP_UNPACK_WITH_CALL 151 +#define BUILD_TUPLE_UNPACK 152 +#define BUILD_SET_UNPACK 153 +#define SETUP_ASYNC_WITH 154 /* 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/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py --- a/Tools/scripts/generate_opcode_h.py +++ b/Tools/scripts/generate_opcode_h.py @@ -43,9 +43,9 @@ fobj.write(header) for name in opcode['opname']: if name in opmap: - fobj.write("#define %-20s\t%-3s\n" % (name, opmap[name])) + fobj.write("#define %-23s %3s\n" % (name, opmap[name])) if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT - fobj.write("#define %-20s\t%-3d\n" % + fobj.write("#define %-23s %3d\n" % ('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT'])) fobj.write(footer) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 00:39:06 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 27 May 2015 22:39:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24304=3A_Fix_broken_license_link_in_FAQ=2E?= Message-ID: <20150527223906.28695.67860@psf.io> https://hg.python.org/cpython/rev/e57e37c3986c changeset: 96318:e57e37c3986c parent: 96314:9d9438cac3db parent: 96317:892a8bed619d user: Ned Deily date: Wed May 27 15:38:16 2015 -0700 summary: Issue 24304: Fix broken license link in FAQ. files: Doc/faq/general.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -53,7 +53,7 @@ unmodified), or to sell products that incorporate Python in some form. We would still like to know about all commercial use of Python, of course. -See `the PSF license page `_ to find further +See `the PSF license page `_ to find further explanations and a link to the full text of the license. The Python logo is trademarked, and in certain cases permission is required to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 00:39:06 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 27 May 2015 22:39:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_24304=3A_Fix_broken_license_link_in_FAQ=2E?= Message-ID: <20150527223906.82000.94924@psf.io> https://hg.python.org/cpython/rev/892a8bed619d changeset: 96317:892a8bed619d branch: 3.5 parent: 96313:055834bb3685 parent: 96316:8631d61f6577 user: Ned Deily date: Wed May 27 15:37:32 2015 -0700 summary: Issue 24304: Fix broken license link in FAQ. files: Doc/faq/general.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -53,7 +53,7 @@ unmodified), or to sell products that incorporate Python in some form. We would still like to know about all commercial use of Python, of course. -See `the PSF license page `_ to find further +See `the PSF license page `_ to find further explanations and a link to the full text of the license. The Python logo is trademarked, and in certain cases permission is required to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 00:39:06 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 27 May 2015 22:39:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQzMDQ6?= =?utf-8?q?_Fix_broken_license_link_in_FAQ=2E?= Message-ID: <20150527223906.81984.48969@psf.io> https://hg.python.org/cpython/rev/8631d61f6577 changeset: 96316:8631d61f6577 branch: 3.4 parent: 96296:5a9901c21213 user: Ned Deily date: Wed May 27 15:37:00 2015 -0700 summary: Issue 24304: Fix broken license link in FAQ. files: Doc/faq/general.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -53,7 +53,7 @@ unmodified), or to sell products that incorporate Python in some form. We would still like to know about all commercial use of Python, of course. -See `the PSF license page `_ to find further +See `the PSF license page `_ to find further explanations and a link to the full text of the license. The Python logo is trademarked, and in certain cases permission is required to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 00:39:06 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 27 May 2015 22:39:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgMjQzMDQ6?= =?utf-8?q?_Fix_broken_license_link_in_FAQ=2E?= Message-ID: <20150527223906.29843.44215@psf.io> https://hg.python.org/cpython/rev/d4080f3c0894 changeset: 96315:d4080f3c0894 branch: 2.7 parent: 96299:9213c70c67d2 user: Ned Deily date: Wed May 27 15:36:39 2015 -0700 summary: Issue 24304: Fix broken license link in FAQ. files: Doc/faq/general.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -53,7 +53,7 @@ unmodified), or to sell products that incorporate Python in some form. We would still like to know about all commercial use of Python, of course. -See `the PSF license page `_ to find further +See `the PSF license page `_ to find further explanations and a link to the full text of the license. The Python logo is trademarked, and in certain cases permission is required to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 01:34:15 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 23:34:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_update_for_3?= =?utf-8?q?=2E6_emerging?= Message-ID: <20150527233415.16461.76284@psf.io> https://hg.python.org/cpython/rev/901178d9d07f changeset: 96319:901178d9d07f branch: 3.4 parent: 96316:8631d61f6577 user: Benjamin Peterson date: Wed May 27 18:32:25 2015 -0500 summary: update for 3.6 emerging files: Doc/tools/static/version_switch.js | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/tools/static/version_switch.js b/Doc/tools/static/version_switch.js --- a/Doc/tools/static/version_switch.js +++ b/Doc/tools/static/version_switch.js @@ -2,7 +2,8 @@ 'use strict'; var all_versions = { - '3.5': 'dev (3.5)', + '3.6': 'dev (3.6)', + '3.5': '3.5', '3.4': '3.4', '3.3': '3.3', '3.2': '3.2', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 01:34:16 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 23:34:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150527233416.17089.70354@psf.io> https://hg.python.org/cpython/rev/734b557342bd changeset: 96321:734b557342bd parent: 96318:e57e37c3986c parent: 96320:3d558ecd9936 user: Benjamin Peterson date: Wed May 27 18:32:53 2015 -0500 summary: merge 3.5 files: Doc/tools/static/version_switch.js | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/tools/static/version_switch.js b/Doc/tools/static/version_switch.js --- a/Doc/tools/static/version_switch.js +++ b/Doc/tools/static/version_switch.js @@ -2,7 +2,8 @@ 'use strict'; var all_versions = { - '3.5': 'dev (3.5)', + '3.6': 'dev (3.6)', + '3.5': '3.5', '3.4': '3.4', '3.3': '3.3', '3.2': '3.2', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 01:34:16 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 23:34:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4?= Message-ID: <20150527233415.125209.61879@psf.io> https://hg.python.org/cpython/rev/3d558ecd9936 changeset: 96320:3d558ecd9936 branch: 3.5 parent: 96317:892a8bed619d parent: 96319:901178d9d07f user: Benjamin Peterson date: Wed May 27 18:32:41 2015 -0500 summary: merge 3.4 files: Doc/tools/static/version_switch.js | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/tools/static/version_switch.js b/Doc/tools/static/version_switch.js --- a/Doc/tools/static/version_switch.js +++ b/Doc/tools/static/version_switch.js @@ -2,7 +2,8 @@ 'use strict'; var all_versions = { - '3.5': 'dev (3.5)', + '3.6': 'dev (3.6)', + '3.5': '3.5', '3.4': '3.4', '3.3': '3.3', '3.2': '3.2', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 01:34:16 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 27 May 2015 23:34:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_update_for_3?= =?utf-8?q?=2E6_emerging?= Message-ID: <20150527233416.84475.34694@psf.io> https://hg.python.org/cpython/rev/581776726b61 changeset: 96322:581776726b61 branch: 2.7 parent: 96315:d4080f3c0894 user: Benjamin Peterson date: Wed May 27 18:32:25 2015 -0500 summary: update for 3.6 emerging files: Doc/tools/static/version_switch.js | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/tools/static/version_switch.js b/Doc/tools/static/version_switch.js --- a/Doc/tools/static/version_switch.js +++ b/Doc/tools/static/version_switch.js @@ -2,7 +2,8 @@ 'use strict'; var all_versions = { - '3.5': 'dev (3.5)', + '3.6': 'dev (3.6)', + '3.5': '3.5', '3.4': '3.4', '3.3': '3.3', '3.2': '3.2', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 04:01:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 02:01:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQyOTg6?= =?utf-8?q?_Fix_signature=28=29_to_properly_unwrap_wrappers_around_bound_m?= =?utf-8?q?ethods?= Message-ID: <20150528020129.17493.26782@psf.io> https://hg.python.org/cpython/rev/42819b176d63 changeset: 96323:42819b176d63 branch: 3.4 parent: 96319:901178d9d07f user: Yury Selivanov date: Wed May 27 21:56:53 2015 -0400 summary: Issue 24298: Fix signature() to properly unwrap wrappers around bound methods files: Lib/inspect.py | 8 ++++++++ Lib/test/test_inspect.py | 13 +++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 24 insertions(+), 0 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1911,6 +1911,14 @@ # Was this function wrapped by a decorator? if follow_wrapper_chains: obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + if isinstance(obj, types.MethodType): + # If the unwrapped object is a *method*, we might want to + # skip its first parameter (self). + # See test_signature_wrapped_bound_method for details. + return _signature_internal( + obj, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg) try: sig = obj.__signature__ diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1939,6 +1939,19 @@ with self.assertRaisesRegex(ValueError, 'invalid method signature'): self.signature(Test()) + def test_signature_wrapped_bound_method(self): + # Issue 24298 + class Test: + def m1(self, arg1, arg2=1) -> int: + pass + @functools.wraps(Test().m1) + def m1d(*args, **kwargs): + pass + self.assertEqual(self.signature(m1d), + ((('arg1', ..., ..., "positional_or_keyword"), + ('arg2', 1, ..., "positional_or_keyword")), + int)) + def test_signature_on_classmethod(self): class Test: @classmethod diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -274,6 +274,9 @@ - Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +- Issue #24298: Fix inspect.signature() to correctly unwrap wrappers + around bound methods. + IDLE ---- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 04:01:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 02:01:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24298=3A_Fix_signature=28=29_to_properly_unwrap_wr?= =?utf-8?q?appers_around_bound_methods?= Message-ID: <20150528020129.9291.23201@psf.io> https://hg.python.org/cpython/rev/ab46801ca359 changeset: 96325:ab46801ca359 parent: 96321:734b557342bd parent: 96324:d7e392c5c53a user: Yury Selivanov date: Wed May 27 21:59:27 2015 -0400 summary: Issue 24298: Fix signature() to properly unwrap wrappers around bound methods files: Lib/inspect.py | 9 +++++++++ Lib/test/test_inspect.py | 13 +++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2130,6 +2130,15 @@ # Was this function wrapped by a decorator? if follow_wrapper_chains: obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + if isinstance(obj, types.MethodType): + # If the unwrapped object is a *method*, we might want to + # skip its first parameter (self). + # See test_signature_wrapped_bound_method for details. + return _signature_from_callable( + obj, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) try: sig = obj.__signature__ diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2086,6 +2086,19 @@ with self.assertRaisesRegex(ValueError, 'invalid method signature'): self.signature(Test()) + def test_signature_wrapped_bound_method(self): + # Issue 24298 + class Test: + def m1(self, arg1, arg2=1) -> int: + pass + @functools.wraps(Test().m1) + def m1d(*args, **kwargs): + pass + self.assertEqual(self.signature(m1d), + ((('arg1', ..., ..., "positional_or_keyword"), + ('arg2', 1, ..., "positional_or_keyword")), + int)) + def test_signature_on_classmethod(self): class Test: @classmethod diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -263,6 +263,9 @@ - Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +- Issue #24298: Fix inspect.signature() to correctly unwrap wrappers + around bound methods. + IDLE ---- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 04:01:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 02:01:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_24298=3A_Fix_signature=28=29_to_properly_unwrap_wrappers?= =?utf-8?q?_around_bound_methods?= Message-ID: <20150528020129.125209.26371@psf.io> https://hg.python.org/cpython/rev/d7e392c5c53a changeset: 96324:d7e392c5c53a branch: 3.5 parent: 96320:3d558ecd9936 parent: 96323:42819b176d63 user: Yury Selivanov date: Wed May 27 21:59:03 2015 -0400 summary: Issue 24298: Fix signature() to properly unwrap wrappers around bound methods files: Lib/inspect.py | 9 +++++++++ Lib/test/test_inspect.py | 13 +++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2130,6 +2130,15 @@ # Was this function wrapped by a decorator? if follow_wrapper_chains: obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + if isinstance(obj, types.MethodType): + # If the unwrapped object is a *method*, we might want to + # skip its first parameter (self). + # See test_signature_wrapped_bound_method for details. + return _signature_from_callable( + obj, + follow_wrapper_chains=follow_wrapper_chains, + skip_bound_arg=skip_bound_arg, + sigcls=sigcls) try: sig = obj.__signature__ diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2086,6 +2086,19 @@ with self.assertRaisesRegex(ValueError, 'invalid method signature'): self.signature(Test()) + def test_signature_wrapped_bound_method(self): + # Issue 24298 + class Test: + def m1(self, arg1, arg2=1) -> int: + pass + @functools.wraps(Test().m1) + def m1d(*args, **kwargs): + pass + self.assertEqual(self.signature(m1d), + ((('arg1', ..., ..., "positional_or_keyword"), + ('arg2', 1, ..., "positional_or_keyword")), + int)) + def test_signature_on_classmethod(self): class Test: @classmethod diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -248,6 +248,9 @@ - Issue #23898: Fix inspect.classify_class_attrs() to support attributes with overloaded __eq__ and __bool__. Patch by Mike Bayer. +- Issue #24298: Fix inspect.signature() to correctly unwrap wrappers + around bound methods. + IDLE ---- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 04:09:16 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 02:09:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_whatsnew_for_3=2E6?= Message-ID: <20150528020916.27302.99979@psf.io> https://hg.python.org/cpython/rev/ccc613d2f03e changeset: 96326:ccc613d2f03e user: Yury Selivanov date: Wed May 27 22:09:10 2015 -0400 summary: Add whatsnew for 3.6 files: Doc/whatsnew/3.6.rst | 158 +++++++++++++++++++++++++++++ Doc/whatsnew/index.rst | 1 + 2 files changed, 159 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst new file mode 100644 --- /dev/null +++ b/Doc/whatsnew/3.6.rst @@ -0,0 +1,158 @@ +**************************** + What's New In Python 3.6 +**************************** + +:Release: |release| +:Date: |today| + +.. Rules for maintenance: + + * Anyone can add text to this document. Do not spend very much time + on the wording of your changes, because your text will probably + get rewritten to some degree. + + * The maintainer will go through Misc/NEWS periodically and add + changes; it's therefore more important to add your changes to + Misc/NEWS than to this file. + + * This is not a complete list of every single change; completeness + is the purpose of Misc/NEWS. Some changes I consider too small + or esoteric to include. If such a change is added to the text, + I'll just remove it. (This is another reason you shouldn't spend + too much time on writing your addition.) + + * If you want to draw your new text to the attention of the + maintainer, add 'XXX' to the beginning of the paragraph or + section. + + * It's OK to just add a fragmentary note about a change. For + example: "XXX Describe the transmogrify() function added to the + socket module." The maintainer will research the change and + write the necessary text. + + * You can comment out your additions if you like, but it's not + necessary (especially when a final release is some months away). + + * Credit the author of a patch or bugfix. Just the name is + sufficient; the e-mail address isn't necessary. + + * It's helpful to add the bug/patch number as a comment: + + XXX Describe the transmogrify() function added to the socket + module. + (Contributed by P.Y. Developer in :issue:`12345`.) + + This saves the maintainer the effort of going through the Mercurial log + when researching a change. + +This article explains the new features in Python 3.6, compared to 3.5. + +For full details, see the :source:`Misc/NEWS` file. + +.. note:: + + Prerelease users should be aware that this document is currently in draft + form. It will be updated substantially as Python 3.6 moves towards release, + so it's worth checking back even after reading earlier versions. + + +Summary -- Release highlights +============================= + +.. This section singles out the most important changes in Python 3.6. + Brevity is key. + +* None yet. + +.. PEP-sized items next. + +.. _pep-4XX: + +.. PEP 4XX: Virtual Environments +.. ============================= + + +.. (Implemented by Foo Bar.) + +.. .. seealso:: + + :pep:`4XX` - Python Virtual Environments + PEP written by Carl Meyer + + +Other Language Changes +====================== + +* None yet. + + +New Modules +=========== + +* None yet. + + +Improved Modules +================ + +* None yet. + + +Optimizations +============= + +* None yet. + + +Build and C API Changes +======================= + +* None yet. + + +Deprecated +========== + +Deprecated Python modules, functions and methods +------------------------------------------------ + +* None yet. + + +Deprecated functions and types of the C API +------------------------------------------- + +* None yet. + + +Deprecated features +------------------- + +* None yet. + + +Removed +======= + +API and Feature Removals +------------------------ + +* None yet. + + +Porting to Python 3.6 +===================== + +This section lists previously described changes and other bugfixes +that may require changes to your code. + +Changes in the Python API +------------------------- + +* None yet. + + +Changes in the C API +-------------------- + +* None yet. diff --git a/Doc/whatsnew/index.rst b/Doc/whatsnew/index.rst --- a/Doc/whatsnew/index.rst +++ b/Doc/whatsnew/index.rst @@ -11,6 +11,7 @@ .. toctree:: :maxdepth: 2 + 3.6.rst 3.5.rst 3.4.rst 3.3.rst -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 06:30:58 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 04:30:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_update_configure_version_t?= =?utf-8?q?o_3=2E6?= Message-ID: <20150528043058.84493.14333@psf.io> https://hg.python.org/cpython/rev/30f5e7ec6afe changeset: 96327:30f5e7ec6afe user: Benjamin Peterson date: Wed May 27 23:29:00 2015 -0500 summary: update configure version to 3.6 files: configure | 20 ++++++++++---------- configure.ac | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for python 3.5. +# Generated by GNU Autoconf 2.69 for python 3.6. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='python' PACKAGE_TARNAME='python' -PACKAGE_VERSION='3.5' -PACKAGE_STRING='python 3.5' +PACKAGE_VERSION='3.6' +PACKAGE_STRING='python 3.6' PACKAGE_BUGREPORT='http://bugs.python.org/' PACKAGE_URL='' @@ -1378,7 +1378,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures python 3.5 to adapt to many kinds of systems. +\`configure' configures python 3.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1443,7 +1443,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of python 3.5:";; + short | recursive ) echo "Configuration of python 3.6:";; esac cat <<\_ACEOF @@ -1597,7 +1597,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -python configure 3.5 +python configure 3.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2436,7 +2436,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by python $as_me 3.5, which was +It was created by python $as_me 3.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3009,7 +3009,7 @@ mv confdefs.h.new confdefs.h -VERSION=3.5 +VERSION=3.6 # Version number of Python's own shared library file. @@ -16540,7 +16540,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by python $as_me 3.5, which was +This file was extended by python $as_me 3.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16602,7 +16602,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -python config.status 3.5 +python config.status 3.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *********************************************** # Set VERSION so we only need to edit in one place (i.e., here) -m4_define(PYTHON_VERSION, 3.5) +m4_define(PYTHON_VERSION, 3.6) AC_PREREQ(2.65) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 07:01:17 2015 From: python-checkins at python.org (ned.deily) Date: Thu, 28 May 2015 05:01:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_More_version_bumping_to_3?= =?utf-8?b?LjYu?= Message-ID: <20150528050117.17501.32607@psf.io> https://hg.python.org/cpython/rev/dfe62f685538 changeset: 96328:dfe62f685538 user: Ned Deily date: Wed May 27 22:00:46 2015 -0700 summary: More version bumping to 3.6. With the creation of the 3.5 branch earlier in the process, it is necessary to do some of the version bumps now rather than at final release time (for example, the equivalent of the 3.4->3.5 bumps in f2bf12fa22c1). (Some of those changes have already been made, for example in 30f5e7ec6afe.) files: Doc/tutorial/interpreter.rst | 14 +++++++------- Doc/tutorial/stdlib.rst | 2 +- Doc/tutorial/stdlib2.rst | 2 +- README | 16 ++++++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -1,4 +1,4 @@ -.. _tut-using: +3.6.. _tut-using: **************************** Using the Python Interpreter @@ -10,13 +10,13 @@ Invoking the Interpreter ======================== -The Python interpreter is usually installed as :file:`/usr/local/bin/python3.5` +The Python interpreter is usually installed as :file:`/usr/local/bin/python3.6` on those machines where it is available; putting :file:`/usr/local/bin` in your Unix shell's search path makes it possible to start it by typing the command: .. code-block:: text - python3.5 + python3.6 to the shell. [#]_ Since the choice of the directory where the interpreter lives is an installation option, other places are possible; check with your local @@ -24,11 +24,11 @@ popular alternative location.) On Windows machines, the Python installation is usually placed in -:file:`C:\\Python35`, though you can change this when you're running the +:file:`C:\\Python36`, though you can change this when you're running the installer. To add this directory to your path, you can type the following command into the command prompt in a DOS box:: - set path=%path%;C:\python35 + set path=%path%;C:\python36 Typing an end-of-file character (:kbd:`Control-D` on Unix, :kbd:`Control-Z` on Windows) at the primary prompt causes the interpreter to exit with a zero exit @@ -96,8 +96,8 @@ prints a welcome message stating its version number and a copyright notice before printing the first prompt:: - $ python3.5 - Python 3.5 (default, Sep 16 2015, 09:25:04) + $ python3.6 + Python 3.6 (default, Sep 16 2015, 09:25:04) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -15,7 +15,7 @@ >>> import os >>> os.getcwd() # Return the current working directory - 'C:\\Python35' + 'C:\\Python36' >>> os.chdir('/server/accesslogs') # Change current working directory >>> os.system('mkdir today') # Run the command mkdir in the system shell 0 diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst --- a/Doc/tutorial/stdlib2.rst +++ b/Doc/tutorial/stdlib2.rst @@ -277,7 +277,7 @@ Traceback (most recent call last): File "", line 1, in d['primary'] # entry was automatically removed - File "C:/python35/lib/weakref.py", line 46, in __getitem__ + File "C:/python36/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.5.0 beta 1 -=================================== +This is Python version 3.6.0 alpha 1 +==================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved. @@ -50,9 +50,9 @@ ---------- We try to have a comprehensive overview of the changes in the "What's New in -Python 3.5" document, found at +Python 3.6" document, found at - http://docs.python.org/3.5/whatsnew/3.5.html + http://docs.python.org/3.6/whatsnew/3.6.html For a more detailed change log, read Misc/NEWS (though this file, too, is incomplete, and also doesn't list anything merged in from the 2.7 release under @@ -65,9 +65,9 @@ Documentation ------------- -Documentation for Python 3.5 is online, updated daily: +Documentation for Python 3.6 is online, updated daily: - http://docs.python.org/3.5/ + http://docs.python.org/3.6/ It can also be downloaded in many formats for faster access. The documentation is downloadable in HTML, PDF, and reStructuredText formats; the latter version @@ -92,7 +92,7 @@ A source-to-source translation tool, "2to3", can take care of the mundane task of converting large amounts of source code. It is not a complete solution but is complemented by the deprecation warnings in 2.6. See -http://docs.python.org/3.5/library/2to3.html for more information. +http://docs.python.org/3.6/library/2to3.html for more information. Testing @@ -130,7 +130,7 @@ Install that version using "make install". Install all other versions using "make altinstall". -For example, if you want to install Python 2.6, 2.7 and 3.5 with 2.7 being the +For example, if you want to install Python 2.6, 2.7 and 3.6 with 2.7 being the primary version, you would execute "make install" in your 2.7 build directory and "make altinstall" in the others. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu May 28 11:02:53 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 28 May 2015 09:02:53 +0000 Subject: [Python-checkins] Daily reference leaks (dfe62f685538): sum=232 Message-ID: <20150528090253.17499.336@psf.io> results for dfe62f685538 on branch "default" -------------------------------------------- test_collections leaked [4, 0, 0] references, sum=4 test_collections leaked [2, 0, 0] memory blocks, sum=2 test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogBMhQkX', '--timeout', '7200'] From python-checkins at python.org Thu May 28 16:53:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 14:53:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogRHJv?= =?utf-8?q?p_some_useless_code_from_tasks=2Epy=2E?= Message-ID: <20150528145322.10370.55003@psf.io> https://hg.python.org/cpython/rev/09327f653ec5 changeset: 96329:09327f653ec5 branch: 3.4 parent: 96323:42819b176d63 user: Yury Selivanov date: Thu May 28 10:52:19 2015 -0400 summary: asyncio: Drop some useless code from tasks.py. See also issue 24017. files: Lib/asyncio/tasks.py | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -74,10 +74,7 @@ super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - if coro.__class__ is types.GeneratorType: - self._coro = coro - else: - self._coro = iter(coro) # Use the iterator just in case. + self._coro = coro self._fut_waiter = None self._must_cancel = False self._loop.call_soon(self._step) @@ -237,10 +234,8 @@ try: if exc is not None: result = coro.throw(exc) - elif value is not None: + else: result = coro.send(value) - else: - result = coro.send(None) except StopIteration as exc: self.set_result(exc.value) except futures.CancelledError as exc: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 16:53:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 14:53:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_asyncio=3A_Drop_some_useless_code_from_tasks=2Epy=2E?= Message-ID: <20150528145322.17479.42996@psf.io> https://hg.python.org/cpython/rev/adf72cffceb7 changeset: 96330:adf72cffceb7 branch: 3.5 parent: 96324:d7e392c5c53a parent: 96329:09327f653ec5 user: Yury Selivanov date: Thu May 28 10:52:46 2015 -0400 summary: asyncio: Drop some useless code from tasks.py. See also issue 24017. files: Lib/asyncio/tasks.py | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -74,10 +74,7 @@ super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - if coro.__class__ is types.GeneratorType: - self._coro = coro - else: - self._coro = iter(coro) # Use the iterator just in case. + self._coro = coro self._fut_waiter = None self._must_cancel = False self._loop.call_soon(self._step) @@ -237,10 +234,8 @@ try: if exc is not None: result = coro.throw(exc) - elif value is not None: + else: result = coro.send(value) - else: - result = coro.send(None) except StopIteration as exc: self.set_result(exc.value) except futures.CancelledError as exc: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 16:53:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 14:53:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_asyncio=3A_Drop_some_useless_code_from_tasks=2Epy=2E?= Message-ID: <20150528145322.62573.95466@psf.io> https://hg.python.org/cpython/rev/9c0a00247021 changeset: 96331:9c0a00247021 parent: 96328:dfe62f685538 parent: 96330:adf72cffceb7 user: Yury Selivanov date: Thu May 28 10:53:04 2015 -0400 summary: asyncio: Drop some useless code from tasks.py. See also issue 24017. files: Lib/asyncio/tasks.py | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -74,10 +74,7 @@ super().__init__(loop=loop) if self._source_traceback: del self._source_traceback[-1] - if coro.__class__ is types.GeneratorType: - self._coro = coro - else: - self._coro = iter(coro) # Use the iterator just in case. + self._coro = coro self._fut_waiter = None self._must_cancel = False self._loop.call_soon(self._step) @@ -237,10 +234,8 @@ try: if exc is not None: result = coro.throw(exc) - elif value is not None: + else: result = coro.send(value) - else: - result = coro.send(None) except StopIteration as exc: self.set_result(exc.value) except futures.CancelledError as exc: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 17:22:50 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 15:22:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQwMTc6?= =?utf-8?q?_Drop_getawaitablefunc_and_friends_in_favor_of_unaryfunc=2E?= Message-ID: <20150528152249.119126.95732@psf.io> https://hg.python.org/cpython/rev/dfa0288c91fd changeset: 96332:dfa0288c91fd branch: 3.5 parent: 96330:adf72cffceb7 user: Yury Selivanov date: Thu May 28 11:21:31 2015 -0400 summary: Issue 24017: Drop getawaitablefunc and friends in favor of unaryfunc. files: Doc/c-api/typeobj.rst | 12 ++++++------ Include/object.h | 9 +++------ Modules/_testcapimodule.c | 2 +- Objects/genobject.c | 2 +- Python/ceval.c | 4 ++-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1357,12 +1357,12 @@ Here is the structure definition:: typedef struct { - getawaitablefunc am_await; - getaiterfunc am_aiter; - aiternextfunc am_anext; + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; } PyAsyncMethods; -.. c:member:: getawaitablefunc PyAsyncMethods.am_await +.. c:member:: unaryfunc PyAsyncMethods.am_await The signature of this function is:: @@ -1373,7 +1373,7 @@ This slot may be set to *NULL* if an object is not an :term:`awaitable`. -.. c:member:: getaiterfunc PyAsyncMethods.am_aiter +.. c:member:: unaryfunc PyAsyncMethods.am_aiter The signature of this function is:: @@ -1384,7 +1384,7 @@ This slot may be set to *NULL* if an object does not implement asynchronous iteration protocol. -.. c:member:: aiternextfunc PyAsyncMethods.am_anext +.. c:member:: unaryfunc PyAsyncMethods.am_anext The signature of this function is:: diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -173,9 +173,6 @@ typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *); -typedef PyObject *(*getawaitablefunc) (PyObject *); -typedef PyObject *(*getaiterfunc) (PyObject *); -typedef PyObject *(*aiternextfunc) (PyObject *); #ifndef Py_LIMITED_API /* buffer interface */ @@ -305,9 +302,9 @@ } PyMappingMethods; typedef struct { - getawaitablefunc am_await; - getaiterfunc am_aiter; - aiternextfunc am_anext; + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; } PyAsyncMethods; typedef struct { diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3987,7 +3987,7 @@ } static PyAsyncMethods awaitType_as_async = { - (getawaitablefunc)awaitObject_await, /* am_await */ + (unaryfunc)awaitObject_await, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ }; diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -708,7 +708,7 @@ PyObject * _PyGen_GetAwaitableIter(PyObject *o) { - getawaitablefunc getter = NULL; + unaryfunc getter = NULL; PyTypeObject *ot; if (PyGen_CheckCoroutineExact(o)) { diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1927,7 +1927,7 @@ } TARGET(GET_AITER) { - getaiterfunc getter = NULL; + unaryfunc getter = NULL; PyObject *iter = NULL; PyObject *awaitable = NULL; PyObject *obj = TOP(); @@ -1974,7 +1974,7 @@ } TARGET(GET_ANEXT) { - aiternextfunc getter = NULL; + unaryfunc getter = NULL; PyObject *next_iter = NULL; PyObject *awaitable = NULL; PyObject *aiter = TOP(); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 17:22:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 15:22:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24017=3A_Drop_getawaitablefunc_and_friends_in_favo?= =?utf-8?q?r_of_unaryfunc=2E?= Message-ID: <20150528152249.17495.97159@psf.io> https://hg.python.org/cpython/rev/99dcca3466d3 changeset: 96333:99dcca3466d3 parent: 96331:9c0a00247021 parent: 96332:dfa0288c91fd user: Yury Selivanov date: Thu May 28 11:22:41 2015 -0400 summary: Issue 24017: Drop getawaitablefunc and friends in favor of unaryfunc. files: Doc/c-api/typeobj.rst | 12 ++++++------ Include/object.h | 9 +++------ Modules/_testcapimodule.c | 2 +- Objects/genobject.c | 2 +- Python/ceval.c | 4 ++-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1357,12 +1357,12 @@ Here is the structure definition:: typedef struct { - getawaitablefunc am_await; - getaiterfunc am_aiter; - aiternextfunc am_anext; + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; } PyAsyncMethods; -.. c:member:: getawaitablefunc PyAsyncMethods.am_await +.. c:member:: unaryfunc PyAsyncMethods.am_await The signature of this function is:: @@ -1373,7 +1373,7 @@ This slot may be set to *NULL* if an object is not an :term:`awaitable`. -.. c:member:: getaiterfunc PyAsyncMethods.am_aiter +.. c:member:: unaryfunc PyAsyncMethods.am_aiter The signature of this function is:: @@ -1384,7 +1384,7 @@ This slot may be set to *NULL* if an object does not implement asynchronous iteration protocol. -.. c:member:: aiternextfunc PyAsyncMethods.am_anext +.. c:member:: unaryfunc PyAsyncMethods.am_anext The signature of this function is:: diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -173,9 +173,6 @@ typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *); -typedef PyObject *(*getawaitablefunc) (PyObject *); -typedef PyObject *(*getaiterfunc) (PyObject *); -typedef PyObject *(*aiternextfunc) (PyObject *); #ifndef Py_LIMITED_API /* buffer interface */ @@ -305,9 +302,9 @@ } PyMappingMethods; typedef struct { - getawaitablefunc am_await; - getaiterfunc am_aiter; - aiternextfunc am_anext; + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; } PyAsyncMethods; typedef struct { diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3987,7 +3987,7 @@ } static PyAsyncMethods awaitType_as_async = { - (getawaitablefunc)awaitObject_await, /* am_await */ + (unaryfunc)awaitObject_await, /* am_await */ 0, /* am_aiter */ 0 /* am_anext */ }; diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -708,7 +708,7 @@ PyObject * _PyGen_GetAwaitableIter(PyObject *o) { - getawaitablefunc getter = NULL; + unaryfunc getter = NULL; PyTypeObject *ot; if (PyGen_CheckCoroutineExact(o)) { diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1927,7 +1927,7 @@ } TARGET(GET_AITER) { - getaiterfunc getter = NULL; + unaryfunc getter = NULL; PyObject *iter = NULL; PyObject *awaitable = NULL; PyObject *obj = TOP(); @@ -1974,7 +1974,7 @@ } TARGET(GET_ANEXT) { - aiternextfunc getter = NULL; + unaryfunc getter = NULL; PyObject *next_iter = NULL; PyObject *awaitable = NULL; PyObject *aiter = TOP(); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 19:29:15 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 28 May 2015 17:29:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixes_test_in_installer=2E?= Message-ID: <20150528172914.119118.47768@psf.io> https://hg.python.org/cpython/rev/cb11c602422f changeset: 96335:cb11c602422f parent: 96333:99dcca3466d3 parent: 96334:23c913269b40 user: Steve Dower date: Thu May 28 10:28:57 2015 -0700 summary: Fixes test in installer. files: Tools/msi/bundle/Default.wxl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -19,7 +19,7 @@ &Cancel &Close Install [WixBundleName] - Select to location to install Python, or choose Customize to enable or disable features. + Select Install Now to install Python with default settings, or choose Customize to enable or disable features. Version [WixBundleVersion] Are you sure you want to cancel? Previous version -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 19:29:15 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 28 May 2015 17:29:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixes_text_in_?= =?utf-8?q?installer=2E?= Message-ID: <20150528172914.125219.29122@psf.io> https://hg.python.org/cpython/rev/23c913269b40 changeset: 96334:23c913269b40 branch: 3.5 parent: 96332:dfa0288c91fd user: Steve Dower date: Thu May 28 10:28:40 2015 -0700 summary: Fixes text in installer. files: Tools/msi/bundle/Default.wxl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -19,7 +19,7 @@ &Cancel &Close Install [WixBundleName] - Select to location to install Python, or choose Customize to enable or disable features. + Select Install Now to install Python with default settings, or choose Customize to enable or disable features. Version [WixBundleVersion] Are you sure you want to cancel? Previous version -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 19:45:37 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 17:45:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_backport_compu?= =?utf-8?q?ted_gotos_=28=234753=29?= Message-ID: <20150528174536.125219.64592@psf.io> https://hg.python.org/cpython/rev/17d3bbde60d2 changeset: 96336:17d3bbde60d2 branch: 2.7 parent: 96322:581776726b61 user: Benjamin Peterson date: Thu May 28 12:45:31 2015 -0500 summary: backport computed gotos (#4753) files: Include/opcode.h | 9 + Makefile.pre.in | 15 + Misc/NEWS | 4 + Python/ceval.c | 961 ++++++++++++++++------- Python/makeopcodetargets.py | 45 + Python/opcode_targets.h | 258 ++++++ configure | 83 ++ configure.ac | 51 + pyconfig.h.in | 6 + 9 files changed, 1112 insertions(+), 320 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -37,12 +37,21 @@ #define SLICE 30 /* Also uses 31-33 */ +#define SLICE_1 31 +#define SLICE_2 32 +#define SLICE_3 33 #define STORE_SLICE 40 /* Also uses 41-43 */ +#define STORE_SLICE_1 41 +#define STORE_SLICE_2 42 +#define STORE_SLICE_3 43 #define DELETE_SLICE 50 /* Also uses 51-53 */ +#define DELETE_SLICE_1 51 +#define DELETE_SLICE_2 52 +#define DELETE_SLICE_3 53 #define STORE_MAP 54 #define INPLACE_ADD 55 diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -300,6 +300,16 @@ ########################################################################## # Python + +OPCODETARGETS_H= \ + $(srcdir)/Python/opcode_targets.h + +OPCODETARGETGEN= \ + $(srcdir)/Python/makeopcodetargets.py + +OPCODETARGETGEN_FILES= \ + $(OPCODETARGETGEN) $(srcdir)/Lib/opcode.py + PYTHON_OBJS= \ Python/_warnings.o \ Python/Python-ast.o \ @@ -671,6 +681,11 @@ Objects/stringobject.o: $(srcdir)/Objects/stringobject.c \ $(STRINGLIB_HEADERS) +$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES) + $(OPCODETARGETGEN) $(OPCODETARGETS_H) + +Python/ceval.o: $(OPCODETARGETS_H) + Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \ $(STRINGLIB_HEADERS) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #4753: On compilers where it is supported, use "computed gotos" for + bytecode dispatch in the interpreter. This improves interpretation + performance. + - Issue #22939: Fixed integer overflow in iterator object. Original patch by Clement Rouault. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -688,6 +688,100 @@ PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { +#ifdef DYNAMIC_EXECUTION_PROFILE + #undef USE_COMPUTED_GOTOS +#endif +#ifdef HAVE_COMPUTED_GOTOS + #ifndef USE_COMPUTED_GOTOS + #define USE_COMPUTED_GOTOS 1 + #endif +#else + #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS + #error "Computed gotos are not supported on this compiler." + #endif + #undef USE_COMPUTED_GOTOS + #define USE_COMPUTED_GOTOS 0 +#endif +#if USE_COMPUTED_GOTOS +/* Import the static jump table */ +#include "opcode_targets.h" + + /* This macro is used when several opcodes defer to the same implementation + (e.g. SETUP_LOOP, SETUP_FINALLY) */ +#define TARGET_WITH_IMPL(op, impl) \ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op: \ + goto impl; \ + +#define TARGET_WITH_IMPL_NOARG(op, impl) \ + TARGET_##op: \ + opcode = op; \ + case op: \ + goto impl; \ + +#define TARGET_NOARG(op) \ + TARGET_##op: \ + opcode = op; \ + case op:\ + +#define TARGET(op) \ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op:\ + + +#define DISPATCH() \ + { \ + int _tick = _Py_Ticker - 1; \ + _Py_Ticker = _tick; \ + if (_tick >= 0) { \ + FAST_DISPATCH(); \ + } \ + continue; \ + } + +#ifdef LLTRACE +#define FAST_DISPATCH() \ + { \ + if (!lltrace && !_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode; \ + } +#else +#define FAST_DISPATCH() { \ + if (!_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode;\ +} +#endif + +#else +#define TARGET(op) \ + case op: +#define TARGET_WITH_IMPL(op, impl) \ + /* silence compiler warnings about `impl` unused */ \ + if (0) goto impl; \ + case op:\ + +#define TARGET_NOARG(op) \ + case op:\ + +#define TARGET_WITH_IMPL_NOARG(op, impl) \ + if (0) goto impl; \ + case op:\ + +#define DISPATCH() continue +#define FAST_DISPATCH() goto fast_next_opcode +#endif + + #ifdef DXPAIRS int lastopcode = 0; #endif @@ -805,14 +899,23 @@ counter updates for both opcodes. */ + +// Next opcode prediction is also enabled for Computed Gotos as well. #ifdef DYNAMIC_EXECUTION_PROFILE -#define PREDICT(op) if (0) goto PRED_##op +#define PREDICT(op) //if (0) goto PRED_##op +#define PREDICTED(op) +#define PREDICTED_WITH_ARG(op) #else #define PREDICT(op) if (*next_instr == op) goto PRED_##op +#define PREDICTED(op) PRED_##op: next_instr++ +#ifdef USE_COMPUTED_GOTOS +#define PREDICTED_WITH_ARG(op) PRED_##op: next_instr++ +#else +#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 #endif - -#define PREDICTED(op) PRED_##op: next_instr++ -#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 +#endif + + /* Stack manipulation macros */ @@ -1108,55 +1211,70 @@ /* case STOP_CODE: this is an error! */ - case NOP: - goto fast_next_opcode; - - case LOAD_FAST: + TARGET_NOARG(NOP) + { + FAST_DISPATCH(); + } + + TARGET(LOAD_FAST) + { x = GETLOCAL(oparg); if (x != NULL) { Py_INCREF(x); PUSH(x); - goto fast_next_opcode; + FAST_DISPATCH(); } format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg)); break; - - case LOAD_CONST: + } + + TARGET(LOAD_CONST) + { x = GETITEM(consts, oparg); Py_INCREF(x); PUSH(x); - goto fast_next_opcode; + FAST_DISPATCH(); + } PREDICTED_WITH_ARG(STORE_FAST); - case STORE_FAST: + TARGET(STORE_FAST) + { v = POP(); SETLOCAL(oparg, v); - goto fast_next_opcode; - - case POP_TOP: + FAST_DISPATCH(); + } + + TARGET_NOARG(POP_TOP) + { v = POP(); Py_DECREF(v); - goto fast_next_opcode; - - case ROT_TWO: + FAST_DISPATCH(); + } + + TARGET_NOARG(ROT_TWO) + { v = TOP(); w = SECOND(); SET_TOP(w); SET_SECOND(v); - goto fast_next_opcode; - - case ROT_THREE: + FAST_DISPATCH(); + } + + TARGET_NOARG(ROT_THREE) + { v = TOP(); w = SECOND(); x = THIRD(); SET_TOP(w); SET_SECOND(x); SET_THIRD(v); - goto fast_next_opcode; - - case ROT_FOUR: + FAST_DISPATCH(); + } + + TARGET_NOARG(ROT_FOUR) + { u = TOP(); v = SECOND(); w = THIRD(); @@ -1165,15 +1283,21 @@ SET_SECOND(w); SET_THIRD(x); SET_FOURTH(u); - goto fast_next_opcode; - - case DUP_TOP: + FAST_DISPATCH(); + } + + + TARGET_NOARG(DUP_TOP) + { v = TOP(); Py_INCREF(v); PUSH(v); - goto fast_next_opcode; - - case DUP_TOPX: + FAST_DISPATCH(); + } + + + TARGET(DUP_TOPX) + { if (oparg == 2) { x = TOP(); Py_INCREF(x); @@ -1182,7 +1306,7 @@ STACKADJ(2); SET_TOP(x); SET_SECOND(w); - goto fast_next_opcode; + FAST_DISPATCH(); } else if (oparg == 3) { x = TOP(); Py_INCREF(x); @@ -1194,84 +1318,100 @@ SET_TOP(x); SET_SECOND(w); SET_THIRD(v); - goto fast_next_opcode; + FAST_DISPATCH(); } Py_FatalError("invalid argument to DUP_TOPX" " (bytecode corruption?)"); /* Never returns, so don't bother to set why. */ break; - - case UNARY_POSITIVE: + } + + TARGET_NOARG(UNARY_POSITIVE) + { v = TOP(); x = PyNumber_Positive(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case UNARY_NEGATIVE: + } + + TARGET_NOARG( UNARY_NEGATIVE) + { v = TOP(); x = PyNumber_Negative(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case UNARY_NOT: + } + + TARGET_NOARG(UNARY_NOT) + { v = TOP(); err = PyObject_IsTrue(v); Py_DECREF(v); if (err == 0) { Py_INCREF(Py_True); SET_TOP(Py_True); - continue; + DISPATCH(); } else if (err > 0) { Py_INCREF(Py_False); SET_TOP(Py_False); err = 0; - continue; + DISPATCH(); } STACKADJ(-1); break; - - case UNARY_CONVERT: + } + + TARGET_NOARG(UNARY_CONVERT) + { v = TOP(); x = PyObject_Repr(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case UNARY_INVERT: + } + + TARGET_NOARG(UNARY_INVERT) + { v = TOP(); x = PyNumber_Invert(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_POWER: + } + + TARGET_NOARG(BINARY_POWER) + { w = POP(); v = TOP(); x = PyNumber_Power(v, w, Py_None); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_MULTIPLY: + } + + TARGET_NOARG(BINARY_MULTIPLY) + { w = POP(); v = TOP(); x = PyNumber_Multiply(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if(x!=NULL) DISPATCH(); break; - - case BINARY_DIVIDE: + } + + TARGET_NOARG(BINARY_DIVIDE) + { if (!_Py_QnewFlag) { w = POP(); v = TOP(); @@ -1279,32 +1419,37 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; } - /* -Qnew is in effect: fall through to - BINARY_TRUE_DIVIDE */ - case BINARY_TRUE_DIVIDE: + } + /* -Qnew is in effect: fall through to BINARY_TRUE_DIVIDE */ + TARGET_NOARG(BINARY_TRUE_DIVIDE) + { w = POP(); v = TOP(); x = PyNumber_TrueDivide(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_FLOOR_DIVIDE: + } + + TARGET_NOARG(BINARY_FLOOR_DIVIDE) + { w = POP(); v = TOP(); x = PyNumber_FloorDivide(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_MODULO: + } + + TARGET_NOARG(BINARY_MODULO) + { w = POP(); v = TOP(); if (PyString_CheckExact(v)) @@ -1314,10 +1459,12 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_ADD: + } + + TARGET_NOARG(BINARY_ADD) + { w = POP(); v = TOP(); if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { @@ -1346,10 +1493,12 @@ skip_decref_vx: Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_SUBTRACT: + } + + TARGET_NOARG(BINARY_SUBTRACT) + { w = POP(); v = TOP(); if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { @@ -1371,10 +1520,12 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_SUBSCR: + } + + TARGET_NOARG(BINARY_SUBSCR) + { w = POP(); v = TOP(); if (PyList_CheckExact(v) && PyInt_CheckExact(w)) { @@ -1395,102 +1546,122 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_LSHIFT: + } + + TARGET_NOARG(BINARY_LSHIFT) + { w = POP(); v = TOP(); x = PyNumber_Lshift(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_RSHIFT: + } + + TARGET_NOARG(BINARY_RSHIFT) + { w = POP(); v = TOP(); x = PyNumber_Rshift(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_AND: + } + + TARGET_NOARG(BINARY_AND) + { w = POP(); v = TOP(); x = PyNumber_And(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_XOR: + } + + TARGET_NOARG(BINARY_XOR) + { w = POP(); v = TOP(); x = PyNumber_Xor(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case BINARY_OR: + } + + TARGET_NOARG(BINARY_OR) + { w = POP(); v = TOP(); x = PyNumber_Or(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case LIST_APPEND: + } + + TARGET(LIST_APPEND) + { w = POP(); v = PEEK(oparg); err = PyList_Append(v, w); Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - continue; + DISPATCH(); } break; - - case SET_ADD: + } + + TARGET(SET_ADD) + { w = POP(); v = stack_pointer[-oparg]; err = PySet_Add(v, w); Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - continue; + DISPATCH(); } break; - - case INPLACE_POWER: + } + + TARGET_NOARG(INPLACE_POWER) + { w = POP(); v = TOP(); x = PyNumber_InPlacePower(v, w, Py_None); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_MULTIPLY: + } + + TARGET_NOARG(INPLACE_MULTIPLY) + { w = POP(); v = TOP(); x = PyNumber_InPlaceMultiply(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_DIVIDE: + } + + TARGET_NOARG(INPLACE_DIVIDE) + { if (!_Py_QnewFlag) { w = POP(); v = TOP(); @@ -1498,42 +1669,50 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; } + } /* -Qnew is in effect: fall through to INPLACE_TRUE_DIVIDE */ - case INPLACE_TRUE_DIVIDE: + TARGET_NOARG(INPLACE_TRUE_DIVIDE) + { w = POP(); v = TOP(); x = PyNumber_InPlaceTrueDivide(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_FLOOR_DIVIDE: + } + + TARGET_NOARG(INPLACE_FLOOR_DIVIDE) + { w = POP(); v = TOP(); x = PyNumber_InPlaceFloorDivide(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_MODULO: + } + + TARGET_NOARG(INPLACE_MODULO) + { w = POP(); v = TOP(); x = PyNumber_InPlaceRemainder(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_ADD: + } + + TARGET_NOARG(INPLACE_ADD) + { w = POP(); v = TOP(); if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { @@ -1560,10 +1739,12 @@ skip_decref_v: Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_SUBTRACT: + } + + TARGET_NOARG(INPLACE_SUBTRACT) + { w = POP(); v = TOP(); if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { @@ -1583,63 +1764,78 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_LSHIFT: + } + + TARGET_NOARG(INPLACE_LSHIFT) + { w = POP(); v = TOP(); x = PyNumber_InPlaceLshift(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_RSHIFT: + } + + TARGET_NOARG(INPLACE_RSHIFT) + { w = POP(); v = TOP(); x = PyNumber_InPlaceRshift(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_AND: + } + + TARGET_NOARG(INPLACE_AND) + { w = POP(); v = TOP(); x = PyNumber_InPlaceAnd(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_XOR: + } + + TARGET_NOARG(INPLACE_XOR) + { w = POP(); v = TOP(); x = PyNumber_InPlaceXor(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case INPLACE_OR: + } + + TARGET_NOARG(INPLACE_OR) + { w = POP(); v = TOP(); x = PyNumber_InPlaceOr(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case SLICE+0: - case SLICE+1: - case SLICE+2: - case SLICE+3: + } + + + + TARGET_WITH_IMPL_NOARG(SLICE, _slice) + TARGET_WITH_IMPL_NOARG(SLICE_1, _slice) + TARGET_WITH_IMPL_NOARG(SLICE_2, _slice) + TARGET_WITH_IMPL_NOARG(SLICE_3, _slice) + _slice: + { if ((opcode-SLICE) & 2) w = POP(); else @@ -1654,13 +1850,17 @@ Py_XDECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case STORE_SLICE+0: - case STORE_SLICE+1: - case STORE_SLICE+2: - case STORE_SLICE+3: + } + + + TARGET_WITH_IMPL_NOARG(STORE_SLICE, _store_slice) + TARGET_WITH_IMPL_NOARG(STORE_SLICE_1, _store_slice) + TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice) + TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice) + _store_slice: + { if ((opcode-STORE_SLICE) & 2) w = POP(); else @@ -1676,13 +1876,17 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case DELETE_SLICE+0: - case DELETE_SLICE+1: - case DELETE_SLICE+2: - case DELETE_SLICE+3: + } + + + TARGET_WITH_IMPL_NOARG(DELETE_SLICE, _delete_slice) + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_1, _delete_slice) + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice) + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice) + _delete_slice: + { if ((opcode-DELETE_SLICE) & 2) w = POP(); else @@ -1697,10 +1901,12 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case STORE_SUBSCR: + } + + TARGET_NOARG(STORE_SUBSCR) + { w = TOP(); v = SECOND(); u = THIRD(); @@ -1710,10 +1916,12 @@ Py_DECREF(u); Py_DECREF(v); Py_DECREF(w); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case DELETE_SUBSCR: + } + + TARGET_NOARG(DELETE_SUBSCR) + { w = TOP(); v = SECOND(); STACKADJ(-2); @@ -1721,10 +1929,12 @@ err = PyObject_DelItem(v, w); Py_DECREF(v); Py_DECREF(w); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case PRINT_EXPR: + } + + TARGET_NOARG(PRINT_EXPR) + { v = POP(); w = PySys_GetObject("displayhook"); if (w == NULL) { @@ -1747,12 +1957,16 @@ Py_DECREF(v); Py_XDECREF(x); break; - - case PRINT_ITEM_TO: + } + + TARGET_NOARG(PRINT_ITEM_TO) + { w = stream = POP(); /* fall through to PRINT_ITEM */ - - case PRINT_ITEM: + } + + TARGET_NOARG(PRINT_ITEM) + { v = POP(); if (stream == NULL || stream == Py_None) { w = PySys_GetObject("stdout"); @@ -1798,16 +2012,20 @@ Py_DECREF(v); Py_XDECREF(stream); stream = NULL; - if (err == 0) - continue; + if (err == 0) DISPATCH(); break; - - case PRINT_NEWLINE_TO: + } + + TARGET_NOARG(PRINT_NEWLINE_TO) + { w = stream = POP(); /* fall through to PRINT_NEWLINE */ - - case PRINT_NEWLINE: - if (stream == NULL || stream == Py_None) { + } + + TARGET_NOARG(PRINT_NEWLINE) + { + if (stream == NULL || stream == Py_None) + { w = PySys_GetObject("stdout"); if (w == NULL) { PyErr_SetString(PyExc_RuntimeError, @@ -1827,12 +2045,14 @@ Py_XDECREF(stream); stream = NULL; break; - + } #ifdef CASE_TOO_BIG default: switch (opcode) { #endif - case RAISE_VARARGS: + + TARGET(RAISE_VARARGS) + { u = v = w = NULL; switch (oparg) { case 3: @@ -1853,28 +2073,37 @@ break; } break; - - case LOAD_LOCALS: - if ((x = f->f_locals) != NULL) { + } + + TARGET_NOARG(LOAD_LOCALS) + { + if ((x = f->f_locals) != NULL) + { Py_INCREF(x); PUSH(x); - continue; + DISPATCH(); } PyErr_SetString(PyExc_SystemError, "no locals"); break; - - case RETURN_VALUE: + } + + TARGET_NOARG(RETURN_VALUE) + { retval = POP(); why = WHY_RETURN; goto fast_block_end; - - case YIELD_VALUE: + } + + TARGET_NOARG(YIELD_VALUE) + { retval = POP(); f->f_stacktop = stack_pointer; why = WHY_YIELD; goto fast_yield; - - case EXEC_STMT: + } + + TARGET_NOARG(EXEC_STMT) + { w = TOP(); v = SECOND(); u = THIRD(); @@ -1886,8 +2115,10 @@ Py_DECREF(v); Py_DECREF(w); break; - - case POP_BLOCK: + } + + TARGET_NOARG(POP_BLOCK) + { { PyTryBlock *b = PyFrame_BlockPop(f); while (STACK_LEVEL() > b->b_level) { @@ -1895,10 +2126,12 @@ Py_DECREF(v); } } - continue; + DISPATCH(); + } PREDICTED(END_FINALLY); - case END_FINALLY: + TARGET_NOARG(END_FINALLY) + { v = POP(); if (PyInt_Check(v)) { why = (enum why_code) PyInt_AS_LONG(v); @@ -1922,8 +2155,10 @@ } Py_DECREF(v); break; - - case BUILD_CLASS: + } + + TARGET_NOARG(BUILD_CLASS) + { u = TOP(); v = SECOND(); w = THIRD(); @@ -1934,8 +2169,10 @@ Py_DECREF(v); Py_DECREF(w); break; - - case STORE_NAME: + } + + TARGET(STORE_NAME) + { w = GETITEM(names, oparg); v = POP(); if ((x = f->f_locals) != NULL) { @@ -1944,7 +2181,7 @@ else err = PyObject_SetItem(x, w, v); Py_DECREF(v); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; } t = PyObject_Repr(w); @@ -1955,8 +2192,10 @@ PyString_AS_STRING(t)); Py_DECREF(t); break; - - case DELETE_NAME: + } + + TARGET(DELETE_NAME) + { w = GETITEM(names, oparg); if ((x = f->f_locals) != NULL) { if ((err = PyObject_DelItem(x, w)) != 0) @@ -1973,9 +2212,11 @@ PyString_AS_STRING(w)); Py_DECREF(t); break; + } PREDICTED_WITH_ARG(UNPACK_SEQUENCE); - case UNPACK_SEQUENCE: + TARGET(UNPACK_SEQUENCE) + { v = POP(); if (PyTuple_CheckExact(v) && PyTuple_GET_SIZE(v) == oparg) { @@ -1987,7 +2228,7 @@ PUSH(w); } Py_DECREF(v); - continue; + DISPATCH(); } else if (PyList_CheckExact(v) && PyList_GET_SIZE(v) == oparg) { PyObject **items = \ @@ -2006,8 +2247,11 @@ } Py_DECREF(v); break; - - case STORE_ATTR: + } + + + TARGET(STORE_ATTR) + { w = GETITEM(names, oparg); v = TOP(); u = SECOND(); @@ -2015,33 +2259,42 @@ err = PyObject_SetAttr(v, w, u); /* v.w = u */ Py_DECREF(v); Py_DECREF(u); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case DELETE_ATTR: + } + + TARGET(DELETE_ATTR) + { w = GETITEM(names, oparg); v = POP(); err = PyObject_SetAttr(v, w, (PyObject *)NULL); /* del v.w */ Py_DECREF(v); break; - - case STORE_GLOBAL: + } + + + TARGET(STORE_GLOBAL) + { w = GETITEM(names, oparg); v = POP(); err = PyDict_SetItem(f->f_globals, w, v); Py_DECREF(v); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case DELETE_GLOBAL: + } + + TARGET(DELETE_GLOBAL) + { w = GETITEM(names, oparg); if ((err = PyDict_DelItem(f->f_globals, w)) != 0) format_exc_check_arg( PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w); break; - - case LOAD_NAME: + } + + TARGET(LOAD_NAME) + { w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { why = WHY_EXCEPTION; @@ -2081,9 +2334,11 @@ Py_INCREF(x); } PUSH(x); - continue; - - case LOAD_GLOBAL: + DISPATCH(); + } + + TARGET(LOAD_GLOBAL) + { w = GETITEM(names, oparg); if (PyString_CheckExact(w)) { /* Inline the PyDict_GetItem() calls. @@ -2103,7 +2358,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - continue; + DISPATCH(); } d = (PyDictObject *)(f->f_builtins); e = d->ma_lookup(d, w, hash); @@ -2115,7 +2370,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - continue; + DISPATCH(); } goto load_global_error; } @@ -2134,13 +2389,15 @@ } Py_INCREF(x); PUSH(x); - continue; - - case DELETE_FAST: + DISPATCH(); + } + + TARGET(DELETE_FAST) + { x = GETLOCAL(oparg); if (x != NULL) { SETLOCAL(oparg, NULL); - continue; + DISPATCH(); } format_exc_check_arg( PyExc_UnboundLocalError, @@ -2148,20 +2405,24 @@ PyTuple_GetItem(co->co_varnames, oparg) ); break; - - case LOAD_CLOSURE: + } + + TARGET(LOAD_CLOSURE) + { x = freevars[oparg]; Py_INCREF(x); PUSH(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case LOAD_DEREF: + } + + TARGET(LOAD_DEREF) + { x = freevars[oparg]; w = PyCell_Get(x); if (w != NULL) { PUSH(w); - continue; + DISPATCH(); } err = -1; /* Don't stomp existing exception */ @@ -2181,15 +2442,19 @@ UNBOUNDFREE_ERROR_MSG, v); } break; - - case STORE_DEREF: + } + + TARGET(STORE_DEREF) + { w = POP(); x = freevars[oparg]; PyCell_Set(x, w); Py_DECREF(w); - continue; - - case BUILD_TUPLE: + DISPATCH(); + } + + TARGET(BUILD_TUPLE) + { x = PyTuple_New(oparg); if (x != NULL) { for (; --oparg >= 0;) { @@ -2197,11 +2462,13 @@ PyTuple_SET_ITEM(x, oparg, w); } PUSH(x); - continue; + DISPATCH(); } break; - - case BUILD_LIST: + } + + TARGET(BUILD_LIST) + { x = PyList_New(oparg); if (x != NULL) { for (; --oparg >= 0;) { @@ -2209,11 +2476,13 @@ PyList_SET_ITEM(x, oparg, w); } PUSH(x); - continue; + DISPATCH(); } break; - - case BUILD_SET: + } + + TARGET(BUILD_SET) + { x = PySet_New(NULL); if (x != NULL) { for (; --oparg >= 0;) { @@ -2227,18 +2496,21 @@ break; } PUSH(x); - continue; + DISPATCH(); } break; - - - case BUILD_MAP: + } + + TARGET(BUILD_MAP) + { x = _PyDict_NewPresized((Py_ssize_t)oparg); PUSH(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case STORE_MAP: + } + + TARGET_NOARG(STORE_MAP) + { w = TOP(); /* key */ u = SECOND(); /* value */ v = THIRD(); /* dict */ @@ -2247,10 +2519,12 @@ err = PyDict_SetItem(v, w, u); /* v[w] = u */ Py_DECREF(u); Py_DECREF(w); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case MAP_ADD: + } + + TARGET(MAP_ADD) + { w = TOP(); /* key */ u = SECOND(); /* value */ STACKADJ(-2); @@ -2261,20 +2535,24 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - continue; + DISPATCH(); } break; - - case LOAD_ATTR: + } + + TARGET(LOAD_ATTR) + { w = GETITEM(names, oparg); v = TOP(); x = PyObject_GetAttr(v, w); Py_DECREF(v); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case COMPARE_OP: + } + + TARGET(COMPARE_OP) + { w = POP(); v = TOP(); if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) { @@ -2307,9 +2585,11 @@ if (x == NULL) break; PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - continue; - - case IMPORT_NAME: + DISPATCH(); + } + + TARGET(IMPORT_NAME) + { w = GETITEM(names, oparg); x = PyDict_GetItemString(f->f_builtins, "__import__"); if (x == NULL) { @@ -2350,10 +2630,12 @@ READ_TIMESTAMP(intr1); Py_DECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case IMPORT_STAR: + } + + TARGET_NOARG(IMPORT_STAR) + { v = POP(); PyFrame_FastToLocals(f); if ((x = f->f_locals) == NULL) { @@ -2366,34 +2648,40 @@ READ_TIMESTAMP(intr1); PyFrame_LocalsToFast(f, 0); Py_DECREF(v); - if (err == 0) continue; + if (err == 0) DISPATCH(); break; - - case IMPORT_FROM: + } + + TARGET(IMPORT_FROM) + { w = GETITEM(names, oparg); v = TOP(); READ_TIMESTAMP(intr0); x = import_from(v, w); READ_TIMESTAMP(intr1); PUSH(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case JUMP_FORWARD: + } + + TARGET(JUMP_FORWARD) + { JUMPBY(oparg); - goto fast_next_opcode; + FAST_DISPATCH(); + } PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); - case POP_JUMP_IF_FALSE: + TARGET(POP_JUMP_IF_FALSE) + { w = POP(); if (w == Py_True) { Py_DECREF(w); - goto fast_next_opcode; + FAST_DISPATCH(); } if (w == Py_False) { Py_DECREF(w); JUMPTO(oparg); - goto fast_next_opcode; + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2403,19 +2691,21 @@ JUMPTO(oparg); else break; - continue; + DISPATCH(); + } PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); - case POP_JUMP_IF_TRUE: + TARGET(POP_JUMP_IF_TRUE) + { w = POP(); if (w == Py_False) { Py_DECREF(w); - goto fast_next_opcode; + FAST_DISPATCH(); } if (w == Py_True) { Py_DECREF(w); JUMPTO(oparg); - goto fast_next_opcode; + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2427,18 +2717,20 @@ ; else break; - continue; - - case JUMP_IF_FALSE_OR_POP: + DISPATCH(); + } + + TARGET(JUMP_IF_FALSE_OR_POP) + { w = TOP(); if (w == Py_True) { STACKADJ(-1); Py_DECREF(w); - goto fast_next_opcode; + FAST_DISPATCH(); } if (w == Py_False) { JUMPTO(oparg); - goto fast_next_opcode; + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2450,18 +2742,20 @@ JUMPTO(oparg); else break; - continue; - - case JUMP_IF_TRUE_OR_POP: + DISPATCH(); + } + + TARGET(JUMP_IF_TRUE_OR_POP) + { w = TOP(); if (w == Py_False) { STACKADJ(-1); Py_DECREF(w); - goto fast_next_opcode; + FAST_DISPATCH(); } if (w == Py_True) { JUMPTO(oparg); - goto fast_next_opcode; + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2474,10 +2768,12 @@ } else break; - continue; + DISPATCH(); + } PREDICTED_WITH_ARG(JUMP_ABSOLUTE); - case JUMP_ABSOLUTE: + TARGET(JUMP_ABSOLUTE) + { JUMPTO(oparg); #if FAST_LOOPS /* Enabling this path speeds-up all while and for-loops by bypassing @@ -2489,10 +2785,12 @@ */ goto fast_next_opcode; #else - continue; + DISPATCH(); #endif - - case GET_ITER: + } + + TARGET_NOARG(GET_ITER) + { /* before: [obj]; after [getiter(obj)] */ v = TOP(); x = PyObject_GetIter(v); @@ -2500,13 +2798,15 @@ if (x != NULL) { SET_TOP(x); PREDICT(FOR_ITER); - continue; + DISPATCH(); } STACKADJ(-1); break; + } PREDICTED_WITH_ARG(FOR_ITER); - case FOR_ITER: + TARGET(FOR_ITER) + { /* before: [iter]; after: [iter, iter()] *or* [] */ v = TOP(); x = (*v->ob_type->tp_iternext)(v); @@ -2514,7 +2814,7 @@ PUSH(x); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); - continue; + DISPATCH(); } if (PyErr_Occurred()) { if (!PyErr_ExceptionMatches( @@ -2526,13 +2826,17 @@ x = v = POP(); Py_DECREF(v); JUMPBY(oparg); - continue; - - case BREAK_LOOP: + DISPATCH(); + } + + TARGET_NOARG(BREAK_LOOP) + { why = WHY_BREAK; goto fast_block_end; - - case CONTINUE_LOOP: + } + + TARGET(CONTINUE_LOOP) + { retval = PyInt_FromLong(oparg); if (!retval) { x = NULL; @@ -2540,10 +2844,13 @@ } why = WHY_CONTINUE; goto fast_block_end; - - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: + } + + TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) + TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) + TARGET(SETUP_FINALLY) + _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. @@ -2551,9 +2858,13 @@ PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); - continue; - - case SETUP_WITH: + DISPATCH(); + } + + + + TARGET(SETUP_WITH) + { { static PyObject *exit, *enter; w = TOP(); @@ -2579,10 +2890,11 @@ STACK_LEVEL()); PUSH(x); - continue; + DISPATCH(); + } } - case WITH_CLEANUP: + TARGET_NOARG(WITH_CLEANUP) { /* At the top of the stack are 1-3 values indicating how/why we entered the finally clause: @@ -2670,7 +2982,7 @@ break; } - case CALL_FUNCTION: + TARGET(CALL_FUNCTION) { PyObject **sp; PCALL(PCALL_ALL); @@ -2682,14 +2994,14 @@ #endif stack_pointer = sp; PUSH(x); - if (x != NULL) - continue; + if (x != NULL) DISPATCH(); break; } - case CALL_FUNCTION_VAR: - case CALL_FUNCTION_KW: - case CALL_FUNCTION_VAR_KW: + TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) + TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) + TARGET(CALL_FUNCTION_VAR_KW) + _call_function_var_kw: { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; @@ -2727,12 +3039,13 @@ Py_DECREF(w); } PUSH(x); - if (x != NULL) - continue; + if (x != NULL) DISPATCH(); break; } - case MAKE_FUNCTION: + + TARGET(MAKE_FUNCTION) + { v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); Py_DECREF(v); @@ -2753,8 +3066,9 @@ } PUSH(x); break; - - case MAKE_CLOSURE: + } + + TARGET(MAKE_CLOSURE) { v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); @@ -2789,7 +3103,8 @@ break; } - case BUILD_SLICE: + TARGET(BUILD_SLICE) + { if (oparg == 3) w = POP(); else @@ -2801,14 +3116,20 @@ Py_DECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) continue; + if (x != NULL) DISPATCH(); break; - - case EXTENDED_ARG: + } + + TARGET(EXTENDED_ARG) + { opcode = NEXTOP(); oparg = oparg<<16 | NEXTARG(); goto dispatch_opcode; - + } + +#if USE_COMPUTED_GOTOS + _unknown_opcode: +#endif default: fprintf(stderr, "XXX lineno: %d, opcode: %d\n", diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py new file mode 100755 --- /dev/null +++ b/Python/makeopcodetargets.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python +"""Generate C code for the jump table of the threaded code interpreter +(for compilers supporting computed gotos or "labels-as-values", such as gcc). +""" + +# This code should stay compatible with Python 2.3, at least while +# some of the buildbots have Python 2.3 as their system Python. + +import imp +import os + + +def find_module(modname): + """Finds and returns a module in the local dist/checkout. + """ + modpath = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "Lib") + return imp.load_module(modname, *imp.find_module(modname, [modpath])) + +def write_contents(f): + """Write C code contents to the target file object. + """ + opcode = find_module("opcode") + targets = ['_unknown_opcode'] * 256 + for opname, op in opcode.opmap.items(): + if opname == "STOP_CODE": + continue + targets[op] = "TARGET_%s" % opname.replace("+0", " ").replace("+", "_") + f.write("static void *opcode_targets[256] = {\n") + f.write(",\n".join([" &&%s" % s for s in targets])) + f.write("\n};\n") + + +if __name__ == "__main__": + import sys + assert len(sys.argv) < 3, "Too many arguments" + if len(sys.argv) == 2: + target = sys.argv[1] + else: + target = "Python/opcode_targets.h" + f = open(target, "w") + try: + write_contents(f) + finally: + f.close() diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h new file mode 100644 --- /dev/null +++ b/Python/opcode_targets.h @@ -0,0 +1,258 @@ +static void *opcode_targets[256] = { + &&_unknown_opcode, + &&TARGET_POP_TOP, + &&TARGET_ROT_TWO, + &&TARGET_ROT_THREE, + &&TARGET_DUP_TOP, + &&TARGET_ROT_FOUR, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_NOP, + &&TARGET_UNARY_POSITIVE, + &&TARGET_UNARY_NEGATIVE, + &&TARGET_UNARY_NOT, + &&TARGET_UNARY_CONVERT, + &&_unknown_opcode, + &&TARGET_UNARY_INVERT, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_BINARY_POWER, + &&TARGET_BINARY_MULTIPLY, + &&TARGET_BINARY_DIVIDE, + &&TARGET_BINARY_MODULO, + &&TARGET_BINARY_ADD, + &&TARGET_BINARY_SUBTRACT, + &&TARGET_BINARY_SUBSCR, + &&TARGET_BINARY_FLOOR_DIVIDE, + &&TARGET_BINARY_TRUE_DIVIDE, + &&TARGET_INPLACE_FLOOR_DIVIDE, + &&TARGET_INPLACE_TRUE_DIVIDE, + &&TARGET_SLICE , + &&TARGET_SLICE_1, + &&TARGET_SLICE_2, + &&TARGET_SLICE_3, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_STORE_SLICE , + &&TARGET_STORE_SLICE_1, + &&TARGET_STORE_SLICE_2, + &&TARGET_STORE_SLICE_3, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_DELETE_SLICE , + &&TARGET_DELETE_SLICE_1, + &&TARGET_DELETE_SLICE_2, + &&TARGET_DELETE_SLICE_3, + &&TARGET_STORE_MAP, + &&TARGET_INPLACE_ADD, + &&TARGET_INPLACE_SUBTRACT, + &&TARGET_INPLACE_MULTIPLY, + &&TARGET_INPLACE_DIVIDE, + &&TARGET_INPLACE_MODULO, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, + &&TARGET_BINARY_LSHIFT, + &&TARGET_BINARY_RSHIFT, + &&TARGET_BINARY_AND, + &&TARGET_BINARY_XOR, + &&TARGET_BINARY_OR, + &&TARGET_INPLACE_POWER, + &&TARGET_GET_ITER, + &&_unknown_opcode, + &&TARGET_PRINT_EXPR, + &&TARGET_PRINT_ITEM, + &&TARGET_PRINT_NEWLINE, + &&TARGET_PRINT_ITEM_TO, + &&TARGET_PRINT_NEWLINE_TO, + &&TARGET_INPLACE_LSHIFT, + &&TARGET_INPLACE_RSHIFT, + &&TARGET_INPLACE_AND, + &&TARGET_INPLACE_XOR, + &&TARGET_INPLACE_OR, + &&TARGET_BREAK_LOOP, + &&TARGET_WITH_CLEANUP, + &&TARGET_LOAD_LOCALS, + &&TARGET_RETURN_VALUE, + &&TARGET_IMPORT_STAR, + &&TARGET_EXEC_STMT, + &&TARGET_YIELD_VALUE, + &&TARGET_POP_BLOCK, + &&TARGET_END_FINALLY, + &&TARGET_BUILD_CLASS, + &&TARGET_STORE_NAME, + &&TARGET_DELETE_NAME, + &&TARGET_UNPACK_SEQUENCE, + &&TARGET_FOR_ITER, + &&TARGET_LIST_APPEND, + &&TARGET_STORE_ATTR, + &&TARGET_DELETE_ATTR, + &&TARGET_STORE_GLOBAL, + &&TARGET_DELETE_GLOBAL, + &&TARGET_DUP_TOPX, + &&TARGET_LOAD_CONST, + &&TARGET_LOAD_NAME, + &&TARGET_BUILD_TUPLE, + &&TARGET_BUILD_LIST, + &&TARGET_BUILD_SET, + &&TARGET_BUILD_MAP, + &&TARGET_LOAD_ATTR, + &&TARGET_COMPARE_OP, + &&TARGET_IMPORT_NAME, + &&TARGET_IMPORT_FROM, + &&TARGET_JUMP_FORWARD, + &&TARGET_JUMP_IF_FALSE_OR_POP, + &&TARGET_JUMP_IF_TRUE_OR_POP, + &&TARGET_JUMP_ABSOLUTE, + &&TARGET_POP_JUMP_IF_FALSE, + &&TARGET_POP_JUMP_IF_TRUE, + &&TARGET_LOAD_GLOBAL, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_CONTINUE_LOOP, + &&TARGET_SETUP_LOOP, + &&TARGET_SETUP_EXCEPT, + &&TARGET_SETUP_FINALLY, + &&_unknown_opcode, + &&TARGET_LOAD_FAST, + &&TARGET_STORE_FAST, + &&TARGET_DELETE_FAST, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_RAISE_VARARGS, + &&TARGET_CALL_FUNCTION, + &&TARGET_MAKE_FUNCTION, + &&TARGET_BUILD_SLICE, + &&TARGET_MAKE_CLOSURE, + &&TARGET_LOAD_CLOSURE, + &&TARGET_LOAD_DEREF, + &&TARGET_STORE_DEREF, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_CALL_FUNCTION_VAR, + &&TARGET_CALL_FUNCTION_KW, + &&TARGET_CALL_FUNCTION_VAR_KW, + &&TARGET_SETUP_WITH, + &&_unknown_opcode, + &&TARGET_EXTENDED_ARG, + &&TARGET_SET_ADD, + &&TARGET_MAP_ADD, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode +}; diff --git a/configure b/configure --- a/configure +++ b/configure @@ -811,6 +811,7 @@ with_libc enable_big_digits enable_unicode +with_computed_gotos with_ensurepip ' ac_precious_vars='build_alias @@ -1494,6 +1495,9 @@ --with-fpectl enable SIGFPE catching --with-libm=STRING math library --with-libc=STRING C library + --with(out)-computed-gotos + Use computed gotos in evaluation loop (enabled by + default on supported compilers) --with(out)-ensurepip=[=OPTION] "install" or "upgrade" using bundled pip, default is "no" @@ -14685,6 +14689,85 @@ mkdir $dir fi done + +# BEGIN_COMPUTED_GOTO +# Check for --with-computed-gotos +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-computed-gotos" >&5 +$as_echo_n "checking for --with-computed-gotos... " >&6; } + +# Check whether --with-computed-gotos was given. +if test "${with_computed_gotos+set}" = set; then : + withval=$with_computed_gotos; +if test "$withval" = yes +then + +$as_echo "#define USE_COMPUTED_GOTOS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +if test "$withval" = no +then + +$as_echo "#define USE_COMPUTED_GOTOS 0" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no value specified" >&5 +$as_echo "no value specified" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports computed gotos" >&5 +$as_echo_n "checking whether $CC supports computed gotos... " >&6; } +if ${ac_cv_computed_gotos+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + if test "${with_computed_gotos+set}" = set; then + ac_cv_computed_gotos="$with_computed_gotos -- configured --with(out)-computed-gotos" + else + ac_cv_computed_gotos=no + fi +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int main(int argc, char **argv) +{ + static void *targets[1] = { &&LABEL1 }; + goto LABEL2; +LABEL1: + return 0; +LABEL2: + goto *targets[0]; + return 1; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_computed_gotos=yes +else + ac_cv_computed_gotos=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_computed_gotos" >&5 +$as_echo "$ac_cv_computed_gotos" >&6; } +case "$ac_cv_computed_gotos" in yes*) + +$as_echo "#define HAVE_COMPUTED_GOTOS 1" >>confdefs.h + +esac +# END_COMPUTED_GOTO + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -4557,6 +4557,57 @@ mkdir $dir fi done + +# BEGIN_COMPUTED_GOTO +# Check for --with-computed-gotos +AC_MSG_CHECKING(for --with-computed-gotos) +AC_ARG_WITH(computed-gotos, + AS_HELP_STRING([--with(out)-computed-gotos], + [Use computed gotos in evaluation loop (enabled by default on supported compilers)]), +[ +if test "$withval" = yes +then + AC_DEFINE(USE_COMPUTED_GOTOS, 1, + [Define if you want to use computed gotos in ceval.c.]) + AC_MSG_RESULT(yes) +fi +if test "$withval" = no +then + AC_DEFINE(USE_COMPUTED_GOTOS, 0, + [Define if you want to use computed gotos in ceval.c.]) + AC_MSG_RESULT(no) +fi +], +[AC_MSG_RESULT(no value specified)]) + +AC_MSG_CHECKING(whether $CC supports computed gotos) +AC_CACHE_VAL(ac_cv_computed_gotos, +AC_RUN_IFELSE([AC_LANG_SOURCE([[[ +int main(int argc, char **argv) +{ + static void *targets[1] = { &&LABEL1 }; + goto LABEL2; +LABEL1: + return 0; +LABEL2: + goto *targets[0]; + return 1; +} +]]])], +[ac_cv_computed_gotos=yes], +[ac_cv_computed_gotos=no], +[if test "${with_computed_gotos+set}" = set; then + ac_cv_computed_gotos="$with_computed_gotos -- configured --with(out)-computed-gotos" + else + ac_cv_computed_gotos=no + fi])) +AC_MSG_RESULT($ac_cv_computed_gotos) +case "$ac_cv_computed_gotos" in yes*) + AC_DEFINE(HAVE_COMPUTED_GOTOS, 1, + [Define if the C compiler supports computed gotos.]) +esac +# END_COMPUTED_GOTO + AC_MSG_RESULT(done) # ensurepip option diff --git a/pyconfig.h.in b/pyconfig.h.in --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -118,6 +118,9 @@ /* Define to 1 if you have the `clock' function. */ #undef HAVE_CLOCK +/* Define if the C compiler supports computed gotos. */ +#undef HAVE_COMPUTED_GOTOS + /* Define to 1 if you have the `confstr' function. */ #undef HAVE_CONFSTR @@ -1069,6 +1072,9 @@ /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME +/* Define if you want to use computed gotos in ceval.c. */ +#undef USE_COMPUTED_GOTOS + /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 19:45:50 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 28 May 2015 17:45:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324309=3A_Removed_?= =?utf-8?q?Python_2_idioms=2E?= Message-ID: <20150528174550.125217.38501@psf.io> https://hg.python.org/cpython/rev/678a76610723 changeset: 96337:678a76610723 parent: 96335:cb11c602422f user: Serhiy Storchaka date: Thu May 28 20:45:29 2015 +0300 summary: Issue #24309: Removed Python 2 idioms. files: Lib/string.py | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Lib/string.py b/Lib/string.py --- a/Lib/string.py +++ b/Lib/string.py @@ -112,10 +112,7 @@ # Check the most common path first. named = mo.group('named') or mo.group('braced') if named is not None: - val = mapping[named] - # We use this idiom instead of str() because the latter will - # fail if val is a Unicode containing non-ASCII characters. - return '%s' % (val,) + return str(mapping[named]) if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: @@ -142,9 +139,7 @@ named = mo.group('named') or mo.group('braced') if named is not None: try: - # We use this idiom instead of str() because the latter - # will fail if val is a Unicode containing non-ASCII - return '%s' % (mapping[named],) + return str(mapping[named]) except KeyError: return mo.group() if mo.group('escaped') is not None: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 20:06:18 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 18:06:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_24297=3A_Add_a_unitt?= =?utf-8?q?est_that_Lib/symbol=2Epy_is_in_sync_with_Grammar?= Message-ID: <20150528180617.17495.47593@psf.io> https://hg.python.org/cpython/rev/a95d0dd3c2b1 changeset: 96338:a95d0dd3c2b1 user: Yury Selivanov date: Thu May 28 14:06:12 2015 -0400 summary: Issue 24297: Add a unittest that Lib/symbol.py is in sync with Grammar files: Lib/test/test_symbol.py | 45 +++++++++++++++++++++++++++++ 1 files changed, 45 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_symbol.py b/Lib/test/test_symbol.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_symbol.py @@ -0,0 +1,45 @@ +import unittest +from test import support +import filecmp +import os +import sys +import subprocess + + +SYMBOL_FILE = support.findfile('symbol.py') +GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), + '..', '..', 'Include', 'graminit.h') +TEST_PY_FILE = 'symbol_test.py' + + +class TestSymbolGeneration(unittest.TestCase): + + def _copy_file_without_generated_symbols(self, source_file, dest_file): + with open(source_file, 'rb') as fp: + lines = fp.readlines() + nl = lines[0][len(lines[0].rstrip()):] + with open(dest_file, 'wb') as fp: + fp.writelines(lines[:lines.index(b"#--start constants--" + nl) + 1]) + fp.writelines(lines[lines.index(b"#--end constants--" + nl):]) + + def _generate_symbols(self, grammar_file, target_symbol_py_file): + proc = subprocess.Popen([sys.executable, + SYMBOL_FILE, + grammar_file, + target_symbol_py_file], stderr=subprocess.PIPE) + stderr = proc.communicate()[1] + return proc.returncode, stderr + + @unittest.skipIf(not os.path.exists(GRAMMAR_FILE), + 'test only works from source build directory') + def test_real_grammar_and_symbol_file(self): + self._copy_file_without_generated_symbols(SYMBOL_FILE, TEST_PY_FILE) + self.addCleanup(support.unlink, TEST_PY_FILE) + self.assertFalse(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) + self.assertEqual((0, b''), self._generate_symbols(GRAMMAR_FILE, + TEST_PY_FILE)) + self.assertTrue(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) + + +if __name__ == "__main__": + unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 21:31:25 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 19:31:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_in_dict_displa?= =?utf-8?q?ys=2C_evaluate_the_key_before_the_value_=28closes_=2311205=29?= Message-ID: <20150528193125.4352.95254@psf.io> https://hg.python.org/cpython/rev/6f05f83c7010 changeset: 96339:6f05f83c7010 branch: 3.5 parent: 96334:23c913269b40 user: Benjamin Peterson date: Thu May 28 14:30:26 2015 -0500 summary: in dict displays, evaluate the key before the value (closes #11205) Patch partially by Steve Dougherty. files: Lib/importlib/_bootstrap_external.py | 3 +- Lib/test/test_compile.py | 11 + Misc/NEWS | 2 + Python/ceval.c | 4 +- Python/compile.c | 4 +- Python/importlib_external.h | 216 +++++++------- 6 files changed, 127 insertions(+), 113 deletions(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -221,12 +221,13 @@ # 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.5b2 3340 (fix dictionary display evaluation order #11205) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). -MAGIC_NUMBER = (3330).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3340).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -461,6 +461,17 @@ ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '', 'exec') + def test_dict_evaluation_order(self): + i = 0 + + def f(): + nonlocal i + i += 1 + return i + + d = {f(): f(), f(): f()} + self.assertEqual(d, {1: 2, 3: 4}) + @support.cpython_only def test_same_filename_used(self): s = """def f(): pass\ndef g(): pass""" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #11205: In dictionary displays, evaluate the key before the value. + - Issue #24285: Fixed regression that prevented importing extension modules from inside packages. Patch by Petr Viktorin. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2584,8 +2584,8 @@ goto error; while (--oparg >= 0) { int err; - PyObject *key = TOP(); - PyObject *value = SECOND(); + PyObject *value = TOP(); + PyObject *key = SECOND(); STACKADJ(-2); err = PyDict_SetItem(map, key, value); Py_DECREF(value); diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -3138,8 +3138,8 @@ containers++; } else { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); elements++; } } @@ -3287,8 +3287,8 @@ } else if (nsubkwargs) { /* A keyword argument and we already have a dict. */ + ADDOP_O(c, LOAD_CONST, kw->arg, consts); VISIT(c, expr, kw->value); - ADDOP_O(c, LOAD_CONST, kw->arg, consts); nseen++; } else { diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -259,7 +259,7 @@ 0,0,114,5,0,0,0,218,13,95,119,114,105,116,101,95, 97,116,111,109,105,99,99,0,0,0,115,26,0,0,0,0, 5,24,1,9,1,33,1,3,3,21,1,20,1,20,1,13, - 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,2, + 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,12, 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, @@ -369,7 +369,7 @@ 116,97,103,90,15,97,108,109,111,115,116,95,102,105,108,101, 110,97,109,101,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,17,99,97,99,104,101,95,102,114,111,109,95, - 115,111,117,114,99,101,241,0,0,0,115,46,0,0,0,0, + 115,111,117,114,99,101,242,0,0,0,115,46,0,0,0,0, 18,12,1,9,1,7,1,12,1,6,1,12,1,18,1,18, 1,24,1,12,1,12,1,12,1,36,1,12,1,18,1,9, 2,12,1,12,1,12,1,12,1,21,1,21,1,114,79,0, @@ -448,7 +448,7 @@ 95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108, 101,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111, - 109,95,99,97,99,104,101,29,1,0,0,115,44,0,0,0, + 109,95,99,97,99,104,101,30,1,0,0,115,44,0,0,0, 0,9,18,1,12,1,18,1,18,1,12,1,9,1,15,1, 15,1,12,1,9,1,15,1,12,1,22,1,15,1,9,1, 12,1,22,1,12,1,9,1,12,1,19,1,114,85,0,0, @@ -486,7 +486,7 @@ 115,105,111,110,218,11,115,111,117,114,99,101,95,112,97,116, 104,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108, - 101,62,1,0,0,115,20,0,0,0,0,7,18,1,4,1, + 101,63,1,0,0,115,20,0,0,0,0,7,18,1,4,1, 24,1,35,1,4,1,3,1,16,1,19,1,21,1,114,91, 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, 11,0,0,0,67,0,0,0,115,92,0,0,0,124,0,0, @@ -500,7 +500,7 @@ 84,0,0,0,114,79,0,0,0,114,66,0,0,0,114,74, 0,0,0,41,1,218,8,102,105,108,101,110,97,109,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, - 95,103,101,116,95,99,97,99,104,101,100,81,1,0,0,115, + 95,103,101,116,95,99,97,99,104,101,100,82,1,0,0,115, 16,0,0,0,0,1,21,1,3,1,14,1,13,1,8,1, 21,1,4,2,114,95,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,60, @@ -515,7 +515,7 @@ 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,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,99, - 97,108,99,95,109,111,100,101,93,1,0,0,115,12,0,0, + 97,108,99,95,109,111,100,101,94,1,0,0,115,12,0,0, 0,0,2,3,1,19,1,13,1,11,3,10,1,114,97,0, 0,0,218,9,118,101,114,98,111,115,105,116,121,114,29,0, 0,0,99,1,0,0,0,1,0,0,0,3,0,0,0,4, @@ -536,7 +536,7 @@ 218,6,115,116,100,101,114,114,41,3,114,75,0,0,0,114, 98,0,0,0,218,4,97,114,103,115,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,16,95,118,101,114,98, - 111,115,101,95,109,101,115,115,97,103,101,105,1,0,0,115, + 111,115,101,95,109,101,115,115,97,103,101,106,1,0,0,115, 8,0,0,0,0,2,18,1,15,1,10,1,114,105,0,0, 0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0, 0,0,3,0,0,0,115,84,0,0,0,100,1,0,135,0, @@ -576,7 +576,7 @@ 0,0,90,6,107,119,97,114,103,115,41,1,218,6,109,101, 116,104,111,100,114,4,0,0,0,114,5,0,0,0,218,19, 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, - 112,101,114,121,1,0,0,115,12,0,0,0,0,1,12,1, + 112,101,114,122,1,0,0,115,12,0,0,0,0,1,12,1, 12,1,15,1,6,1,25,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, @@ -595,7 +595,7 @@ 116,97,116,116,114,218,8,95,95,100,105,99,116,95,95,218, 6,117,112,100,97,116,101,41,3,90,3,110,101,119,90,3, 111,108,100,114,52,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,5,95,119,114,97,112,132,1, + 0,0,114,5,0,0,0,218,5,95,119,114,97,112,133,1, 0,0,115,8,0,0,0,0,1,25,1,15,1,29,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,3,218,10,95, @@ -603,7 +603,7 @@ 78,97,109,101,69,114,114,111,114,41,3,114,109,0,0,0, 114,110,0,0,0,114,120,0,0,0,114,4,0,0,0,41, 1,114,109,0,0,0,114,5,0,0,0,218,11,95,99,104, - 101,99,107,95,110,97,109,101,113,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,114,1,0,0,115,14,0,0, 0,0,8,21,7,3,1,13,1,13,2,17,5,13,1,114, 123,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, 0,4,0,0,0,67,0,0,0,115,84,0,0,0,124,0, @@ -633,7 +633,7 @@ 218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17, 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, - 109,141,1,0,0,115,10,0,0,0,0,10,21,1,24,1, + 109,142,1,0,0,115,10,0,0,0,0,10,21,1,24,1, 6,1,29,1,114,130,0,0,0,99,4,0,0,0,0,0, 0,0,11,0,0,0,19,0,0,0,67,0,0,0,115,228, 1,0,0,105,0,0,125,4,0,124,2,0,100,1,0,107, @@ -717,7 +717,7 @@ 109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,25, 95,118,97,108,105,100,97,116,101,95,98,121,116,101,99,111, - 100,101,95,104,101,97,100,101,114,158,1,0,0,115,76,0, + 100,101,95,104,101,97,100,101,114,159,1,0,0,115,76,0, 0,0,0,11,6,1,12,1,13,3,6,1,12,1,10,1, 16,1,16,1,16,1,12,1,18,1,10,1,18,1,18,1, 15,1,10,1,15,1,18,1,15,1,10,1,12,1,12,1, @@ -748,7 +748,7 @@ 114,106,0,0,0,114,89,0,0,0,114,90,0,0,0,218, 4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,109,112,105,108,101,95,98, - 121,116,101,99,111,100,101,213,1,0,0,115,16,0,0,0, + 121,116,101,99,111,100,101,214,1,0,0,115,16,0,0,0, 0,2,15,1,15,1,13,1,12,1,16,1,4,2,18,1, 114,147,0,0,0,114,59,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, @@ -768,7 +768,7 @@ 4,114,146,0,0,0,114,133,0,0,0,114,140,0,0,0, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,100,101,95,116,111,95,98, - 121,116,101,99,111,100,101,225,1,0,0,115,10,0,0,0, + 121,116,101,99,111,100,101,226,1,0,0,115,10,0,0,0, 0,3,12,1,19,1,19,1,22,1,114,150,0,0,0,99, 1,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, 67,0,0,0,115,89,0,0,0,100,1,0,100,2,0,108, @@ -797,7 +797,7 @@ 100,105,110,103,90,15,110,101,119,108,105,110,101,95,100,101, 99,111,100,101,114,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,13,100,101,99,111,100,101,95,115,111,117, - 114,99,101,235,1,0,0,115,10,0,0,0,0,5,12,1, + 114,99,101,236,1,0,0,115,10,0,0,0,0,5,12,1, 18,1,15,1,18,1,114,155,0,0,0,114,127,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, @@ -862,7 +862,7 @@ 159,0,0,0,90,7,100,105,114,110,97,109,101,114,4,0, 0,0,114,4,0,0,0,114,5,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,252,1,0,0,115,60,0,0,0,0,12, + 97,116,105,111,110,253,1,0,0,115,60,0,0,0,0,12, 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, @@ -902,7 +902,7 @@ 79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,3, 99,108,115,218,3,107,101,121,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, - 101,103,105,115,116,114,121,74,2,0,0,115,8,0,0,0, + 101,103,105,115,116,114,121,75,2,0,0,115,8,0,0,0, 0,2,3,1,23,1,13,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, @@ -929,7 +929,7 @@ 171,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101, 112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,81,2,0,0,115,22,0,0,0,0,2, + 105,115,116,114,121,82,2,0,0,115,22,0,0,0,0,2, 9,1,12,2,9,1,15,1,22,1,3,1,18,1,29,1, 13,1,9,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, @@ -953,7 +953,7 @@ 114,35,0,0,0,218,6,116,97,114,103,101,116,114,177,0, 0,0,114,127,0,0,0,114,166,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,102,105,110,100,95,115,112,101,99,96,2,0,0,115, + 218,9,102,105,110,100,95,115,112,101,99,97,2,0,0,115, 26,0,0,0,0,2,15,1,12,1,4,1,3,1,14,1, 13,1,9,1,22,1,21,1,9,1,15,1,9,1,122,31, 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, @@ -973,7 +973,7 @@ 0,0,0,41,4,114,170,0,0,0,114,126,0,0,0,114, 35,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,5,0,0,0,218,11,102,105,110,100,95,109, - 111,100,117,108,101,112,2,0,0,115,8,0,0,0,0,7, + 111,100,117,108,101,113,2,0,0,115,8,0,0,0,0,7, 18,1,12,1,7,2,122,33,87,105,110,100,111,119,115,82, 101,103,105,115,116,114,121,70,105,110,100,101,114,46,102,105, 110,100,95,109,111,100,117,108,101,41,12,114,112,0,0,0, @@ -982,7 +982,7 @@ 99,108,97,115,115,109,101,116,104,111,100,114,172,0,0,0, 114,178,0,0,0,114,181,0,0,0,114,182,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,168,0,0,0,62,2,0,0,115,20,0,0, + 0,0,0,114,168,0,0,0,63,2,0,0,115,20,0,0, 0,12,2,6,3,6,3,6,2,6,2,18,7,18,15,3, 1,21,15,3,1,114,168,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, @@ -1020,7 +1020,7 @@ 0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,159,0,0,0,131,2,0,0,115,8,0,0,0,0, + 0,114,159,0,0,0,132,2,0,0,115,8,0,0,0,0, 3,25,1,22,1,19,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, @@ -1030,7 +1030,7 @@ 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,164,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,13, - 99,114,101,97,116,101,95,109,111,100,117,108,101,139,2,0, + 99,114,101,97,116,101,95,109,111,100,117,108,101,140,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, @@ -1052,7 +1052,7 @@ 0,41,3,114,108,0,0,0,218,6,109,111,100,117,108,101, 114,146,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, - 101,142,2,0,0,115,10,0,0,0,0,2,18,1,12,1, + 101,143,2,0,0,115,10,0,0,0,0,2,18,1,12,1, 9,1,15,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,3,0,0,0, @@ -1061,14 +1061,14 @@ 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,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,11,108,111,97,100,95,109,111,100,117,108,101,150,2, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,151,2, 0,0,115,2,0,0,0,0,1,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,112,0,0,0,114,111,0,0, 0,114,113,0,0,0,114,114,0,0,0,114,159,0,0,0, 114,186,0,0,0,114,191,0,0,0,114,193,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,184,0,0,0,126,2,0,0,115,10,0,0, + 0,0,0,114,184,0,0,0,127,2,0,0,115,10,0,0, 0,12,3,6,2,12,8,12,3,12,8,114,184,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,106,0,0,0,101,0,0,90,1,0, @@ -1096,11 +1096,11 @@ 1,218,7,73,79,69,114,114,111,114,41,2,114,108,0,0, 0,114,35,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,112,97,116,104,95,109,116,105,109, - 101,156,2,0,0,115,2,0,0,0,0,6,122,23,83,111, + 101,157,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,3,0,0,0,67,0,0,0,115,19,0,0,0,124, - 0,0,106,0,0,124,1,0,131,1,0,100,1,0,105,1, + 0,0,3,0,0,0,67,0,0,0,115,19,0,0,0,100, + 1,0,124,0,0,106,0,0,124,1,0,131,1,0,105,1, 0,83,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, @@ -1131,7 +1131,7 @@ 32,32,32,114,133,0,0,0,41,1,114,196,0,0,0,41, 2,114,108,0,0,0,114,35,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,10,112,97,116,104, - 95,115,116,97,116,115,164,2,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,165,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,3,0,0,0,67,0,0,0,115, @@ -1155,7 +1155,7 @@ 90,0,0,0,90,10,99,97,99,104,101,95,112,97,116,104, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,15,95,99,97,99,104,101,95,98,121,116, - 101,99,111,100,101,177,2,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,178,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, @@ -1172,7 +1172,7 @@ 32,32,32,32,32,32,78,114,4,0,0,0,41,3,114,108, 0,0,0,114,35,0,0,0,114,53,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, - 0,187,2,0,0,115,0,0,0,0,122,21,83,111,117,114, + 0,188,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,16,0, 0,0,67,0,0,0,115,105,0,0,0,124,0,0,106,0, @@ -1194,7 +1194,7 @@ 0,0,114,126,0,0,0,114,35,0,0,0,114,153,0,0, 0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,103,101,116,95,115,111,117,114,99, - 101,194,2,0,0,115,14,0,0,0,0,2,15,1,3,1, + 101,195,2,0,0,115,14,0,0,0,0,2,15,1,3,1, 19,1,18,1,9,1,31,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,218,9,95,111,112,116,105,109,105,122,101,114,29,0,0, @@ -1216,7 +1216,7 @@ 101,41,4,114,108,0,0,0,114,53,0,0,0,114,35,0, 0,0,114,203,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,14,115,111,117,114,99,101,95,116, - 111,95,99,111,100,101,204,2,0,0,115,4,0,0,0,0, + 111,95,99,111,100,101,205,2,0,0,115,4,0,0,0,0, 5,21,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,10,0,0,0,43,0,0, @@ -1277,7 +1277,7 @@ 98,121,116,101,115,95,100,97,116,97,114,153,0,0,0,90, 11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0, 0,114,4,0,0,0,114,5,0,0,0,114,187,0,0,0, - 212,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, + 213,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, 1,16,1,13,1,11,2,3,1,19,1,13,1,5,2,16, 1,3,1,19,1,13,1,5,2,3,1,9,1,12,1,13, 1,19,1,5,2,9,1,7,1,15,1,6,1,7,1,15, @@ -1289,7 +1289,7 @@ 199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206, 0,0,0,114,187,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, - 0,154,2,0,0,115,14,0,0,0,12,2,12,8,12,13, + 0,155,2,0,0,115,14,0,0,0,12,2,12,8,12,13, 12,10,12,7,12,10,18,8,114,194,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,112,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1317,7 +1317,7 @@ 32,32,32,32,32,32,102,105,110,100,101,114,46,78,41,2, 114,106,0,0,0,114,35,0,0,0,41,3,114,108,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,13, + 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,14, 3,0,0,115,4,0,0,0,0,3,9,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, @@ -1327,7 +1327,7 @@ 41,2,218,9,95,95,99,108,97,115,115,95,95,114,118,0, 0,0,41,2,114,108,0,0,0,218,5,111,116,104,101,114, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 6,95,95,101,113,95,95,19,3,0,0,115,4,0,0,0, + 6,95,95,101,113,95,95,20,3,0,0,115,4,0,0,0, 0,1,18,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,26,0,0, @@ -1336,7 +1336,7 @@ 218,4,104,97,115,104,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,8,95,95,104,97,115,104,95,95, - 23,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 24,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,22,0,0,0,116,0,0,116,1,0, @@ -1350,7 +1350,7 @@ 32,32,32,32,32,32,32,32,41,3,218,5,115,117,112,101, 114,114,210,0,0,0,114,193,0,0,0,41,2,114,108,0, 0,0,114,126,0,0,0,41,1,114,211,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,193,0,0,0,26,3,0, + 0,0,0,114,5,0,0,0,114,193,0,0,0,27,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, @@ -1361,7 +1361,7 @@ 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,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,157,0,0,0,38,3,0,0,115,2,0,0,0,0, + 0,114,157,0,0,0,39,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, @@ -1374,14 +1374,14 @@ 49,0,0,0,114,50,0,0,0,90,4,114,101,97,100,41, 3,114,108,0,0,0,114,35,0,0,0,114,54,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 200,0,0,0,43,3,0,0,115,4,0,0,0,0,2,21, + 200,0,0,0,44,3,0,0,115,4,0,0,0,0,2,21, 1,122,19,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,100,97,116,97,41,11,114,112,0,0,0,114,111,0, 0,0,114,113,0,0,0,114,114,0,0,0,114,185,0,0, 0,114,213,0,0,0,114,215,0,0,0,114,123,0,0,0, 114,193,0,0,0,114,157,0,0,0,114,200,0,0,0,114, 4,0,0,0,114,4,0,0,0,41,1,114,211,0,0,0, - 114,5,0,0,0,114,210,0,0,0,8,3,0,0,115,14, + 114,5,0,0,0,114,210,0,0,0,9,3,0,0,115,14, 0,0,0,12,3,6,2,12,6,12,4,12,3,24,12,18, 5,114,210,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,64,0,0,0, @@ -1396,15 +1396,15 @@ 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,5,0,0,0,67,0,0,0,115,34,0,0,0,116,0, - 0,124,1,0,131,1,0,125,2,0,124,2,0,106,1,0, - 100,1,0,124,2,0,106,2,0,100,2,0,105,2,0,83, + 0,124,1,0,131,1,0,125,2,0,100,1,0,124,2,0, + 106,1,0,100,2,0,124,2,0,106,2,0,105,2,0,83, 41,3,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,114,133,0,0,0,114,134,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,108,0,0,0, 114,35,0,0,0,114,208,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,197,0,0,0,53,3, + 4,0,0,0,114,5,0,0,0,114,197,0,0,0,54,3, 0,0,115,4,0,0,0,0,2,12,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, @@ -1415,7 +1415,7 @@ 114,97,0,0,0,114,198,0,0,0,41,5,114,108,0,0, 0,114,90,0,0,0,114,89,0,0,0,114,53,0,0,0, 114,42,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,199,0,0,0,58,3,0,0,115,4,0, + 5,0,0,0,114,199,0,0,0,59,3,0,0,115,4,0, 0,0,0,2,12,1,122,32,83,111,117,114,99,101,70,105, 108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, 98,121,116,101,99,111,100,101,114,220,0,0,0,105,182,1, @@ -1453,7 +1453,7 @@ 53,0,0,0,114,220,0,0,0,218,6,112,97,114,101,110, 116,114,94,0,0,0,114,27,0,0,0,114,23,0,0,0, 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,198,0,0,0,63,3,0,0,115,38,0, + 5,0,0,0,114,198,0,0,0,64,3,0,0,115,38,0, 0,0,0,2,18,1,6,2,22,1,18,1,17,2,19,1, 15,1,3,1,17,1,13,2,7,1,18,3,16,1,27,1, 3,1,16,1,17,1,18,2,122,25,83,111,117,114,99,101, @@ -1462,7 +1462,7 @@ 114,113,0,0,0,114,114,0,0,0,114,197,0,0,0,114, 199,0,0,0,114,198,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,218,0, - 0,0,49,3,0,0,115,8,0,0,0,12,2,6,2,12, + 0,0,50,3,0,0,115,8,0,0,0,12,2,6,2,12, 5,12,5,114,218,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,46,0, 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, @@ -1484,7 +1484,7 @@ 114,147,0,0,0,41,5,114,108,0,0,0,114,126,0,0, 0,114,35,0,0,0,114,53,0,0,0,114,209,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 187,0,0,0,96,3,0,0,115,8,0,0,0,0,1,15, + 187,0,0,0,97,3,0,0,115,8,0,0,0,0,1,15, 1,15,1,24,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, @@ -1494,13 +1494,13 @@ 32,115,111,117,114,99,101,32,99,111,100,101,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,202, - 0,0,0,102,3,0,0,115,2,0,0,0,0,2,122,31, + 0,0,0,103,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,112,0,0,0,114,111,0,0,0,114,113,0,0, 0,114,114,0,0,0,114,187,0,0,0,114,202,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,223,0,0,0,92,3,0,0,115,6,0, + 5,0,0,0,114,223,0,0,0,93,3,0,0,115,6,0, 0,0,12,2,6,2,12,6,114,223,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,136,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1525,7 +1525,7 @@ 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,119,3,0,0,115,4,0, + 5,0,0,0,114,185,0,0,0,120,3,0,0,115,4,0, 0,0,0,1,9,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, @@ -1534,7 +1534,7 @@ 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, 41,1,78,41,2,114,211,0,0,0,114,118,0,0,0,41, 2,114,108,0,0,0,114,212,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,123, + 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,124, 3,0,0,115,4,0,0,0,0,1,18,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, @@ -1543,7 +1543,7 @@ 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, 3,114,214,0,0,0,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,215,0,0,0,127,3,0,0,115, + 0,114,5,0,0,0,114,215,0,0,0,128,3,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, @@ -1561,7 +1561,7 @@ 114,105,0,0,0,114,106,0,0,0,114,35,0,0,0,41, 3,114,108,0,0,0,114,164,0,0,0,114,190,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 186,0,0,0,130,3,0,0,115,10,0,0,0,0,2,6, + 186,0,0,0,131,3,0,0,115,10,0,0,0,0,2,6, 1,15,1,6,1,16,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, @@ -1578,7 +1578,7 @@ 12,101,120,101,99,95,100,121,110,97,109,105,99,114,105,0, 0,0,114,106,0,0,0,114,35,0,0,0,41,2,114,108, 0,0,0,114,190,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,191,0,0,0,138,3,0,0, + 0,0,114,5,0,0,0,114,191,0,0,0,139,3,0,0, 115,6,0,0,0,0,2,19,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, @@ -1597,7 +1597,7 @@ 78,114,4,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,4,0,0,0,114,5,0,0,0,250,9,60,103, - 101,110,101,120,112,114,62,147,3,0,0,115,2,0,0,0, + 101,110,101,120,112,114,62,148,3,0,0,115,2,0,0,0, 6,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, @@ -1605,7 +1605,7 @@ 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,108,0,0, 0,114,126,0,0,0,114,4,0,0,0,41,1,114,226,0, - 0,0,114,5,0,0,0,114,159,0,0,0,144,3,0,0, + 0,0,114,5,0,0,0,114,159,0,0,0,145,3,0,0, 115,6,0,0,0,0,2,19,1,18,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, @@ -1617,7 +1617,7 @@ 99,111,100,101,32,111,98,106,101,99,116,46,78,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,187,0, - 0,0,150,3,0,0,115,2,0,0,0,0,2,122,28,69, + 0,0,151,3,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, @@ -1627,7 +1627,7 @@ 118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100, 101,46,78,114,4,0,0,0,41,2,114,108,0,0,0,114, 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,202,0,0,0,154,3,0,0,115,2,0,0, + 0,0,0,114,202,0,0,0,155,3,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, @@ -1638,7 +1638,7 @@ 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,108,0,0,0, 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,157,0,0,0,158,3,0,0,115,2,0, + 5,0,0,0,114,157,0,0,0,159,3,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,112,0,0,0,114,111, @@ -1647,7 +1647,7 @@ 0,114,191,0,0,0,114,159,0,0,0,114,187,0,0,0, 114,202,0,0,0,114,123,0,0,0,114,157,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,224,0,0,0,111,3,0,0,115,20,0,0, + 0,0,0,114,224,0,0,0,112,3,0,0,115,20,0,0, 0,12,6,6,2,12,4,12,4,12,3,12,8,12,6,12, 6,12,4,12,4,114,224,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, @@ -1691,7 +1691,7 @@ 95,112,97,116,104,95,102,105,110,100,101,114,41,4,114,108, 0,0,0,114,106,0,0,0,114,35,0,0,0,218,11,112, 97,116,104,95,102,105,110,100,101,114,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,185,0,0,0,171,3, + 4,0,0,0,114,5,0,0,0,114,185,0,0,0,172,3, 0,0,115,8,0,0,0,0,1,9,1,9,1,21,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, @@ -1710,7 +1710,7 @@ 41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111, 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,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,177,3,0, + 110,116,95,112,97,116,104,95,110,97,109,101,115,178,3,0, 0,115,8,0,0,0,0,2,27,1,12,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, @@ -1724,7 +1724,7 @@ 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,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,233,0, - 0,0,187,3,0,0,115,4,0,0,0,0,1,18,1,122, + 0,0,188,3,0,0,115,4,0,0,0,0,1,18,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,3,0,0, @@ -1742,7 +1742,7 @@ 108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, 104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108, - 97,116,101,191,3,0,0,115,16,0,0,0,0,2,18,1, + 97,116,101,192,3,0,0,115,16,0,0,0,0,2,18,1, 15,1,21,3,27,1,9,1,12,1,9,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, @@ -1751,14 +1751,14 @@ 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,240, 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101, - 114,95,95,204,3,0,0,115,2,0,0,0,0,1,122,23, + 114,95,95,205,3,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,1,0,0,0,0,0,0,0, 1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0, 0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0, 83,41,1,78,41,2,114,31,0,0,0,114,240,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,207, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,208, 3,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,2, @@ -1768,7 +1768,7 @@ 123,33,114,125,41,41,2,114,47,0,0,0,114,232,0,0, 0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95, - 95,210,3,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,211,3,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,2,0,0,0,67,0,0,0,115,16,0,0,0,124, @@ -1776,7 +1776,7 @@ 1,78,41,1,114,240,0,0,0,41,2,114,108,0,0,0, 218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110, - 115,95,95,213,3,0,0,115,2,0,0,0,0,1,122,27, + 115,95,95,214,3,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,2,0,0,0,67,0,0,0, @@ -1784,7 +1784,7 @@ 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,232, 0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114, 245,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,163,0,0,0,216,3,0,0,115,2,0,0, + 0,0,0,114,163,0,0,0,217,3,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,13,114,112,0, 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, @@ -1792,7 +1792,7 @@ 114,240,0,0,0,114,242,0,0,0,114,243,0,0,0,114, 244,0,0,0,114,246,0,0,0,114,163,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,230,0,0,0,164,3,0,0,115,20,0,0,0, + 0,0,114,230,0,0,0,165,3,0,0,115,20,0,0,0, 12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3, 12,3,12,3,114,230,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,118, @@ -1811,7 +1811,7 @@ 41,1,78,41,2,114,230,0,0,0,114,232,0,0,0,41, 4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0, 114,236,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,222,3,0,0,115,2,0, + 5,0,0,0,114,185,0,0,0,223,3,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,2,0,0,0, @@ -1828,14 +1828,14 @@ 110,97,109,101,115,112,97,99,101,41,62,41,2,114,47,0, 0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,225, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,226, 3,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,0,83,41,2,78,84,114,4,0,0,0,41, 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,234, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,235, 3,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, @@ -1843,7 +1843,7 @@ 0,100,1,0,83,41,2,78,114,30,0,0,0,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0, - 0,0,237,3,0,0,115,2,0,0,0,0,1,122,27,95, + 0,0,238,3,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, @@ -1852,7 +1852,7 @@ 0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0, 0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2, 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,187,0,0,0,240,3, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,241,3, 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, @@ -1862,14 +1862,14 @@ 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, 78,114,4,0,0,0,41,2,114,108,0,0,0,114,164,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,186,0,0,0,243,3,0,0,115,0,0,0,0,122, + 0,114,186,0,0,0,244,3,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,0,83,41,1,78, 114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,191,0,0,0,246,3,0,0,115,2,0,0,0,0,1, + 114,191,0,0,0,247,3,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,3,0,0,0,67, @@ -1887,7 +1887,7 @@ 104,32,123,33,114,125,41,4,114,105,0,0,0,114,232,0, 0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108, 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,193,0,0,0,249,3,0,0, + 0,0,114,5,0,0,0,114,193,0,0,0,250,3,0,0, 115,4,0,0,0,0,7,16,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,112,0,0,0,114, @@ -1895,7 +1895,7 @@ 0,0,0,114,248,0,0,0,114,159,0,0,0,114,202,0, 0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0, 0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,221, + 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,222, 3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3, 12,3,12,3,12,3,12,3,114,247,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0, @@ -1933,7 +1933,7 @@ 114,95,99,97,99,104,101,218,6,118,97,108,117,101,115,114, 115,0,0,0,114,250,0,0,0,41,2,114,170,0,0,0, 218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,250,0,0,0,10,4,0,0, + 0,0,114,5,0,0,0,114,250,0,0,0,11,4,0,0, 115,6,0,0,0,0,4,22,1,15,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, @@ -1959,7 +1959,7 @@ 107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0, 90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111, - 107,115,18,4,0,0,115,16,0,0,0,0,7,25,1,16, + 107,115,19,4,0,0,115,16,0,0,0,0,7,25,1,16, 1,16,1,3,1,14,1,13,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, @@ -1991,7 +1991,7 @@ 0,0,114,255,0,0,0,41,3,114,170,0,0,0,114,35, 0,0,0,114,253,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,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,35,4,0, + 109,112,111,114,116,101,114,95,99,97,99,104,101,36,4,0, 0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3, 9,1,3,1,17,1,13,1,15,1,18,1,122,31,80,97, 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, @@ -2011,7 +2011,7 @@ 0,0,114,126,0,0,0,114,253,0,0,0,114,127,0,0, 0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,57,4,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,58,4,0,0, 115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12, 1,16,1,18,1,9,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, @@ -2047,7 +2047,7 @@ 101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116, 114,121,114,253,0,0,0,114,164,0,0,0,114,128,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,95,103,101,116,95,115,112,101,99,72,4,0,0,115, + 218,9,95,103,101,116,95,115,112,101,99,73,4,0,0,115, 40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1, 12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1, 9,1,12,1,12,5,17,2,18,1,9,1,122,20,80,97, @@ -2075,7 +2075,7 @@ 6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0, 114,180,0,0,0,114,164,0,0,0,114,4,1,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181, - 0,0,0,104,4,0,0,115,26,0,0,0,0,4,12,1, + 0,0,0,105,4,0,0,115,26,0,0,0,0,4,12,1, 9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1, 24,1,4,2,7,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, @@ -2097,7 +2097,7 @@ 114,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 182,0,0,0,126,4,0,0,115,8,0,0,0,0,8,18, + 182,0,0,0,127,4,0,0,115,8,0,0,0,0,8,18, 1,12,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,12,114, 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, @@ -2105,7 +2105,7 @@ 0,0,114,1,1,0,0,114,2,1,0,0,114,5,1,0, 0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 249,0,0,0,6,4,0,0,115,22,0,0,0,12,2,6, + 249,0,0,0,7,4,0,0,115,22,0,0,0,12,2,6, 2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21, 21,3,1,114,249,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,133,0, @@ -2154,7 +2154,7 @@ 0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0, 0,0,41,2,114,22,0,0,0,114,225,0,0,0,41,1, 114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 227,0,0,0,155,4,0,0,115,2,0,0,0,6,0,122, + 227,0,0,0,156,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0, @@ -2167,7 +2167,7 @@ 111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108, 111,97,100,101,114,115,114,166,0,0,0,114,4,0,0,0, 41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0, - 0,149,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 0,150,4,0,0,115,16,0,0,0,0,4,6,1,19,1, 36,1,9,2,15,1,9,1,12,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, @@ -2177,7 +2177,7 @@ 114,121,32,109,116,105,109,101,46,114,29,0,0,0,78,114, 87,0,0,0,41,1,114,8,1,0,0,41,1,114,108,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,250,0,0,0,163,4,0,0,115,2,0,0,0,0, + 0,114,250,0,0,0,164,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, @@ -2201,7 +2201,7 @@ 114,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41, 3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 124,0,0,0,169,4,0,0,115,8,0,0,0,0,7,15, + 124,0,0,0,170,4,0,0,115,8,0,0,0,0,7,15, 1,12,1,10,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,7,0,0,0,67,0, @@ -2212,7 +2212,7 @@ 0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114, 126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, 180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,5,1,0,0,181,4,0, + 0,0,0,114,5,0,0,0,114,5,1,0,0,182,4,0, 0,115,6,0,0,0,0,1,15,1,18,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, @@ -2276,7 +2276,7 @@ 0,114,165,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,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,181,0,0,0,186,4,0,0,115,68,0, + 5,0,0,0,114,181,0,0,0,187,4,0,0,115,68,0, 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1, 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2, 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2, @@ -2313,7 +2313,7 @@ 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22, 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112, - 62,4,5,0,0,115,2,0,0,0,9,0,122,41,70,105, + 62,5,5,0,0,115,2,0,0,0,9,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, @@ -2330,7 +2330,7 @@ 114,245,0,0,0,114,106,0,0,0,114,237,0,0,0,114, 225,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,13,1, - 0,0,231,4,0,0,115,34,0,0,0,0,2,9,1,3, + 0,0,232,4,0,0,115,34,0,0,0,0,2,9,1,3, 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24, 1,6,1,27,2,6,1,17,1,9,1,18,1,122,22,70, 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, @@ -2369,14 +2369,14 @@ 0,41,2,114,170,0,0,0,114,12,1,0,0,114,4,0, 0,0,114,5,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,16,5,0,0,115,6,0,0,0,0,2,12,1,18,1, + 114,17,5,0,0,115,6,0,0,0,0,2,12,1,18,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, 170,0,0,0,114,12,1,0,0,114,18,1,0,0,114,4, 0,0,0,41,2,114,170,0,0,0,114,12,1,0,0,114, - 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,6, + 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,7, 5,0,0,115,4,0,0,0,0,10,21,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, @@ -2385,7 +2385,7 @@ 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114, 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,244,0,0,0,24,5,0,0,115,2,0,0, + 0,0,0,114,244,0,0,0,25,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,15,114,112,0,0,0,114, 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185, @@ -2393,7 +2393,7 @@ 0,0,114,124,0,0,0,114,5,1,0,0,114,181,0,0, 0,114,13,1,0,0,114,183,0,0,0,114,19,1,0,0, 114,244,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,6,1,0,0,140,4, + 4,0,0,0,114,5,0,0,0,114,6,1,0,0,141,4, 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6, 2,12,12,12,5,15,45,12,31,18,18,114,6,1,0,0, 99,4,0,0,0,0,0,0,0,6,0,0,0,11,0,0, @@ -2420,7 +2420,7 @@ 97,116,104,110,97,109,101,114,127,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,14,95,102,105,120,95,117,112,95,109,111,100,117,108,101, - 30,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, + 31,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, 1,6,1,12,1,12,1,18,2,15,1,6,1,21,1,3, 1,10,1,10,1,10,1,14,1,13,2,114,24,1,0,0, 99,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0, @@ -2440,7 +2440,7 @@ 0,0,0,114,74,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,5,0,0,0,114,161,0,0,0,53,5,0,0, + 0,0,114,5,0,0,0,114,161,0,0,0,54,5,0,0, 115,8,0,0,0,0,5,18,1,12,1,12,1,114,161,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,70,2,0,0,124,0,0,97, @@ -2502,7 +2502,7 @@ 1,113,3,0,100,1,0,83,41,2,114,29,0,0,0,78, 41,1,114,31,0,0,0,41,2,114,22,0,0,0,114,77, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,227,0,0,0,89,5,0,0,115,2,0,0,0, + 0,0,114,227,0,0,0,90,5,0,0,115,2,0,0,0, 6,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,59,0, 0,0,122,30,105,109,112,111,114,116,108,105,98,32,114,101, @@ -2532,7 +2532,7 @@ 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,5,0,0,0,218,6,95,115,101,116,117,112,64,5,0, + 114,5,0,0,0,218,6,95,115,101,116,117,112,65,5,0, 0,115,82,0,0,0,0,8,6,1,9,1,9,3,13,1, 13,1,15,1,18,2,13,1,20,3,33,1,19,2,31,1, 10,1,15,1,13,1,4,2,3,1,15,1,5,1,13,1, @@ -2558,7 +2558,7 @@ 0,0,114,249,0,0,0,114,218,0,0,0,41,2,114,32, 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,5,0,0,0,218,8,95,105,110,115,116,97,108,108,132, + 114,5,0,0,0,218,8,95,105,110,115,116,97,108,108,133, 5,0,0,115,16,0,0,0,0,2,10,1,9,1,28,1, 15,1,16,1,16,4,9,1,114,35,1,0,0,41,3,122, 3,119,105,110,114,1,0,0,0,114,2,0,0,0,41,57, @@ -2588,7 +2588,7 @@ 5,0,0,0,218,8,60,109,111,100,117,108,101,62,8,0, 0,0,115,100,0,0,0,6,17,6,3,12,12,12,5,12, 5,12,6,12,12,12,10,12,9,12,5,12,7,15,22,15, - 108,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, + 109,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, 44,12,33,12,19,12,12,12,12,18,8,12,28,12,17,21, 55,21,12,18,10,12,14,9,3,12,1,15,65,19,64,19, 28,22,110,19,41,25,43,25,16,6,3,25,53,19,57,19, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 21:31:26 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 19:31:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMTEyMDUp?= Message-ID: <20150528193125.27666.78481@psf.io> https://hg.python.org/cpython/rev/ba9e4df5368c changeset: 96340:ba9e4df5368c parent: 96338:a95d0dd3c2b1 parent: 96339:6f05f83c7010 user: Benjamin Peterson date: Thu May 28 14:31:14 2015 -0500 summary: merge 3.5 (#11205) files: Lib/importlib/_bootstrap_external.py | 3 +- Lib/test/test_compile.py | 11 + Misc/NEWS | 2 + Python/ceval.c | 4 +- Python/compile.c | 4 +- Python/importlib_external.h | 216 +++++++------- 6 files changed, 127 insertions(+), 113 deletions(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -221,12 +221,13 @@ # 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.5b2 3340 (fix dictionary display evaluation order #11205) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). -MAGIC_NUMBER = (3330).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3340).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -461,6 +461,17 @@ ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '', 'exec') + def test_dict_evaluation_order(self): + i = 0 + + def f(): + nonlocal i + i += 1 + return i + + d = {f(): f(), f(): f()} + self.assertEqual(d, {1: 2, 3: 4}) + @support.cpython_only def test_same_filename_used(self): s = """def f(): pass\ndef g(): pass""" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Core and Builtins ----------------- +- Issue #11205: In dictionary displays, evaluate the key before the value. + - Issue #24285: Fixed regression that prevented importing extension modules from inside packages. Patch by Petr Viktorin. diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2584,8 +2584,8 @@ goto error; while (--oparg >= 0) { int err; - PyObject *key = TOP(); - PyObject *value = SECOND(); + PyObject *value = TOP(); + PyObject *key = SECOND(); STACKADJ(-2); err = PyDict_SetItem(map, key, value); Py_DECREF(value); diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -3138,8 +3138,8 @@ containers++; } else { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); elements++; } } @@ -3287,8 +3287,8 @@ } else if (nsubkwargs) { /* A keyword argument and we already have a dict. */ + ADDOP_O(c, LOAD_CONST, kw->arg, consts); VISIT(c, expr, kw->value); - ADDOP_O(c, LOAD_CONST, kw->arg, consts); nseen++; } else { diff --git a/Python/importlib_external.h b/Python/importlib_external.h --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -259,7 +259,7 @@ 0,0,114,5,0,0,0,218,13,95,119,114,105,116,101,95, 97,116,111,109,105,99,99,0,0,0,115,26,0,0,0,0, 5,24,1,9,1,33,1,3,3,21,1,20,1,20,1,13, - 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,2, + 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,12, 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, @@ -369,7 +369,7 @@ 116,97,103,90,15,97,108,109,111,115,116,95,102,105,108,101, 110,97,109,101,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,17,99,97,99,104,101,95,102,114,111,109,95, - 115,111,117,114,99,101,241,0,0,0,115,46,0,0,0,0, + 115,111,117,114,99,101,242,0,0,0,115,46,0,0,0,0, 18,12,1,9,1,7,1,12,1,6,1,12,1,18,1,18, 1,24,1,12,1,12,1,12,1,36,1,12,1,18,1,9, 2,12,1,12,1,12,1,12,1,21,1,21,1,114,79,0, @@ -448,7 +448,7 @@ 95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108, 101,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111, - 109,95,99,97,99,104,101,29,1,0,0,115,44,0,0,0, + 109,95,99,97,99,104,101,30,1,0,0,115,44,0,0,0, 0,9,18,1,12,1,18,1,18,1,12,1,9,1,15,1, 15,1,12,1,9,1,15,1,12,1,22,1,15,1,9,1, 12,1,22,1,12,1,9,1,12,1,19,1,114,85,0,0, @@ -486,7 +486,7 @@ 115,105,111,110,218,11,115,111,117,114,99,101,95,112,97,116, 104,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108, - 101,62,1,0,0,115,20,0,0,0,0,7,18,1,4,1, + 101,63,1,0,0,115,20,0,0,0,0,7,18,1,4,1, 24,1,35,1,4,1,3,1,16,1,19,1,21,1,114,91, 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, 11,0,0,0,67,0,0,0,115,92,0,0,0,124,0,0, @@ -500,7 +500,7 @@ 84,0,0,0,114,79,0,0,0,114,66,0,0,0,114,74, 0,0,0,41,1,218,8,102,105,108,101,110,97,109,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, - 95,103,101,116,95,99,97,99,104,101,100,81,1,0,0,115, + 95,103,101,116,95,99,97,99,104,101,100,82,1,0,0,115, 16,0,0,0,0,1,21,1,3,1,14,1,13,1,8,1, 21,1,4,2,114,95,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,60, @@ -515,7 +515,7 @@ 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,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,99, - 97,108,99,95,109,111,100,101,93,1,0,0,115,12,0,0, + 97,108,99,95,109,111,100,101,94,1,0,0,115,12,0,0, 0,0,2,3,1,19,1,13,1,11,3,10,1,114,97,0, 0,0,218,9,118,101,114,98,111,115,105,116,121,114,29,0, 0,0,99,1,0,0,0,1,0,0,0,3,0,0,0,4, @@ -536,7 +536,7 @@ 218,6,115,116,100,101,114,114,41,3,114,75,0,0,0,114, 98,0,0,0,218,4,97,114,103,115,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,16,95,118,101,114,98, - 111,115,101,95,109,101,115,115,97,103,101,105,1,0,0,115, + 111,115,101,95,109,101,115,115,97,103,101,106,1,0,0,115, 8,0,0,0,0,2,18,1,15,1,10,1,114,105,0,0, 0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0, 0,0,3,0,0,0,115,84,0,0,0,100,1,0,135,0, @@ -576,7 +576,7 @@ 0,0,90,6,107,119,97,114,103,115,41,1,218,6,109,101, 116,104,111,100,114,4,0,0,0,114,5,0,0,0,218,19, 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, - 112,101,114,121,1,0,0,115,12,0,0,0,0,1,12,1, + 112,101,114,122,1,0,0,115,12,0,0,0,0,1,12,1, 12,1,15,1,6,1,25,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, @@ -595,7 +595,7 @@ 116,97,116,116,114,218,8,95,95,100,105,99,116,95,95,218, 6,117,112,100,97,116,101,41,3,90,3,110,101,119,90,3, 111,108,100,114,52,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,5,95,119,114,97,112,132,1, + 0,0,114,5,0,0,0,218,5,95,119,114,97,112,133,1, 0,0,115,8,0,0,0,0,1,25,1,15,1,29,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,3,218,10,95, @@ -603,7 +603,7 @@ 78,97,109,101,69,114,114,111,114,41,3,114,109,0,0,0, 114,110,0,0,0,114,120,0,0,0,114,4,0,0,0,41, 1,114,109,0,0,0,114,5,0,0,0,218,11,95,99,104, - 101,99,107,95,110,97,109,101,113,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,114,1,0,0,115,14,0,0, 0,0,8,21,7,3,1,13,1,13,2,17,5,13,1,114, 123,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, 0,4,0,0,0,67,0,0,0,115,84,0,0,0,124,0, @@ -633,7 +633,7 @@ 218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17, 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, - 109,141,1,0,0,115,10,0,0,0,0,10,21,1,24,1, + 109,142,1,0,0,115,10,0,0,0,0,10,21,1,24,1, 6,1,29,1,114,130,0,0,0,99,4,0,0,0,0,0, 0,0,11,0,0,0,19,0,0,0,67,0,0,0,115,228, 1,0,0,105,0,0,125,4,0,124,2,0,100,1,0,107, @@ -717,7 +717,7 @@ 109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,25, 95,118,97,108,105,100,97,116,101,95,98,121,116,101,99,111, - 100,101,95,104,101,97,100,101,114,158,1,0,0,115,76,0, + 100,101,95,104,101,97,100,101,114,159,1,0,0,115,76,0, 0,0,0,11,6,1,12,1,13,3,6,1,12,1,10,1, 16,1,16,1,16,1,12,1,18,1,10,1,18,1,18,1, 15,1,10,1,15,1,18,1,15,1,10,1,12,1,12,1, @@ -748,7 +748,7 @@ 114,106,0,0,0,114,89,0,0,0,114,90,0,0,0,218, 4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,109,112,105,108,101,95,98, - 121,116,101,99,111,100,101,213,1,0,0,115,16,0,0,0, + 121,116,101,99,111,100,101,214,1,0,0,115,16,0,0,0, 0,2,15,1,15,1,13,1,12,1,16,1,4,2,18,1, 114,147,0,0,0,114,59,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, @@ -768,7 +768,7 @@ 4,114,146,0,0,0,114,133,0,0,0,114,140,0,0,0, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,100,101,95,116,111,95,98, - 121,116,101,99,111,100,101,225,1,0,0,115,10,0,0,0, + 121,116,101,99,111,100,101,226,1,0,0,115,10,0,0,0, 0,3,12,1,19,1,19,1,22,1,114,150,0,0,0,99, 1,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, 67,0,0,0,115,89,0,0,0,100,1,0,100,2,0,108, @@ -797,7 +797,7 @@ 100,105,110,103,90,15,110,101,119,108,105,110,101,95,100,101, 99,111,100,101,114,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,13,100,101,99,111,100,101,95,115,111,117, - 114,99,101,235,1,0,0,115,10,0,0,0,0,5,12,1, + 114,99,101,236,1,0,0,115,10,0,0,0,0,5,12,1, 18,1,15,1,18,1,114,155,0,0,0,114,127,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, @@ -862,7 +862,7 @@ 159,0,0,0,90,7,100,105,114,110,97,109,101,114,4,0, 0,0,114,4,0,0,0,114,5,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,252,1,0,0,115,60,0,0,0,0,12, + 97,116,105,111,110,253,1,0,0,115,60,0,0,0,0,12, 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, @@ -902,7 +902,7 @@ 79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,3, 99,108,115,218,3,107,101,121,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, - 101,103,105,115,116,114,121,74,2,0,0,115,8,0,0,0, + 101,103,105,115,116,114,121,75,2,0,0,115,8,0,0,0, 0,2,3,1,23,1,13,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, @@ -929,7 +929,7 @@ 171,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101, 112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,81,2,0,0,115,22,0,0,0,0,2, + 105,115,116,114,121,82,2,0,0,115,22,0,0,0,0,2, 9,1,12,2,9,1,15,1,22,1,3,1,18,1,29,1, 13,1,9,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, @@ -953,7 +953,7 @@ 114,35,0,0,0,218,6,116,97,114,103,101,116,114,177,0, 0,0,114,127,0,0,0,114,166,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,102,105,110,100,95,115,112,101,99,96,2,0,0,115, + 218,9,102,105,110,100,95,115,112,101,99,97,2,0,0,115, 26,0,0,0,0,2,15,1,12,1,4,1,3,1,14,1, 13,1,9,1,22,1,21,1,9,1,15,1,9,1,122,31, 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, @@ -973,7 +973,7 @@ 0,0,0,41,4,114,170,0,0,0,114,126,0,0,0,114, 35,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,5,0,0,0,218,11,102,105,110,100,95,109, - 111,100,117,108,101,112,2,0,0,115,8,0,0,0,0,7, + 111,100,117,108,101,113,2,0,0,115,8,0,0,0,0,7, 18,1,12,1,7,2,122,33,87,105,110,100,111,119,115,82, 101,103,105,115,116,114,121,70,105,110,100,101,114,46,102,105, 110,100,95,109,111,100,117,108,101,41,12,114,112,0,0,0, @@ -982,7 +982,7 @@ 99,108,97,115,115,109,101,116,104,111,100,114,172,0,0,0, 114,178,0,0,0,114,181,0,0,0,114,182,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,168,0,0,0,62,2,0,0,115,20,0,0, + 0,0,0,114,168,0,0,0,63,2,0,0,115,20,0,0, 0,12,2,6,3,6,3,6,2,6,2,18,7,18,15,3, 1,21,15,3,1,114,168,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, @@ -1020,7 +1020,7 @@ 0,0,0,114,94,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,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,159,0,0,0,131,2,0,0,115,8,0,0,0,0, + 0,114,159,0,0,0,132,2,0,0,115,8,0,0,0,0, 3,25,1,22,1,19,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, @@ -1030,7 +1030,7 @@ 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,164,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,13, - 99,114,101,97,116,101,95,109,111,100,117,108,101,139,2,0, + 99,114,101,97,116,101,95,109,111,100,117,108,101,140,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, @@ -1052,7 +1052,7 @@ 0,41,3,114,108,0,0,0,218,6,109,111,100,117,108,101, 114,146,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, - 101,142,2,0,0,115,10,0,0,0,0,2,18,1,12,1, + 101,143,2,0,0,115,10,0,0,0,0,2,18,1,12,1, 9,1,15,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,3,0,0,0, @@ -1061,14 +1061,14 @@ 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,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,11,108,111,97,100,95,109,111,100,117,108,101,150,2, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,151,2, 0,0,115,2,0,0,0,0,1,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,112,0,0,0,114,111,0,0, 0,114,113,0,0,0,114,114,0,0,0,114,159,0,0,0, 114,186,0,0,0,114,191,0,0,0,114,193,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,184,0,0,0,126,2,0,0,115,10,0,0, + 0,0,0,114,184,0,0,0,127,2,0,0,115,10,0,0, 0,12,3,6,2,12,8,12,3,12,8,114,184,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,106,0,0,0,101,0,0,90,1,0, @@ -1096,11 +1096,11 @@ 1,218,7,73,79,69,114,114,111,114,41,2,114,108,0,0, 0,114,35,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,112,97,116,104,95,109,116,105,109, - 101,156,2,0,0,115,2,0,0,0,0,6,122,23,83,111, + 101,157,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,3,0,0,0,67,0,0,0,115,19,0,0,0,124, - 0,0,106,0,0,124,1,0,131,1,0,100,1,0,105,1, + 0,0,3,0,0,0,67,0,0,0,115,19,0,0,0,100, + 1,0,124,0,0,106,0,0,124,1,0,131,1,0,105,1, 0,83,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, @@ -1131,7 +1131,7 @@ 32,32,32,114,133,0,0,0,41,1,114,196,0,0,0,41, 2,114,108,0,0,0,114,35,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,10,112,97,116,104, - 95,115,116,97,116,115,164,2,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,165,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,3,0,0,0,67,0,0,0,115, @@ -1155,7 +1155,7 @@ 90,0,0,0,90,10,99,97,99,104,101,95,112,97,116,104, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,15,95,99,97,99,104,101,95,98,121,116, - 101,99,111,100,101,177,2,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,178,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, @@ -1172,7 +1172,7 @@ 32,32,32,32,32,32,78,114,4,0,0,0,41,3,114,108, 0,0,0,114,35,0,0,0,114,53,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, - 0,187,2,0,0,115,0,0,0,0,122,21,83,111,117,114, + 0,188,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,16,0, 0,0,67,0,0,0,115,105,0,0,0,124,0,0,106,0, @@ -1194,7 +1194,7 @@ 0,0,114,126,0,0,0,114,35,0,0,0,114,153,0,0, 0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,103,101,116,95,115,111,117,114,99, - 101,194,2,0,0,115,14,0,0,0,0,2,15,1,3,1, + 101,195,2,0,0,115,14,0,0,0,0,2,15,1,3,1, 19,1,18,1,9,1,31,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,218,9,95,111,112,116,105,109,105,122,101,114,29,0,0, @@ -1216,7 +1216,7 @@ 101,41,4,114,108,0,0,0,114,53,0,0,0,114,35,0, 0,0,114,203,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,14,115,111,117,114,99,101,95,116, - 111,95,99,111,100,101,204,2,0,0,115,4,0,0,0,0, + 111,95,99,111,100,101,205,2,0,0,115,4,0,0,0,0, 5,21,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,10,0,0,0,43,0,0, @@ -1277,7 +1277,7 @@ 98,121,116,101,115,95,100,97,116,97,114,153,0,0,0,90, 11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0, 0,114,4,0,0,0,114,5,0,0,0,114,187,0,0,0, - 212,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, + 213,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, 1,16,1,13,1,11,2,3,1,19,1,13,1,5,2,16, 1,3,1,19,1,13,1,5,2,3,1,9,1,12,1,13, 1,19,1,5,2,9,1,7,1,15,1,6,1,7,1,15, @@ -1289,7 +1289,7 @@ 199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206, 0,0,0,114,187,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, - 0,154,2,0,0,115,14,0,0,0,12,2,12,8,12,13, + 0,155,2,0,0,115,14,0,0,0,12,2,12,8,12,13, 12,10,12,7,12,10,18,8,114,194,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,112,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1317,7 +1317,7 @@ 32,32,32,32,32,32,102,105,110,100,101,114,46,78,41,2, 114,106,0,0,0,114,35,0,0,0,41,3,114,108,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,13, + 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,14, 3,0,0,115,4,0,0,0,0,3,9,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, @@ -1327,7 +1327,7 @@ 41,2,218,9,95,95,99,108,97,115,115,95,95,114,118,0, 0,0,41,2,114,108,0,0,0,218,5,111,116,104,101,114, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 6,95,95,101,113,95,95,19,3,0,0,115,4,0,0,0, + 6,95,95,101,113,95,95,20,3,0,0,115,4,0,0,0, 0,1,18,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,26,0,0, @@ -1336,7 +1336,7 @@ 218,4,104,97,115,104,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,8,95,95,104,97,115,104,95,95, - 23,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 24,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,22,0,0,0,116,0,0,116,1,0, @@ -1350,7 +1350,7 @@ 32,32,32,32,32,32,32,32,41,3,218,5,115,117,112,101, 114,114,210,0,0,0,114,193,0,0,0,41,2,114,108,0, 0,0,114,126,0,0,0,41,1,114,211,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,193,0,0,0,26,3,0, + 0,0,0,114,5,0,0,0,114,193,0,0,0,27,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, @@ -1361,7 +1361,7 @@ 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,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,157,0,0,0,38,3,0,0,115,2,0,0,0,0, + 0,114,157,0,0,0,39,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, @@ -1374,14 +1374,14 @@ 49,0,0,0,114,50,0,0,0,90,4,114,101,97,100,41, 3,114,108,0,0,0,114,35,0,0,0,114,54,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 200,0,0,0,43,3,0,0,115,4,0,0,0,0,2,21, + 200,0,0,0,44,3,0,0,115,4,0,0,0,0,2,21, 1,122,19,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,100,97,116,97,41,11,114,112,0,0,0,114,111,0, 0,0,114,113,0,0,0,114,114,0,0,0,114,185,0,0, 0,114,213,0,0,0,114,215,0,0,0,114,123,0,0,0, 114,193,0,0,0,114,157,0,0,0,114,200,0,0,0,114, 4,0,0,0,114,4,0,0,0,41,1,114,211,0,0,0, - 114,5,0,0,0,114,210,0,0,0,8,3,0,0,115,14, + 114,5,0,0,0,114,210,0,0,0,9,3,0,0,115,14, 0,0,0,12,3,6,2,12,6,12,4,12,3,24,12,18, 5,114,210,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,64,0,0,0, @@ -1396,15 +1396,15 @@ 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,5,0,0,0,67,0,0,0,115,34,0,0,0,116,0, - 0,124,1,0,131,1,0,125,2,0,124,2,0,106,1,0, - 100,1,0,124,2,0,106,2,0,100,2,0,105,2,0,83, + 0,124,1,0,131,1,0,125,2,0,100,1,0,124,2,0, + 106,1,0,100,2,0,124,2,0,106,2,0,105,2,0,83, 41,3,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,114,133,0,0,0,114,134,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,108,0,0,0, 114,35,0,0,0,114,208,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,197,0,0,0,53,3, + 4,0,0,0,114,5,0,0,0,114,197,0,0,0,54,3, 0,0,115,4,0,0,0,0,2,12,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, @@ -1415,7 +1415,7 @@ 114,97,0,0,0,114,198,0,0,0,41,5,114,108,0,0, 0,114,90,0,0,0,114,89,0,0,0,114,53,0,0,0, 114,42,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,199,0,0,0,58,3,0,0,115,4,0, + 5,0,0,0,114,199,0,0,0,59,3,0,0,115,4,0, 0,0,0,2,12,1,122,32,83,111,117,114,99,101,70,105, 108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, 98,121,116,101,99,111,100,101,114,220,0,0,0,105,182,1, @@ -1453,7 +1453,7 @@ 53,0,0,0,114,220,0,0,0,218,6,112,97,114,101,110, 116,114,94,0,0,0,114,27,0,0,0,114,23,0,0,0, 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,198,0,0,0,63,3,0,0,115,38,0, + 5,0,0,0,114,198,0,0,0,64,3,0,0,115,38,0, 0,0,0,2,18,1,6,2,22,1,18,1,17,2,19,1, 15,1,3,1,17,1,13,2,7,1,18,3,16,1,27,1, 3,1,16,1,17,1,18,2,122,25,83,111,117,114,99,101, @@ -1462,7 +1462,7 @@ 114,113,0,0,0,114,114,0,0,0,114,197,0,0,0,114, 199,0,0,0,114,198,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,218,0, - 0,0,49,3,0,0,115,8,0,0,0,12,2,6,2,12, + 0,0,50,3,0,0,115,8,0,0,0,12,2,6,2,12, 5,12,5,114,218,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,46,0, 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, @@ -1484,7 +1484,7 @@ 114,147,0,0,0,41,5,114,108,0,0,0,114,126,0,0, 0,114,35,0,0,0,114,53,0,0,0,114,209,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 187,0,0,0,96,3,0,0,115,8,0,0,0,0,1,15, + 187,0,0,0,97,3,0,0,115,8,0,0,0,0,1,15, 1,15,1,24,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, @@ -1494,13 +1494,13 @@ 32,115,111,117,114,99,101,32,99,111,100,101,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,202, - 0,0,0,102,3,0,0,115,2,0,0,0,0,2,122,31, + 0,0,0,103,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,112,0,0,0,114,111,0,0,0,114,113,0,0, 0,114,114,0,0,0,114,187,0,0,0,114,202,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,223,0,0,0,92,3,0,0,115,6,0, + 5,0,0,0,114,223,0,0,0,93,3,0,0,115,6,0, 0,0,12,2,6,2,12,6,114,223,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,136,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1525,7 +1525,7 @@ 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,119,3,0,0,115,4,0, + 5,0,0,0,114,185,0,0,0,120,3,0,0,115,4,0, 0,0,0,1,9,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, @@ -1534,7 +1534,7 @@ 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, 41,1,78,41,2,114,211,0,0,0,114,118,0,0,0,41, 2,114,108,0,0,0,114,212,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,123, + 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,124, 3,0,0,115,4,0,0,0,0,1,18,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, @@ -1543,7 +1543,7 @@ 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, 3,114,214,0,0,0,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,215,0,0,0,127,3,0,0,115, + 0,114,5,0,0,0,114,215,0,0,0,128,3,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, @@ -1561,7 +1561,7 @@ 114,105,0,0,0,114,106,0,0,0,114,35,0,0,0,41, 3,114,108,0,0,0,114,164,0,0,0,114,190,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 186,0,0,0,130,3,0,0,115,10,0,0,0,0,2,6, + 186,0,0,0,131,3,0,0,115,10,0,0,0,0,2,6, 1,15,1,6,1,16,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, @@ -1578,7 +1578,7 @@ 12,101,120,101,99,95,100,121,110,97,109,105,99,114,105,0, 0,0,114,106,0,0,0,114,35,0,0,0,41,2,114,108, 0,0,0,114,190,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,191,0,0,0,138,3,0,0, + 0,0,114,5,0,0,0,114,191,0,0,0,139,3,0,0, 115,6,0,0,0,0,2,19,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, @@ -1597,7 +1597,7 @@ 78,114,4,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,4,0,0,0,114,5,0,0,0,250,9,60,103, - 101,110,101,120,112,114,62,147,3,0,0,115,2,0,0,0, + 101,110,101,120,112,114,62,148,3,0,0,115,2,0,0,0, 6,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, @@ -1605,7 +1605,7 @@ 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,108,0,0, 0,114,126,0,0,0,114,4,0,0,0,41,1,114,226,0, - 0,0,114,5,0,0,0,114,159,0,0,0,144,3,0,0, + 0,0,114,5,0,0,0,114,159,0,0,0,145,3,0,0, 115,6,0,0,0,0,2,19,1,18,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, @@ -1617,7 +1617,7 @@ 99,111,100,101,32,111,98,106,101,99,116,46,78,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,187,0, - 0,0,150,3,0,0,115,2,0,0,0,0,2,122,28,69, + 0,0,151,3,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, @@ -1627,7 +1627,7 @@ 118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100, 101,46,78,114,4,0,0,0,41,2,114,108,0,0,0,114, 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,202,0,0,0,154,3,0,0,115,2,0,0, + 0,0,0,114,202,0,0,0,155,3,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, @@ -1638,7 +1638,7 @@ 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,108,0,0,0, 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,157,0,0,0,158,3,0,0,115,2,0, + 5,0,0,0,114,157,0,0,0,159,3,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,112,0,0,0,114,111, @@ -1647,7 +1647,7 @@ 0,114,191,0,0,0,114,159,0,0,0,114,187,0,0,0, 114,202,0,0,0,114,123,0,0,0,114,157,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,224,0,0,0,111,3,0,0,115,20,0,0, + 0,0,0,114,224,0,0,0,112,3,0,0,115,20,0,0, 0,12,6,6,2,12,4,12,4,12,3,12,8,12,6,12, 6,12,4,12,4,114,224,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, @@ -1691,7 +1691,7 @@ 95,112,97,116,104,95,102,105,110,100,101,114,41,4,114,108, 0,0,0,114,106,0,0,0,114,35,0,0,0,218,11,112, 97,116,104,95,102,105,110,100,101,114,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,185,0,0,0,171,3, + 4,0,0,0,114,5,0,0,0,114,185,0,0,0,172,3, 0,0,115,8,0,0,0,0,1,9,1,9,1,21,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, @@ -1710,7 +1710,7 @@ 41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111, 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,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,177,3,0, + 110,116,95,112,97,116,104,95,110,97,109,101,115,178,3,0, 0,115,8,0,0,0,0,2,27,1,12,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, @@ -1724,7 +1724,7 @@ 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,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,233,0, - 0,0,187,3,0,0,115,4,0,0,0,0,1,18,1,122, + 0,0,188,3,0,0,115,4,0,0,0,0,1,18,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,3,0,0, @@ -1742,7 +1742,7 @@ 108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, 104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108, - 97,116,101,191,3,0,0,115,16,0,0,0,0,2,18,1, + 97,116,101,192,3,0,0,115,16,0,0,0,0,2,18,1, 15,1,21,3,27,1,9,1,12,1,9,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, @@ -1751,14 +1751,14 @@ 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,240, 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101, - 114,95,95,204,3,0,0,115,2,0,0,0,0,1,122,23, + 114,95,95,205,3,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,1,0,0,0,0,0,0,0, 1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0, 0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0, 83,41,1,78,41,2,114,31,0,0,0,114,240,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,207, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,208, 3,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,2, @@ -1768,7 +1768,7 @@ 123,33,114,125,41,41,2,114,47,0,0,0,114,232,0,0, 0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95, - 95,210,3,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,211,3,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,2,0,0,0,67,0,0,0,115,16,0,0,0,124, @@ -1776,7 +1776,7 @@ 1,78,41,1,114,240,0,0,0,41,2,114,108,0,0,0, 218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110, - 115,95,95,213,3,0,0,115,2,0,0,0,0,1,122,27, + 115,95,95,214,3,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,2,0,0,0,67,0,0,0, @@ -1784,7 +1784,7 @@ 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,232, 0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114, 245,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,163,0,0,0,216,3,0,0,115,2,0,0, + 0,0,0,114,163,0,0,0,217,3,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,13,114,112,0, 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, @@ -1792,7 +1792,7 @@ 114,240,0,0,0,114,242,0,0,0,114,243,0,0,0,114, 244,0,0,0,114,246,0,0,0,114,163,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,230,0,0,0,164,3,0,0,115,20,0,0,0, + 0,0,114,230,0,0,0,165,3,0,0,115,20,0,0,0, 12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3, 12,3,12,3,114,230,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,118, @@ -1811,7 +1811,7 @@ 41,1,78,41,2,114,230,0,0,0,114,232,0,0,0,41, 4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0, 114,236,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,222,3,0,0,115,2,0, + 5,0,0,0,114,185,0,0,0,223,3,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,2,0,0,0, @@ -1828,14 +1828,14 @@ 110,97,109,101,115,112,97,99,101,41,62,41,2,114,47,0, 0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,225, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,226, 3,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,0,83,41,2,78,84,114,4,0,0,0,41, 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,234, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,235, 3,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, @@ -1843,7 +1843,7 @@ 0,100,1,0,83,41,2,78,114,30,0,0,0,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0, - 0,0,237,3,0,0,115,2,0,0,0,0,1,122,27,95, + 0,0,238,3,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, @@ -1852,7 +1852,7 @@ 0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0, 0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2, 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,187,0,0,0,240,3, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,241,3, 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, @@ -1862,14 +1862,14 @@ 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, 78,114,4,0,0,0,41,2,114,108,0,0,0,114,164,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,186,0,0,0,243,3,0,0,115,0,0,0,0,122, + 0,114,186,0,0,0,244,3,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,0,83,41,1,78, 114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,191,0,0,0,246,3,0,0,115,2,0,0,0,0,1, + 114,191,0,0,0,247,3,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,3,0,0,0,67, @@ -1887,7 +1887,7 @@ 104,32,123,33,114,125,41,4,114,105,0,0,0,114,232,0, 0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108, 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,193,0,0,0,249,3,0,0, + 0,0,114,5,0,0,0,114,193,0,0,0,250,3,0,0, 115,4,0,0,0,0,7,16,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,112,0,0,0,114, @@ -1895,7 +1895,7 @@ 0,0,0,114,248,0,0,0,114,159,0,0,0,114,202,0, 0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0, 0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,221, + 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,222, 3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3, 12,3,12,3,12,3,12,3,114,247,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0, @@ -1933,7 +1933,7 @@ 114,95,99,97,99,104,101,218,6,118,97,108,117,101,115,114, 115,0,0,0,114,250,0,0,0,41,2,114,170,0,0,0, 218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,250,0,0,0,10,4,0,0, + 0,0,114,5,0,0,0,114,250,0,0,0,11,4,0,0, 115,6,0,0,0,0,4,22,1,15,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, @@ -1959,7 +1959,7 @@ 107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0, 90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111, - 107,115,18,4,0,0,115,16,0,0,0,0,7,25,1,16, + 107,115,19,4,0,0,115,16,0,0,0,0,7,25,1,16, 1,16,1,3,1,14,1,13,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, @@ -1991,7 +1991,7 @@ 0,0,114,255,0,0,0,41,3,114,170,0,0,0,114,35, 0,0,0,114,253,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,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,35,4,0, + 109,112,111,114,116,101,114,95,99,97,99,104,101,36,4,0, 0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3, 9,1,3,1,17,1,13,1,15,1,18,1,122,31,80,97, 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, @@ -2011,7 +2011,7 @@ 0,0,114,126,0,0,0,114,253,0,0,0,114,127,0,0, 0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,57,4,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,58,4,0,0, 115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12, 1,16,1,18,1,9,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, @@ -2047,7 +2047,7 @@ 101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116, 114,121,114,253,0,0,0,114,164,0,0,0,114,128,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,95,103,101,116,95,115,112,101,99,72,4,0,0,115, + 218,9,95,103,101,116,95,115,112,101,99,73,4,0,0,115, 40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1, 12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1, 9,1,12,1,12,5,17,2,18,1,9,1,122,20,80,97, @@ -2075,7 +2075,7 @@ 6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0, 114,180,0,0,0,114,164,0,0,0,114,4,1,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181, - 0,0,0,104,4,0,0,115,26,0,0,0,0,4,12,1, + 0,0,0,105,4,0,0,115,26,0,0,0,0,4,12,1, 9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1, 24,1,4,2,7,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, @@ -2097,7 +2097,7 @@ 114,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 182,0,0,0,126,4,0,0,115,8,0,0,0,0,8,18, + 182,0,0,0,127,4,0,0,115,8,0,0,0,0,8,18, 1,12,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,12,114, 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, @@ -2105,7 +2105,7 @@ 0,0,114,1,1,0,0,114,2,1,0,0,114,5,1,0, 0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 249,0,0,0,6,4,0,0,115,22,0,0,0,12,2,6, + 249,0,0,0,7,4,0,0,115,22,0,0,0,12,2,6, 2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21, 21,3,1,114,249,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,133,0, @@ -2154,7 +2154,7 @@ 0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0, 0,0,41,2,114,22,0,0,0,114,225,0,0,0,41,1, 114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 227,0,0,0,155,4,0,0,115,2,0,0,0,6,0,122, + 227,0,0,0,156,4,0,0,115,2,0,0,0,6,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,58,0,0,0,114,29,0,0, @@ -2167,7 +2167,7 @@ 111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108, 111,97,100,101,114,115,114,166,0,0,0,114,4,0,0,0, 41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0, - 0,149,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 0,150,4,0,0,115,16,0,0,0,0,4,6,1,19,1, 36,1,9,2,15,1,9,1,12,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, @@ -2177,7 +2177,7 @@ 114,121,32,109,116,105,109,101,46,114,29,0,0,0,78,114, 87,0,0,0,41,1,114,8,1,0,0,41,1,114,108,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,250,0,0,0,163,4,0,0,115,2,0,0,0,0, + 0,114,250,0,0,0,164,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, @@ -2201,7 +2201,7 @@ 114,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41, 3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 124,0,0,0,169,4,0,0,115,8,0,0,0,0,7,15, + 124,0,0,0,170,4,0,0,115,8,0,0,0,0,7,15, 1,12,1,10,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,7,0,0,0,67,0, @@ -2212,7 +2212,7 @@ 0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114, 126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, 180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,5,1,0,0,181,4,0, + 0,0,0,114,5,0,0,0,114,5,1,0,0,182,4,0, 0,115,6,0,0,0,0,1,15,1,18,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, @@ -2276,7 +2276,7 @@ 0,114,165,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,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,181,0,0,0,186,4,0,0,115,68,0, + 5,0,0,0,114,181,0,0,0,187,4,0,0,115,68,0, 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1, 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2, 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2, @@ -2313,7 +2313,7 @@ 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22, 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112, - 62,4,5,0,0,115,2,0,0,0,9,0,122,41,70,105, + 62,5,5,0,0,115,2,0,0,0,9,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, @@ -2330,7 +2330,7 @@ 114,245,0,0,0,114,106,0,0,0,114,237,0,0,0,114, 225,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,13,1, - 0,0,231,4,0,0,115,34,0,0,0,0,2,9,1,3, + 0,0,232,4,0,0,115,34,0,0,0,0,2,9,1,3, 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24, 1,6,1,27,2,6,1,17,1,9,1,18,1,122,22,70, 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, @@ -2369,14 +2369,14 @@ 0,41,2,114,170,0,0,0,114,12,1,0,0,114,4,0, 0,0,114,5,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,16,5,0,0,115,6,0,0,0,0,2,12,1,18,1, + 114,17,5,0,0,115,6,0,0,0,0,2,12,1,18,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, 170,0,0,0,114,12,1,0,0,114,18,1,0,0,114,4, 0,0,0,41,2,114,170,0,0,0,114,12,1,0,0,114, - 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,6, + 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,7, 5,0,0,115,4,0,0,0,0,10,21,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, @@ -2385,7 +2385,7 @@ 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114, 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,244,0,0,0,24,5,0,0,115,2,0,0, + 0,0,0,114,244,0,0,0,25,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,15,114,112,0,0,0,114, 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185, @@ -2393,7 +2393,7 @@ 0,0,114,124,0,0,0,114,5,1,0,0,114,181,0,0, 0,114,13,1,0,0,114,183,0,0,0,114,19,1,0,0, 114,244,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,6,1,0,0,140,4, + 4,0,0,0,114,5,0,0,0,114,6,1,0,0,141,4, 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6, 2,12,12,12,5,15,45,12,31,18,18,114,6,1,0,0, 99,4,0,0,0,0,0,0,0,6,0,0,0,11,0,0, @@ -2420,7 +2420,7 @@ 97,116,104,110,97,109,101,114,127,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,14,95,102,105,120,95,117,112,95,109,111,100,117,108,101, - 30,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, + 31,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, 1,6,1,12,1,12,1,18,2,15,1,6,1,21,1,3, 1,10,1,10,1,10,1,14,1,13,2,114,24,1,0,0, 99,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0, @@ -2440,7 +2440,7 @@ 0,0,0,114,74,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,5,0,0,0,114,161,0,0,0,53,5,0,0, + 0,0,114,5,0,0,0,114,161,0,0,0,54,5,0,0, 115,8,0,0,0,0,5,18,1,12,1,12,1,114,161,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,70,2,0,0,124,0,0,97, @@ -2502,7 +2502,7 @@ 1,113,3,0,100,1,0,83,41,2,114,29,0,0,0,78, 41,1,114,31,0,0,0,41,2,114,22,0,0,0,114,77, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,227,0,0,0,89,5,0,0,115,2,0,0,0, + 0,0,114,227,0,0,0,90,5,0,0,115,2,0,0,0, 6,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,59,0, 0,0,122,30,105,109,112,111,114,116,108,105,98,32,114,101, @@ -2532,7 +2532,7 @@ 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,5,0,0,0,218,6,95,115,101,116,117,112,64,5,0, + 114,5,0,0,0,218,6,95,115,101,116,117,112,65,5,0, 0,115,82,0,0,0,0,8,6,1,9,1,9,3,13,1, 13,1,15,1,18,2,13,1,20,3,33,1,19,2,31,1, 10,1,15,1,13,1,4,2,3,1,15,1,5,1,13,1, @@ -2558,7 +2558,7 @@ 0,0,114,249,0,0,0,114,218,0,0,0,41,2,114,32, 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,5,0,0,0,218,8,95,105,110,115,116,97,108,108,132, + 114,5,0,0,0,218,8,95,105,110,115,116,97,108,108,133, 5,0,0,115,16,0,0,0,0,2,10,1,9,1,28,1, 15,1,16,1,16,4,9,1,114,35,1,0,0,41,3,122, 3,119,105,110,114,1,0,0,0,114,2,0,0,0,41,57, @@ -2588,7 +2588,7 @@ 5,0,0,0,218,8,60,109,111,100,117,108,101,62,8,0, 0,0,115,100,0,0,0,6,17,6,3,12,12,12,5,12, 5,12,6,12,12,12,10,12,9,12,5,12,7,15,22,15, - 108,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, + 109,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, 44,12,33,12,19,12,12,12,12,18,8,12,28,12,17,21, 55,21,12,18,10,12,14,9,3,12,1,15,65,19,64,19, 28,22,110,19,41,25,43,25,16,6,3,25,53,19,57,19, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 21:37:54 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 28 May 2015 19:37:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMDk1?= =?utf-8?q?=3A_Fixed_HTTPConnection=2Eset=5Ftunnel_with_default_port=2E__T?= =?utf-8?q?he_port?= Message-ID: <20150528193754.4336.11102@psf.io> https://hg.python.org/cpython/rev/3b6e0720a69d changeset: 96341:3b6e0720a69d branch: 2.7 parent: 96336:17d3bbde60d2 user: Serhiy Storchaka date: Thu May 28 22:37:13 2015 +0300 summary: Issue #22095: Fixed HTTPConnection.set_tunnel with default port. The port value in the host header was set to "None". Patch by Demian Brecht. files: Lib/httplib.py | 7 +++---- Lib/test/test_httplib.py | 8 +++++--- Misc/NEWS | 3 +++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -772,8 +772,7 @@ if self.sock: raise RuntimeError("Can't setup tunnel for established connection.") - self._tunnel_host = host - self._tunnel_port = port + self._tunnel_host, self._tunnel_port = self._get_hostport(host, port) if headers: self._tunnel_headers = headers else: @@ -802,8 +801,8 @@ self.debuglevel = level def _tunnel(self): - (host, port) = self._get_hostport(self._tunnel_host, self._tunnel_port) - self.send("CONNECT %s:%d HTTP/1.0\r\n" % (host, port)) + self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host, + self._tunnel_port)) for header, value in self._tunnel_headers.iteritems(): self.send("%s: %s\r\n" % (header, value)) self.send("\r\n") diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -842,10 +842,12 @@ self.assertEqual(conn.sock.host, 'proxy.com') self.assertEqual(conn.sock.port, 80) - self.assertTrue('CONNECT destination.com' in conn.sock.data) - self.assertTrue('Host: destination.com' in conn.sock.data) + self.assertIn('CONNECT destination.com', conn.sock.data) + # issue22095 + self.assertNotIn('Host: destination.com:None', conn.sock.data) + self.assertIn('Host: destination.com', conn.sock.data) - self.assertTrue('Host: proxy.com' not in conn.sock.data) + self.assertNotIn('Host: proxy.com', conn.sock.data) conn.close() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Library ------- +- Issue #22095: Fixed HTTPConnection.set_tunnel with default port. The port + value in the host header was set to "None". Patch by Demian Brecht. + - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 21:40:21 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 19:40:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_remove_STORE?= =?utf-8?q?=5FMAP=2C_since_it=27s_unused?= Message-ID: <20150528194021.25413.16032@psf.io> https://hg.python.org/cpython/rev/ac891c518d4e changeset: 96342:ac891c518d4e branch: 3.5 parent: 96339:6f05f83c7010 user: Benjamin Peterson date: Thu May 28 14:40:08 2015 -0500 summary: remove STORE_MAP, since it's unused files: Doc/library/dis.rst | 4 ---- Include/opcode.h | 1 - Lib/opcode.py | 1 - Python/ceval.c | 15 --------------- Python/compile.c | 2 -- Python/opcode_targets.h | 2 +- 6 files changed, 1 insertions(+), 24 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -848,10 +848,6 @@ Pushes a try block from a try-except clause onto the block stack. *delta* points to the finally block. -.. opcode:: STORE_MAP - - Store a key and value pair in a dictionary. Pops the key and value while - leaving the dictionary on the stack. .. opcode:: LOAD_FAST (var_num) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -32,7 +32,6 @@ #define GET_AITER 50 #define GET_ANEXT 51 #define BEFORE_ASYNC_WITH 52 -#define STORE_MAP 54 #define INPLACE_ADD 55 #define INPLACE_SUBTRACT 56 #define INPLACE_MULTIPLY 57 diff --git a/Lib/opcode.py b/Lib/opcode.py --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -89,7 +89,6 @@ def_op('GET_ANEXT', 51) def_op('BEFORE_ASYNC_WITH', 52) -def_op('STORE_MAP', 54) def_op('INPLACE_ADD', 55) def_op('INPLACE_SUBTRACT', 56) def_op('INPLACE_MULTIPLY', 57) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2680,21 +2680,6 @@ DISPATCH(); } - TARGET(STORE_MAP) { - PyObject *key = TOP(); - PyObject *value = SECOND(); - PyObject *map = THIRD(); - int err; - STACKADJ(-2); - assert(PyDict_CheckExact(map)); - err = PyDict_SetItem(map, key, value); - Py_DECREF(value); - Py_DECREF(key); - if (err != 0) - goto error; - DISPATCH(); - } - TARGET(MAP_ADD) { PyObject *key = TOP(); PyObject *value = SECOND(); diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -903,8 +903,6 @@ return -1; case STORE_SUBSCR: return -3; - case STORE_MAP: - return -2; case DELETE_SUBSCR: return -2; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -53,7 +53,7 @@ &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&_unknown_opcode, - &&TARGET_STORE_MAP, + &&_unknown_opcode, &&TARGET_INPLACE_ADD, &&TARGET_INPLACE_SUBTRACT, &&TARGET_INPLACE_MULTIPLY, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 21:40:23 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 28 May 2015 19:40:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150528194021.83491.33551@psf.io> https://hg.python.org/cpython/rev/ddb402d8f5b9 changeset: 96343:ddb402d8f5b9 parent: 96340:ba9e4df5368c parent: 96342:ac891c518d4e user: Benjamin Peterson date: Thu May 28 14:40:15 2015 -0500 summary: merge 3.5 files: Doc/library/dis.rst | 4 ---- Include/opcode.h | 1 - Lib/opcode.py | 1 - Python/ceval.c | 15 --------------- Python/compile.c | 2 -- Python/opcode_targets.h | 2 +- 6 files changed, 1 insertions(+), 24 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -848,10 +848,6 @@ Pushes a try block from a try-except clause onto the block stack. *delta* points to the finally block. -.. opcode:: STORE_MAP - - Store a key and value pair in a dictionary. Pops the key and value while - leaving the dictionary on the stack. .. opcode:: LOAD_FAST (var_num) diff --git a/Include/opcode.h b/Include/opcode.h --- a/Include/opcode.h +++ b/Include/opcode.h @@ -32,7 +32,6 @@ #define GET_AITER 50 #define GET_ANEXT 51 #define BEFORE_ASYNC_WITH 52 -#define STORE_MAP 54 #define INPLACE_ADD 55 #define INPLACE_SUBTRACT 56 #define INPLACE_MULTIPLY 57 diff --git a/Lib/opcode.py b/Lib/opcode.py --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -89,7 +89,6 @@ def_op('GET_ANEXT', 51) def_op('BEFORE_ASYNC_WITH', 52) -def_op('STORE_MAP', 54) def_op('INPLACE_ADD', 55) def_op('INPLACE_SUBTRACT', 56) def_op('INPLACE_MULTIPLY', 57) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2680,21 +2680,6 @@ DISPATCH(); } - TARGET(STORE_MAP) { - PyObject *key = TOP(); - PyObject *value = SECOND(); - PyObject *map = THIRD(); - int err; - STACKADJ(-2); - assert(PyDict_CheckExact(map)); - err = PyDict_SetItem(map, key, value); - Py_DECREF(value); - Py_DECREF(key); - if (err != 0) - goto error; - DISPATCH(); - } - TARGET(MAP_ADD) { PyObject *key = TOP(); PyObject *value = SECOND(); diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -903,8 +903,6 @@ return -1; case STORE_SUBSCR: return -3; - case STORE_MAP: - return -2; case DELETE_SUBSCR: return -2; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -53,7 +53,7 @@ &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&_unknown_opcode, - &&TARGET_STORE_MAP, + &&_unknown_opcode, &&TARGET_INPLACE_ADD, &&TARGET_INPLACE_SUBTRACT, &&TARGET_INPLACE_MULTIPLY, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 23:10:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 21:10:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150528211051.25425.96670@psf.io> https://hg.python.org/cpython/rev/bce40ff299aa changeset: 96345:bce40ff299aa parent: 96343:ddb402d8f5b9 parent: 96344:3254a3c0acb4 user: Yury Selivanov date: Thu May 28 17:09:38 2015 -0400 summary: Merge 3.5 files: Doc/whatsnew/3.5.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -805,6 +805,14 @@ Deprecated ========== +New Keywords +------------ + +``async`` and ``await`` are not recommended to be used as variable, class or +function names. Introduced by :pep:`492` in Python 3.5, they will become +proper keywords in Python 3.7. + + Unsupported Operating Systems ----------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 23:10:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 21:10:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_docs/whatsnew?= =?utf-8?q?=3A_Mention_that_=27async=27_and_=27await=27_will_be_keywords_i?= =?utf-8?q?n_3=2E7?= Message-ID: <20150528211051.18664.98203@psf.io> https://hg.python.org/cpython/rev/3254a3c0acb4 changeset: 96344:3254a3c0acb4 branch: 3.5 parent: 96342:ac891c518d4e user: Yury Selivanov date: Thu May 28 17:09:14 2015 -0400 summary: docs/whatsnew: Mention that 'async' and 'await' will be keywords in 3.7 files: Doc/whatsnew/3.5.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -805,6 +805,14 @@ Deprecated ========== +New Keywords +------------ + +``async`` and ``await`` are not recommended to be used as variable, class or +function names. Introduced by :pep:`492` in Python 3.5, they will become +proper keywords in Python 3.7. + + Unsupported Operating Systems ----------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu May 28 23:10:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 28 May 2015 21:10:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_docs/whatsnew/3=2E6=3A_Men?= =?utf-8?q?tion_that_=27async=27_and_=27await=27_will_be_keywords_in_3=2E7?= Message-ID: <20150528211051.18684.3241@psf.io> https://hg.python.org/cpython/rev/abe0c5a78d68 changeset: 96346:abe0c5a78d68 user: Yury Selivanov date: Thu May 28 17:10:29 2015 -0400 summary: docs/whatsnew/3.6: Mention that 'async' and 'await' will be keywords in 3.7 files: Doc/whatsnew/3.6.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -113,6 +113,14 @@ Deprecated ========== +New Keywords +------------ + +``async`` and ``await`` are not recommended to be used as variable, class or +function names. Introduced by :pep:`492` in Python 3.5, they will become +proper keywords in Python 3.7. + + Deprecated Python modules, functions and methods ------------------------------------------------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 00:30:22 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 28 May 2015 22:30:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_Windows_build_for_3?= =?utf-8?q?=2E6?= Message-ID: <20150528223021.83481.57563@psf.io> https://hg.python.org/cpython/rev/c9d89d3f3ff1 changeset: 96347:c9d89d3f3ff1 user: Zachary Ware date: Thu May 28 17:30:03 2015 -0500 summary: Update Windows build for 3.6 files: PC/example_nt/example.vcproj | 4 +- PC/pyconfig.h | 4 +- PC/python3.def | 1402 +++++++++++----------- PCbuild/prepare_ssl.bat | 4 +- 4 files changed, 707 insertions(+), 707 deletions(-) diff --git a/PC/example_nt/example.vcproj b/PC/example_nt/example.vcproj --- a/PC/example_nt/example.vcproj +++ b/PC/example_nt/example.vcproj @@ -39,7 +39,7 @@ https://hg.python.org/peps/rev/0c72052a317b changeset: 5881:0c72052a317b user: Larry Hastings date: Thu May 28 23:21:18 2015 -0700 summary: Updated Python 3.5 release schedule to add the new beta 2. files: pep-0478.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -41,8 +41,9 @@ - 3.5.0 alpha 3: March 29, 2015 - 3.5.0 alpha 4: April 19, 2015 - 3.5.0 beta 1: May 24, 2015 -- 3.5.0 beta 2: July 5, 2015 -- 3.5.0 beta 3: July 26, 2015 +- 3.5.0 beta 2: May 31, 2015 +- 3.5.0 beta 3: July 5, 2015 +- 3.5.0 beta 4: July 26, 2015 - 3.5.0 candidate 1: August 9, 2015 - 3.5.0 candidate 2: August 23, 2015 - 3.5.0 candidate 3: September 6, 2015 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri May 29 10:32:49 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 29 May 2015 08:32:49 +0000 Subject: [Python-checkins] =?utf-8?q?release=3A_Fix_add-to-pydotorg=2Epy_s?= =?utf-8?q?o_it_handles_all_the_new_Windows_binaries=2E?= Message-ID: <20150529083249.24071.58293@psf.io> https://hg.python.org/release/rev/436c71fbc19d changeset: 97:436c71fbc19d user: Larry Hastings date: Fri May 29 01:32:45 2015 -0700 summary: Fix add-to-pydotorg.py so it handles all the new Windows binaries. Also, removed an unused function (I think it got inlined). files: add-to-pydotorg.py | 26 ++++++++++++-------------- release.py | 9 +++++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/add-to-pydotorg.py b/add-to-pydotorg.py --- a/add-to-pydotorg.py +++ b/add-to-pydotorg.py @@ -55,7 +55,19 @@ (rx(r'\.tar\.xz$'), ('XZ compressed source tarball', 3, '')), (rx(r'\.amd64\.msi$'), ('Windows x86-64 MSI installer', 1, 'for AMD64/EM64T/x64, not Itanium processors')), + (rx(r'-amd64-webinstall\.exe$'), ('Windows x86-64 web-based installer', 1, + 'for AMD64/EM64T/x64, not Itanium processors')), + (rx(r'-embed-amd64\.zip$'), ('Windows x86-64 embeddable zip file', 1, + 'for AMD64/EM64T/x64, not Itanium processors')), + (rx(r'-embed-amd64\.exe$'), ('Windows x86-64 embeddable installer', 1, + 'for AMD64/EM64T/x64, not Itanium processors')), + (rx(r'-amd64\.exe$'), ('Windows x86-64 executable installer', 1, + 'for AMD64/EM64T/x64, not Itanium processors')), (rx(r'\.msi$'), ('Windows x86 MSI installer', 1, '')), + (rx(r'-embed-win32\.zip$'), ('Windows x86 embeddable zip file', 1, '')), + (rx(r'-embed-win32\.exe$'), ('Windows x86 embeddable installer', 1, '')), + (rx(r'-webinstall\.exe$'), ('Windows x86 web-based installer', 1, '')), + (rx(r'\.exe$'), ('Windows x86 executable installer', 1, '')), (rx(r'\.chm$'), ('Windows help file', 1, '')), (rx(r'amd64-pdb\.zip$'), ('Windows debug information files for 64-bit binaries', 1, '')), (rx(r'-pdb\.zip$'), ('Windows debug information files', 1, '')), @@ -90,20 +102,6 @@ m = tag_cre.match(release) return ".".join(m.groups()[:3]) -def build_release_dict(release, reldate, is_latest, page_pk): - """Return a dictionary with all needed fields for a Release object.""" - return dict( - name = 'Python ' + release, - slug = slug_for(release), - version = int(release[0]), - is_published = True, - release_date = reldate, # in "YYYY-MM-ddTHH:MM:SS" - pre_release = bool(release[5:]), - release_page = '/api/v1/pages/page/%s/' % page_pk, # XXX doesn't work yet - release_notes_url = changelog_for(release), - show_on_download_page = True, - ) - def build_file_dict(release, rfile, rel_pk, file_desc, os_pk, add_desc): """Return a dictionary with all needed fields for a ReleaseFile object.""" d = dict( diff --git a/release.py b/release.py --- a/release.py +++ b/release.py @@ -34,7 +34,7 @@ def run_cmd(args, silent=False): cmd = SPACE.join(args) - if not silent: + if 1: # not silent: print('Executing %s' % cmd) try: if silent: @@ -250,9 +250,9 @@ except OSError: pass - if tag.is_final: + if 1 or tag.is_final: docdist = build_docs() - if tag.is_final: + if 1 or tag.is_final: shutil.copytree(docdist, 'docs') with changed_dir(os.path.join(archivename, 'Doc')): @@ -283,7 +283,8 @@ with tempfile.TemporaryDirectory() as venv: run_cmd(['virtualenv', venv]) pip = os.path.join(venv, 'bin', 'pip') - run_cmd([pip, 'install', 'Sphinx']) + run_cmd([pip, 'install', 'Sphinx==1.2.3']) + # run_cmd([pip, 'install', 'Sphinx']) sphinx_build = os.path.join(venv, 'bin', 'sphinx-build') with changed_dir('Doc'): run_cmd(['make', 'dist', 'SPHINXBUILD=' + sphinx_build]) -- Repository URL: https://hg.python.org/release From solipsis at pitrou.net Fri May 29 10:51:18 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 29 May 2015 08:51:18 +0000 Subject: [Python-checkins] Daily reference leaks (c9d89d3f3ff1): sum=226 Message-ID: <20150529085118.89797.65108@psf.io> results for c9d89d3f3ff1 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogCyEmV_', '--timeout', '7200'] From python-checkins at python.org Fri May 29 15:01:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 13:01:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24315=3A_Make_collections=2Eabc=2ECoroutine_derive?= =?utf-8?q?d_from_Awaitable?= Message-ID: <20150529130153.18169.14111@psf.io> https://hg.python.org/cpython/rev/a7a9c8631d0e changeset: 96349:a7a9c8631d0e parent: 96347:c9d89d3f3ff1 parent: 96348:968af3838553 user: Yury Selivanov date: Fri May 29 09:01:47 2015 -0400 summary: Issue 24315: Make collections.abc.Coroutine derived from Awaitable (Merge 3.5) files: Doc/library/collections.abc.rst | 10 +- Lib/_collections_abc.py | 49 +++++++++------ Lib/test/test_asyncio/test_pep492.py | 14 +-- Lib/test/test_collections.py | 34 ++++++++-- 4 files changed, 67 insertions(+), 40 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -82,7 +82,7 @@ :class:`Set` ``__iter__`` :class:`ValuesView` :class:`MappingView` ``__contains__``, ``__iter__`` :class:`Awaitable` ``__await__`` -:class:`Coroutine` ``send``, ``throw`` ``close`` +:class:`Coroutine` :class:`Awaitable` ``send``, ``throw`` ``close`` :class:`AsyncIterable` ``__aiter__`` :class:`AsyncIterator` :class:`AsyncIterable` ``__anext__`` ``__aiter__`` ========================== ====================== ======================= ==================================================== @@ -166,10 +166,10 @@ ABC for coroutine compatible classes that implement a subset of generator methods defined in :pep:`342`, namely: - :meth:`~generator.send`, :meth:`~generator.throw` and - :meth:`~generator.close` methods. All :class:`Coroutine` instances - are also instances of :class:`Awaitable`. See also the definition - of :term:`coroutine`. + :meth:`~generator.send`, :meth:`~generator.throw`, + :meth:`~generator.close` methods. :meth:`__await__` must also be + implemented. All :class:`Coroutine` instances are also instances of + :class:`Awaitable`. See also the definition of :term:`coroutine`. .. versionadded:: 3.5 diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -75,7 +75,7 @@ return NotImplemented -class _CoroutineMeta(ABCMeta): +class _AwaitableMeta(ABCMeta): def __instancecheck__(cls, instance): # 0x80 = CO_COROUTINE @@ -92,7 +92,26 @@ return super().__instancecheck__(instance) -class Coroutine(metaclass=_CoroutineMeta): +class Awaitable(metaclass=_AwaitableMeta): + + __slots__ = () + + @abstractmethod + def __await__(self): + yield + + @classmethod + def __subclasshook__(cls, C): + if cls is Awaitable: + for B in C.__mro__: + if "__await__" in B.__dict__: + if B.__dict__["__await__"]: + return True + break + return NotImplemented + + +class Coroutine(Awaitable): __slots__ = () @@ -126,27 +145,19 @@ else: raise RuntimeError("coroutine ignored GeneratorExit") - -class Awaitable(metaclass=_CoroutineMeta): - - __slots__ = () - - @abstractmethod - def __await__(self): - yield - @classmethod def __subclasshook__(cls, C): - if cls is Awaitable: - for B in C.__mro__: - if "__await__" in B.__dict__: - if B.__dict__["__await__"]: - return True - break + if cls is Coroutine: + mro = C.__mro__ + for method in ('__await__', 'send', 'throw', 'close'): + for base in mro: + if method in base.__dict__: + break + else: + return NotImplemented + return True return NotImplemented -Awaitable.register(Coroutine) - class AsyncIterable(metaclass=ABCMeta): diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -97,18 +97,14 @@ finally: f.close() # silence warning - class FakeCoro(collections.abc.Coroutine): + # Test that asyncio.iscoroutine() uses collections.abc.Coroutine + class FakeCoro: def send(self, value): pass def throw(self, typ, val=None, tb=None): pass + def close(self): pass + def __await__(self): yield - fc = FakeCoro() - try: - self.assertTrue(asyncio.iscoroutine(fc)) - finally: - # To make sure that ABCMeta caches are freed - # from FakeCoro ASAP. - fc = FakeCoro = None - support.gc_collect() + self.assertTrue(asyncio.iscoroutine(FakeCoro())) if __name__ == '__main__': diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -496,6 +496,8 @@ return value def throw(self, typ, val=None, tb=None): super().throw(typ, val, tb) + def __await__(self): + yield non_samples = [None, int(), gen(), object()] for x in non_samples: @@ -515,13 +517,7 @@ self.assertIsInstance(c, Awaitable) c.close() # awoid RuntimeWarning that coro() was not awaited - class CoroLike: - def send(self, value): - pass - def throw(self, typ, val=None, tb=None): - pass - def close(self): - pass + class CoroLike: pass Coroutine.register(CoroLike) self.assertTrue(isinstance(CoroLike(), Awaitable)) self.assertTrue(issubclass(CoroLike, Awaitable)) @@ -548,6 +544,8 @@ return value def throw(self, typ, val=None, tb=None): super().throw(typ, val, tb) + def __await__(self): + yield non_samples = [None, int(), gen(), object(), Bar()] for x in non_samples: @@ -567,6 +565,28 @@ self.assertIsInstance(c, Coroutine) c.close() # awoid RuntimeWarning that coro() was not awaited + class CoroLike: + def send(self, value): + pass + def throw(self, typ, val=None, tb=None): + pass + def close(self): + pass + def __await__(self): + pass + self.assertTrue(isinstance(CoroLike(), Coroutine)) + self.assertTrue(issubclass(CoroLike, Coroutine)) + + class CoroLike: + def send(self, value): + pass + def close(self): + pass + def __await__(self): + pass + self.assertFalse(isinstance(CoroLike(), Coroutine)) + self.assertFalse(issubclass(CoroLike, Coroutine)) + def test_Hashable(self): # Check some non-hashables non_samples = [bytearray(), list(), set(), dict()] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 15:01:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 13:01:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQzMTU6?= =?utf-8?q?_Make_collections=2Eabc=2ECoroutine_derived_from_Awaitable?= Message-ID: <20150529130153.83473.42437@psf.io> https://hg.python.org/cpython/rev/968af3838553 changeset: 96348:968af3838553 branch: 3.5 parent: 96344:3254a3c0acb4 user: Yury Selivanov date: Fri May 29 09:01:29 2015 -0400 summary: Issue 24315: Make collections.abc.Coroutine derived from Awaitable files: Doc/library/collections.abc.rst | 10 +- Lib/_collections_abc.py | 49 +++++++++------ Lib/test/test_asyncio/test_pep492.py | 14 +-- Lib/test/test_collections.py | 34 ++++++++-- 4 files changed, 67 insertions(+), 40 deletions(-) diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -82,7 +82,7 @@ :class:`Set` ``__iter__`` :class:`ValuesView` :class:`MappingView` ``__contains__``, ``__iter__`` :class:`Awaitable` ``__await__`` -:class:`Coroutine` ``send``, ``throw`` ``close`` +:class:`Coroutine` :class:`Awaitable` ``send``, ``throw`` ``close`` :class:`AsyncIterable` ``__aiter__`` :class:`AsyncIterator` :class:`AsyncIterable` ``__anext__`` ``__aiter__`` ========================== ====================== ======================= ==================================================== @@ -166,10 +166,10 @@ ABC for coroutine compatible classes that implement a subset of generator methods defined in :pep:`342`, namely: - :meth:`~generator.send`, :meth:`~generator.throw` and - :meth:`~generator.close` methods. All :class:`Coroutine` instances - are also instances of :class:`Awaitable`. See also the definition - of :term:`coroutine`. + :meth:`~generator.send`, :meth:`~generator.throw`, + :meth:`~generator.close` methods. :meth:`__await__` must also be + implemented. All :class:`Coroutine` instances are also instances of + :class:`Awaitable`. See also the definition of :term:`coroutine`. .. versionadded:: 3.5 diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -75,7 +75,7 @@ return NotImplemented -class _CoroutineMeta(ABCMeta): +class _AwaitableMeta(ABCMeta): def __instancecheck__(cls, instance): # 0x80 = CO_COROUTINE @@ -92,7 +92,26 @@ return super().__instancecheck__(instance) -class Coroutine(metaclass=_CoroutineMeta): +class Awaitable(metaclass=_AwaitableMeta): + + __slots__ = () + + @abstractmethod + def __await__(self): + yield + + @classmethod + def __subclasshook__(cls, C): + if cls is Awaitable: + for B in C.__mro__: + if "__await__" in B.__dict__: + if B.__dict__["__await__"]: + return True + break + return NotImplemented + + +class Coroutine(Awaitable): __slots__ = () @@ -126,27 +145,19 @@ else: raise RuntimeError("coroutine ignored GeneratorExit") - -class Awaitable(metaclass=_CoroutineMeta): - - __slots__ = () - - @abstractmethod - def __await__(self): - yield - @classmethod def __subclasshook__(cls, C): - if cls is Awaitable: - for B in C.__mro__: - if "__await__" in B.__dict__: - if B.__dict__["__await__"]: - return True - break + if cls is Coroutine: + mro = C.__mro__ + for method in ('__await__', 'send', 'throw', 'close'): + for base in mro: + if method in base.__dict__: + break + else: + return NotImplemented + return True return NotImplemented -Awaitable.register(Coroutine) - class AsyncIterable(metaclass=ABCMeta): diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -97,18 +97,14 @@ finally: f.close() # silence warning - class FakeCoro(collections.abc.Coroutine): + # Test that asyncio.iscoroutine() uses collections.abc.Coroutine + class FakeCoro: def send(self, value): pass def throw(self, typ, val=None, tb=None): pass + def close(self): pass + def __await__(self): yield - fc = FakeCoro() - try: - self.assertTrue(asyncio.iscoroutine(fc)) - finally: - # To make sure that ABCMeta caches are freed - # from FakeCoro ASAP. - fc = FakeCoro = None - support.gc_collect() + self.assertTrue(asyncio.iscoroutine(FakeCoro())) if __name__ == '__main__': diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -496,6 +496,8 @@ return value def throw(self, typ, val=None, tb=None): super().throw(typ, val, tb) + def __await__(self): + yield non_samples = [None, int(), gen(), object()] for x in non_samples: @@ -515,13 +517,7 @@ self.assertIsInstance(c, Awaitable) c.close() # awoid RuntimeWarning that coro() was not awaited - class CoroLike: - def send(self, value): - pass - def throw(self, typ, val=None, tb=None): - pass - def close(self): - pass + class CoroLike: pass Coroutine.register(CoroLike) self.assertTrue(isinstance(CoroLike(), Awaitable)) self.assertTrue(issubclass(CoroLike, Awaitable)) @@ -548,6 +544,8 @@ return value def throw(self, typ, val=None, tb=None): super().throw(typ, val, tb) + def __await__(self): + yield non_samples = [None, int(), gen(), object(), Bar()] for x in non_samples: @@ -567,6 +565,28 @@ self.assertIsInstance(c, Coroutine) c.close() # awoid RuntimeWarning that coro() was not awaited + class CoroLike: + def send(self, value): + pass + def throw(self, typ, val=None, tb=None): + pass + def close(self): + pass + def __await__(self): + pass + self.assertTrue(isinstance(CoroLike(), Coroutine)) + self.assertTrue(issubclass(CoroLike, Coroutine)) + + class CoroLike: + def send(self, value): + pass + def close(self): + pass + def __await__(self): + pass + self.assertFalse(isinstance(CoroLike(), Coroutine)) + self.assertFalse(issubclass(CoroLike, Coroutine)) + def test_Hashable(self): # Check some non-hashables non_samples = [bytearray(), list(), set(), dict()] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 15:06:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 13:06:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24316=3A_Fix_types=2Ecoroutine=28=29_to_accept_obj?= =?utf-8?q?ects_from_Cython?= Message-ID: <20150529130634.4330.11944@psf.io> https://hg.python.org/cpython/rev/748c55375225 changeset: 96351:748c55375225 parent: 96349:a7a9c8631d0e parent: 96350:7356f71fb0a4 user: Yury Selivanov date: Fri May 29 09:06:24 2015 -0400 summary: Issue 24316: Fix types.coroutine() to accept objects from Cython (Merge 3.5) files: Lib/test/test_types.py | 32 +++++++++++++- Lib/types.py | 66 +++++++++++++++++++---------- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1196,11 +1196,39 @@ pass def bar(): pass - samples = [Foo, Foo(), bar, None, int, 1] + samples = [None, 1, object()] for sample in samples: - with self.assertRaisesRegex(TypeError, 'expects a generator'): + with self.assertRaisesRegex(TypeError, + 'types.coroutine.*expects a callable'): types.coroutine(sample) + def test_wrong_func(self): + @types.coroutine + def foo(): + pass + @types.coroutine + def gen(): + def _gen(): yield + return _gen() + + for sample in (foo, gen): + with self.assertRaisesRegex(TypeError, + 'callable wrapped .* non-coroutine'): + sample() + + def test_duck_coro(self): + class CoroLike: + def send(self): pass + def throw(self): pass + def close(self): pass + def __await__(self): pass + + coro = CoroLike() + @types.coroutine + def foo(): + return coro + self.assertIs(coro, foo()) + def test_genfunc(self): def gen(): yield diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -43,30 +43,6 @@ del sys, _f, _g, _C, # Not for export -_CO_GENERATOR = 0x20 -_CO_ITERABLE_COROUTINE = 0x100 - -def coroutine(func): - """Convert regular generator function to a coroutine.""" - - # TODO: Implement this in C. - - if (not isinstance(func, (FunctionType, MethodType)) or - not isinstance(getattr(func, '__code__', None), CodeType) or - not (func.__code__.co_flags & _CO_GENERATOR)): - raise TypeError('coroutine() expects a generator function') - - co = func.__code__ - func.__code__ = CodeType( - co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, - co.co_flags | _CO_ITERABLE_COROUTINE, - co.co_code, - co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, - co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) - - return func - - # Provide a PEP 3115 compliant mechanism for class creation def new_class(name, bases=(), kwds=None, exec_body=None): """Create a class object dynamically using the appropriate metaclass.""" @@ -182,4 +158,46 @@ return result +import functools as _functools +import collections.abc as _collections_abc + +def coroutine(func): + """Convert regular generator function to a coroutine.""" + + # We don't want to import 'dis' or 'inspect' just for + # these constants. + _CO_GENERATOR = 0x20 + _CO_ITERABLE_COROUTINE = 0x100 + + if not callable(func): + raise TypeError('types.coroutine() expects a callable') + + if (isinstance(func, FunctionType) and + isinstance(getattr(func, '__code__', None), CodeType) and + (func.__code__.co_flags & _CO_GENERATOR)): + + # TODO: Implement this in C. + co = func.__code__ + func.__code__ = CodeType( + co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, + co.co_stacksize, + co.co_flags | _CO_ITERABLE_COROUTINE, + co.co_code, + co.co_consts, co.co_names, co.co_varnames, co.co_filename, + co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, + co.co_cellvars) + return func + + @_functools.wraps(func) + def wrapped(*args, **kwargs): + coro = func(*args, **kwargs) + if not isinstance(coro, _collections_abc.Coroutine): + raise TypeError( + 'callable wrapped with types.coroutine() returned ' + 'non-coroutine: {!r}'.format(coro)) + return coro + + return wrapped + + __all__ = [n for n in globals() if n[:1] != '_'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 15:06:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 13:06:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQzMTY6?= =?utf-8?q?_Fix_types=2Ecoroutine=28=29_to_accept_objects_from_Cython?= Message-ID: <20150529130634.25407.6697@psf.io> https://hg.python.org/cpython/rev/7356f71fb0a4 changeset: 96350:7356f71fb0a4 branch: 3.5 parent: 96348:968af3838553 user: Yury Selivanov date: Fri May 29 09:06:05 2015 -0400 summary: Issue 24316: Fix types.coroutine() to accept objects from Cython files: Lib/test/test_types.py | 32 +++++++++++++- Lib/types.py | 66 +++++++++++++++++++---------- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1196,11 +1196,39 @@ pass def bar(): pass - samples = [Foo, Foo(), bar, None, int, 1] + samples = [None, 1, object()] for sample in samples: - with self.assertRaisesRegex(TypeError, 'expects a generator'): + with self.assertRaisesRegex(TypeError, + 'types.coroutine.*expects a callable'): types.coroutine(sample) + def test_wrong_func(self): + @types.coroutine + def foo(): + pass + @types.coroutine + def gen(): + def _gen(): yield + return _gen() + + for sample in (foo, gen): + with self.assertRaisesRegex(TypeError, + 'callable wrapped .* non-coroutine'): + sample() + + def test_duck_coro(self): + class CoroLike: + def send(self): pass + def throw(self): pass + def close(self): pass + def __await__(self): pass + + coro = CoroLike() + @types.coroutine + def foo(): + return coro + self.assertIs(coro, foo()) + def test_genfunc(self): def gen(): yield diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -43,30 +43,6 @@ del sys, _f, _g, _C, # Not for export -_CO_GENERATOR = 0x20 -_CO_ITERABLE_COROUTINE = 0x100 - -def coroutine(func): - """Convert regular generator function to a coroutine.""" - - # TODO: Implement this in C. - - if (not isinstance(func, (FunctionType, MethodType)) or - not isinstance(getattr(func, '__code__', None), CodeType) or - not (func.__code__.co_flags & _CO_GENERATOR)): - raise TypeError('coroutine() expects a generator function') - - co = func.__code__ - func.__code__ = CodeType( - co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, - co.co_flags | _CO_ITERABLE_COROUTINE, - co.co_code, - co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, - co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) - - return func - - # Provide a PEP 3115 compliant mechanism for class creation def new_class(name, bases=(), kwds=None, exec_body=None): """Create a class object dynamically using the appropriate metaclass.""" @@ -182,4 +158,46 @@ return result +import functools as _functools +import collections.abc as _collections_abc + +def coroutine(func): + """Convert regular generator function to a coroutine.""" + + # We don't want to import 'dis' or 'inspect' just for + # these constants. + _CO_GENERATOR = 0x20 + _CO_ITERABLE_COROUTINE = 0x100 + + if not callable(func): + raise TypeError('types.coroutine() expects a callable') + + if (isinstance(func, FunctionType) and + isinstance(getattr(func, '__code__', None), CodeType) and + (func.__code__.co_flags & _CO_GENERATOR)): + + # TODO: Implement this in C. + co = func.__code__ + func.__code__ = CodeType( + co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, + co.co_stacksize, + co.co_flags | _CO_ITERABLE_COROUTINE, + co.co_code, + co.co_consts, co.co_names, co.co_varnames, co.co_filename, + co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, + co.co_cellvars) + return func + + @_functools.wraps(func) + def wrapped(*args, **kwargs): + coro = func(*args, **kwargs) + if not isinstance(coro, _collections_abc.Coroutine): + raise TypeError( + 'callable wrapped with types.coroutine() returned ' + 'non-coroutine: {!r}'.format(coro)) + return coro + + return wrapped + + __all__ = [n for n in globals() if n[:1] != '_'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 22:19:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 20:19:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQzMTY6?= =?utf-8?q?_Wrap_gen_objects_returned_from_callables_in_types=2Ecoroutine?= Message-ID: <20150529201942.18662.14138@psf.io> https://hg.python.org/cpython/rev/8080b53342e8 changeset: 96352:8080b53342e8 branch: 3.5 parent: 96350:7356f71fb0a4 user: Yury Selivanov date: Fri May 29 16:19:18 2015 -0400 summary: Issue 24316: Wrap gen objects returned from callables in types.coroutine files: Lib/test/test_types.py | 45 ++++++++++++++++++++++------- Lib/types.py | 40 ++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1206,28 +1206,51 @@ @types.coroutine def foo(): pass - @types.coroutine - def gen(): - def _gen(): yield - return _gen() - - for sample in (foo, gen): - with self.assertRaisesRegex(TypeError, - 'callable wrapped .* non-coroutine'): - sample() + with self.assertRaisesRegex(TypeError, + 'callable wrapped .* non-coroutine'): + foo() def test_duck_coro(self): class CoroLike: def send(self): pass def throw(self): pass def close(self): pass - def __await__(self): pass + def __await__(self): return self coro = CoroLike() @types.coroutine def foo(): return coro - self.assertIs(coro, foo()) + self.assertIs(foo().__await__(), coro) + + def test_duck_gen(self): + class GenLike: + def send(self): pass + def throw(self): pass + def close(self): pass + def __iter__(self): return self + def __next__(self): pass + + gen = GenLike() + @types.coroutine + def foo(): + return gen + self.assertIs(foo().__await__(), gen) + + with self.assertRaises(AttributeError): + foo().gi_code + + def test_gen(self): + def gen(): yield + gen = gen() + @types.coroutine + def foo(): return gen + self.assertIs(foo().__await__(), gen) + + for name in ('__name__', '__qualname__', 'gi_code', + 'gi_running', 'gi_frame'): + self.assertIs(getattr(foo(), name), + getattr(gen, name)) def test_genfunc(self): def gen(): diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -166,32 +166,64 @@ # We don't want to import 'dis' or 'inspect' just for # these constants. - _CO_GENERATOR = 0x20 - _CO_ITERABLE_COROUTINE = 0x100 + CO_GENERATOR = 0x20 + CO_ITERABLE_COROUTINE = 0x100 if not callable(func): raise TypeError('types.coroutine() expects a callable') if (isinstance(func, FunctionType) and isinstance(getattr(func, '__code__', None), CodeType) and - (func.__code__.co_flags & _CO_GENERATOR)): + (func.__code__.co_flags & CO_GENERATOR)): # TODO: Implement this in C. co = func.__code__ func.__code__ = CodeType( co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, - co.co_flags | _CO_ITERABLE_COROUTINE, + co.co_flags | CO_ITERABLE_COROUTINE, co.co_code, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) return func + # The following code is primarily to support functions that + # return generator-like objects (for instance generators + # compiled with Cython). + + class GeneratorWrapper: + def __init__(self, gen): + self.__wrapped__ = gen + self.send = gen.send + self.throw = gen.throw + self.close = gen.close + self.__name__ = getattr(gen, '__name__', None) + self.__qualname__ = getattr(gen, '__qualname__', None) + @property + def gi_code(self): + return self.__wrapped__.gi_code + @property + def gi_frame(self): + return self.__wrapped__.gi_frame + @property + def gi_running(self): + return self.__wrapped__.gi_running + def __next__(self): + return next(self.__wrapped__) + def __iter__(self): + return self.__wrapped__ + __await__ = __iter__ + @_functools.wraps(func) def wrapped(*args, **kwargs): coro = func(*args, **kwargs) + if coro.__class__ is GeneratorType: + return GeneratorWrapper(coro) + # slow checks if not isinstance(coro, _collections_abc.Coroutine): + if isinstance(coro, _collections_abc.Generator): + return GeneratorWrapper(coro) raise TypeError( 'callable wrapped with types.coroutine() returned ' 'non-coroutine: {!r}'.format(coro)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 22:19:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 29 May 2015 20:19:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24316=3A_Wrap_gen_objects_returned_from_callables_?= =?utf-8?q?in_types=2Ecoroutine?= Message-ID: <20150529201942.18163.28790@psf.io> https://hg.python.org/cpython/rev/c0434ef75177 changeset: 96353:c0434ef75177 parent: 96351:748c55375225 parent: 96352:8080b53342e8 user: Yury Selivanov date: Fri May 29 16:19:34 2015 -0400 summary: Issue 24316: Wrap gen objects returned from callables in types.coroutine (Merge 3.5) files: Lib/test/test_types.py | 45 ++++++++++++++++++++++------- Lib/types.py | 40 ++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1206,28 +1206,51 @@ @types.coroutine def foo(): pass - @types.coroutine - def gen(): - def _gen(): yield - return _gen() - - for sample in (foo, gen): - with self.assertRaisesRegex(TypeError, - 'callable wrapped .* non-coroutine'): - sample() + with self.assertRaisesRegex(TypeError, + 'callable wrapped .* non-coroutine'): + foo() def test_duck_coro(self): class CoroLike: def send(self): pass def throw(self): pass def close(self): pass - def __await__(self): pass + def __await__(self): return self coro = CoroLike() @types.coroutine def foo(): return coro - self.assertIs(coro, foo()) + self.assertIs(foo().__await__(), coro) + + def test_duck_gen(self): + class GenLike: + def send(self): pass + def throw(self): pass + def close(self): pass + def __iter__(self): return self + def __next__(self): pass + + gen = GenLike() + @types.coroutine + def foo(): + return gen + self.assertIs(foo().__await__(), gen) + + with self.assertRaises(AttributeError): + foo().gi_code + + def test_gen(self): + def gen(): yield + gen = gen() + @types.coroutine + def foo(): return gen + self.assertIs(foo().__await__(), gen) + + for name in ('__name__', '__qualname__', 'gi_code', + 'gi_running', 'gi_frame'): + self.assertIs(getattr(foo(), name), + getattr(gen, name)) def test_genfunc(self): def gen(): diff --git a/Lib/types.py b/Lib/types.py --- a/Lib/types.py +++ b/Lib/types.py @@ -166,32 +166,64 @@ # We don't want to import 'dis' or 'inspect' just for # these constants. - _CO_GENERATOR = 0x20 - _CO_ITERABLE_COROUTINE = 0x100 + CO_GENERATOR = 0x20 + CO_ITERABLE_COROUTINE = 0x100 if not callable(func): raise TypeError('types.coroutine() expects a callable') if (isinstance(func, FunctionType) and isinstance(getattr(func, '__code__', None), CodeType) and - (func.__code__.co_flags & _CO_GENERATOR)): + (func.__code__.co_flags & CO_GENERATOR)): # TODO: Implement this in C. co = func.__code__ func.__code__ = CodeType( co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, - co.co_flags | _CO_ITERABLE_COROUTINE, + co.co_flags | CO_ITERABLE_COROUTINE, co.co_code, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) return func + # The following code is primarily to support functions that + # return generator-like objects (for instance generators + # compiled with Cython). + + class GeneratorWrapper: + def __init__(self, gen): + self.__wrapped__ = gen + self.send = gen.send + self.throw = gen.throw + self.close = gen.close + self.__name__ = getattr(gen, '__name__', None) + self.__qualname__ = getattr(gen, '__qualname__', None) + @property + def gi_code(self): + return self.__wrapped__.gi_code + @property + def gi_frame(self): + return self.__wrapped__.gi_frame + @property + def gi_running(self): + return self.__wrapped__.gi_running + def __next__(self): + return next(self.__wrapped__) + def __iter__(self): + return self.__wrapped__ + __await__ = __iter__ + @_functools.wraps(func) def wrapped(*args, **kwargs): coro = func(*args, **kwargs) + if coro.__class__ is GeneratorType: + return GeneratorWrapper(coro) + # slow checks if not isinstance(coro, _collections_abc.Coroutine): + if isinstance(coro, _collections_abc.Generator): + return GeneratorWrapper(coro) raise TypeError( 'callable wrapped with types.coroutine() returned ' 'non-coroutine: {!r}'.format(coro)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 23:59:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 29 May 2015 21:59:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MzI2?= =?utf-8?q?=3A_Fixed_audioop=2Eratecv=28=29_with_non-default_weightB_argum?= =?utf-8?q?ent=2E?= Message-ID: <20150529215859.18151.60573@psf.io> https://hg.python.org/cpython/rev/800a55c20b56 changeset: 96354:800a55c20b56 branch: 3.4 parent: 96329:09327f653ec5 user: Serhiy Storchaka date: Sat May 30 00:53:26 2015 +0300 summary: Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. files: Lib/test/test_audioop.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ Modules/audioop.c | 2 +- 3 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -363,6 +363,9 @@ (b'', (-2, ((0, 0),)))) self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None)[0], datas[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 1, 0)[0], + datas[w]) + state = None d1, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) d2, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) @@ -378,6 +381,20 @@ self.assertEqual(d, d0) self.assertEqual(state, state0) + expected = { + 1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14), + 2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a), + 3: packs[3](0, 0x0da740, 0x377776, -0x262fca, + 0x56740c, -0x4a62fd, -0x1298c0), + 4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962, + 0x56740da6, -0x4a62fc96, -0x1298bf26), + } + for w in 1, 2, 3, 4: + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0], + expected[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0], + expected[w]) + def test_reverse(self): for w in 1, 2, 3, 4: self.assertEqual(audioop.reverse(b'', w), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Library ------- +- Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. + Original patch by David Moore. + - Issue #23840: tokenize.open() now closes the temporary binary file on error to fix a resource warning. diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1320,7 +1320,7 @@ /* divide weightA and weightB by their greatest common divisor */ d = gcd(weightA, weightB); weightA /= d; - weightA /= d; + weightB /= d; if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) { PyErr_SetString(PyExc_MemoryError, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 23:59:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 29 May 2015 21:59:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MzI2?= =?utf-8?q?=3A_Fixed_audioop=2Eratecv=28=29_with_non-default_weightB_argum?= =?utf-8?q?ent=2E?= Message-ID: <20150529215900.7123.15846@psf.io> https://hg.python.org/cpython/rev/418ab34fd1ce changeset: 96355:418ab34fd1ce branch: 2.7 parent: 96341:3b6e0720a69d user: Serhiy Storchaka date: Sat May 30 00:53:26 2015 +0300 summary: Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. files: Lib/test/test_audioop.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ Modules/audioop.c | 2 +- 3 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -280,6 +280,9 @@ (b'', (-2, ((0, 0),)))) self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None)[0], datas[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 1, 0)[0], + datas[w]) + state = None d1, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) d2, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) @@ -295,6 +298,20 @@ self.assertEqual(d, d0) self.assertEqual(state, state0) + expected = { + 1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14), + 2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a), + 3: packs[3](0, 0x0da740, 0x377776, -0x262fca, + 0x56740c, -0x4a62fd, -0x1298c0), + 4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962, + 0x56740da6, -0x4a62fc96, -0x1298bf26), + } + for w in 1, 2, 3, 4: + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0], + expected[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0], + expected[w]) + def test_reverse(self): for w in 1, 2, 4: self.assertEqual(audioop.reverse(b'', w), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Library ------- +- Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. + Original patch by David Moore. + - Issue #22095: Fixed HTTPConnection.set_tunnel with default port. The port value in the host header was set to "None". Patch by Demian Brecht. diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1130,7 +1130,7 @@ /* divide weightA and weightB by their greatest common divisor */ d = gcd(weightA, weightB); weightA /= d; - weightA /= d; + weightB /= d; if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) { PyErr_SetString(PyExc_MemoryError, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 23:59:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 29 May 2015 21:59:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324326=3A_Fixed_audioop=2Eratecv=28=29_with_non-?= =?utf-8?q?default_weightB_argument=2E?= Message-ID: <20150529215900.18149.98968@psf.io> https://hg.python.org/cpython/rev/1acb6c88b901 changeset: 96357:1acb6c88b901 parent: 96353:c0434ef75177 parent: 96356:fc85a384b16c user: Serhiy Storchaka date: Sat May 30 00:58:09 2015 +0300 summary: Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. files: Lib/test/test_audioop.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ Modules/audioop.c | 2 +- 3 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -363,6 +363,9 @@ (b'', (-2, ((0, 0),)))) self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None)[0], datas[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 1, 0)[0], + datas[w]) + state = None d1, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) d2, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) @@ -378,6 +381,20 @@ self.assertEqual(d, d0) self.assertEqual(state, state0) + expected = { + 1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14), + 2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a), + 3: packs[3](0, 0x0da740, 0x377776, -0x262fca, + 0x56740c, -0x4a62fd, -0x1298c0), + 4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962, + 0x56740da6, -0x4a62fc96, -0x1298bf26), + } + for w in 1, 2, 3, 4: + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0], + expected[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0], + expected[w]) + def test_reverse(self): for w in 1, 2, 3, 4: self.assertEqual(audioop.reverse(b'', w), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,9 @@ Library ------- +- Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. + Original patch by David Moore. + What's New in Python 3.5.0 beta 1? ================================== diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1331,7 +1331,7 @@ /* divide weightA and weightB by their greatest common divisor */ d = gcd(weightA, weightB); weightA /= d; - weightA /= d; + weightB /= d; if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) { PyErr_SetString(PyExc_MemoryError, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri May 29 23:59:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 29 May 2015 21:59:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324326=3A_Fixed_audioop=2Eratecv=28=29_with_non-defaul?= =?utf-8?q?t_weightB_argument=2E?= Message-ID: <20150529215900.25433.88600@psf.io> https://hg.python.org/cpython/rev/fc85a384b16c changeset: 96356:fc85a384b16c branch: 3.5 parent: 96352:8080b53342e8 parent: 96354:800a55c20b56 user: Serhiy Storchaka date: Sat May 30 00:57:21 2015 +0300 summary: Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. files: Lib/test/test_audioop.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ Modules/audioop.c | 2 +- 3 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -363,6 +363,9 @@ (b'', (-2, ((0, 0),)))) self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None)[0], datas[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 1, 0)[0], + datas[w]) + state = None d1, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) d2, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state) @@ -378,6 +381,20 @@ self.assertEqual(d, d0) self.assertEqual(state, state0) + expected = { + 1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14), + 2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a), + 3: packs[3](0, 0x0da740, 0x377776, -0x262fca, + 0x56740c, -0x4a62fd, -0x1298c0), + 4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962, + 0x56740da6, -0x4a62fc96, -0x1298bf26), + } + for w in 1, 2, 3, 4: + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0], + expected[w]) + self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0], + expected[w]) + def test_reverse(self): for w in 1, 2, 3, 4: self.assertEqual(audioop.reverse(b'', w), b'') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,9 @@ Library ------- +- Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. + Original patch by David Moore. + What's New in Python 3.5.0 beta 1? ================================== diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1331,7 +1331,7 @@ /* divide weightA and weightB by their greatest common divisor */ d = gcd(weightA, weightB); weightA /= d; - weightA /= d; + weightB /= d; if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) { PyErr_SetString(PyExc_MemoryError, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 00:11:51 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 29 May 2015 22:11:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_fix_importing_?= =?utf-8?q?one_char_extension_modules_=28closes_=2324328=29?= Message-ID: <20150529221151.27660.11006@psf.io> https://hg.python.org/cpython/rev/784f372d701a changeset: 96358:784f372d701a branch: 3.5 parent: 96356:fc85a384b16c user: Benjamin Peterson date: Fri May 29 17:10:30 2015 -0500 summary: fix importing one char extension modules (closes #24328) files: Lib/test/test_importlib/extension/test_loader.py | 8 ++++ Misc/NEWS | 2 + Modules/_testmultiphase.c | 8 ++++ Python/importdl.c | 19 ++++----- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -177,6 +177,14 @@ self.assertEqual(module.__name__, 'pkg.' + self.name) self.assertEqual(module.str_const, 'something different') + def test_load_short_name(self): + '''Test loading module with a one-character name''' + module = self.load_module_by_name('x') + self.assertIsInstance(module, types.ModuleType) + self.assertEqual(module.__name__, 'x') + self.assertEqual(module.str_const, 'something different') + assert 'x' not in sys.modules + def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' module1 = self.load_module_by_name(self.name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24328: Fix importing one character extension modules. + - Issue #11205: In dictionary displays, evaluate the key before the value. - Issue #24285: Fixed regression that prevented importing extension modules diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -321,6 +321,14 @@ return PyModuleDef_Init(&def_nonascii_kana); } +/*** Module with a single-character name ***/ + +PyMODINIT_FUNC +PyInit_x(PyObject *spec) +{ + return PyModuleDef_Init(&main_def); +} + /**** Testing NULL slots ****/ static PyModuleDef null_slots_def = TEST_MODULE_DEF( diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -34,10 +34,11 @@ */ static PyObject * get_encoded_name(PyObject *name, const char **hook_prefix) { - char *buf; PyObject *tmp; PyObject *encoded = NULL; - Py_ssize_t name_len, lastdot, i; + PyObject *modname = NULL; + Py_ssize_t name_len, lastdot; + _Py_IDENTIFIER(replace); /* Get the short name (substring after last dot) */ name_len = PyUnicode_GetLength(name); @@ -71,16 +72,14 @@ } } - buf = PyBytes_AS_STRING(encoded); - assert(Py_REFCNT(encoded) == 1); - for (i = 0; i < PyBytes_GET_SIZE(encoded) + 1; i++) { - if (buf[i] == '-') { - buf[i] = '_'; - } - } + /* Replace '-' by '_' */ + modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc", '-', '_'); + if (modname == NULL) + goto error; Py_DECREF(name); - return encoded; + Py_DECREF(encoded); + return modname; error: Py_DECREF(name); Py_XDECREF(encoded); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 00:11:51 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 29 May 2015 22:11:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQzMjgp?= Message-ID: <20150529221151.18169.79447@psf.io> https://hg.python.org/cpython/rev/d89bab1f160e changeset: 96359:d89bab1f160e parent: 96357:1acb6c88b901 parent: 96358:784f372d701a user: Benjamin Peterson date: Fri May 29 17:11:36 2015 -0500 summary: merge 3.5 (#24328) files: Lib/test/test_importlib/extension/test_loader.py | 8 ++++ Misc/NEWS | 2 + Modules/_testmultiphase.c | 8 ++++ Python/importdl.c | 19 ++++----- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -177,6 +177,14 @@ self.assertEqual(module.__name__, 'pkg.' + self.name) self.assertEqual(module.str_const, 'something different') + def test_load_short_name(self): + '''Test loading module with a one-character name''' + module = self.load_module_by_name('x') + self.assertIsInstance(module, types.ModuleType) + self.assertEqual(module.__name__, 'x') + self.assertEqual(module.str_const, 'something different') + assert 'x' not in sys.modules + def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' module1 = self.load_module_by_name(self.name) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Core and Builtins ----------------- +- Issue #24328: Fix importing one character extension modules. + - Issue #11205: In dictionary displays, evaluate the key before the value. - Issue #24285: Fixed regression that prevented importing extension modules diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -321,6 +321,14 @@ return PyModuleDef_Init(&def_nonascii_kana); } +/*** Module with a single-character name ***/ + +PyMODINIT_FUNC +PyInit_x(PyObject *spec) +{ + return PyModuleDef_Init(&main_def); +} + /**** Testing NULL slots ****/ static PyModuleDef null_slots_def = TEST_MODULE_DEF( diff --git a/Python/importdl.c b/Python/importdl.c --- a/Python/importdl.c +++ b/Python/importdl.c @@ -34,10 +34,11 @@ */ static PyObject * get_encoded_name(PyObject *name, const char **hook_prefix) { - char *buf; PyObject *tmp; PyObject *encoded = NULL; - Py_ssize_t name_len, lastdot, i; + PyObject *modname = NULL; + Py_ssize_t name_len, lastdot; + _Py_IDENTIFIER(replace); /* Get the short name (substring after last dot) */ name_len = PyUnicode_GetLength(name); @@ -71,16 +72,14 @@ } } - buf = PyBytes_AS_STRING(encoded); - assert(Py_REFCNT(encoded) == 1); - for (i = 0; i < PyBytes_GET_SIZE(encoded) + 1; i++) { - if (buf[i] == '-') { - buf[i] = '_'; - } - } + /* Replace '-' by '_' */ + modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc", '-', '_'); + if (modname == NULL) + goto error; Py_DECREF(name); - return encoded; + Py_DECREF(encoded); + return modname; error: Py_DECREF(name); Py_XDECREF(encoded); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 01:44:55 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 29 May 2015 23:44:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150529234455.4330.90821@psf.io> https://hg.python.org/cpython/rev/466c5119a256 changeset: 96361:466c5119a256 parent: 96359:d89bab1f160e parent: 96360:8428cb297d15 user: Benjamin Peterson date: Fri May 29 18:44:50 2015 -0500 summary: merge 3.5 files: Lib/test/test_importlib/extension/test_loader.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -183,7 +183,7 @@ self.assertIsInstance(module, types.ModuleType) self.assertEqual(module.__name__, 'x') self.assertEqual(module.str_const, 'something different') - assert 'x' not in sys.modules + self.assertNotIn('x', sys.modules) def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 01:44:55 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 29 May 2015 23:44:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_use_assert_met?= =?utf-8?b?aG9kICgjMjQzMjgp?= Message-ID: <20150529234455.18664.65912@psf.io> https://hg.python.org/cpython/rev/8428cb297d15 changeset: 96360:8428cb297d15 branch: 3.5 parent: 96358:784f372d701a user: Benjamin Peterson date: Fri May 29 18:44:45 2015 -0500 summary: use assert method (#24328) files: Lib/test/test_importlib/extension/test_loader.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -183,7 +183,7 @@ self.assertIsInstance(module, types.ModuleType) self.assertEqual(module.__name__, 'x') self.assertEqual(module.str_const, 'something different') - assert 'x' not in sys.modules + self.assertNotIn('x', sys.modules) def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 06:28:33 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 04:28:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316991=3A_Add_a_C_?= =?utf-8?q?implementation_of_collections=2EOrderedDict=2E?= Message-ID: <20150530042833.111606.19476@psf.io> https://hg.python.org/cpython/rev/e7af362b78df changeset: 96362:e7af362b78df user: Eric Snow date: Fri May 29 22:21:39 2015 -0600 summary: Issue #16991: Add a C implementation of collections.OrderedDict. files: Include/Python.h | 1 + Include/dictobject.h | 15 +- Include/odictobject.h | 42 + Lib/collections/__init__.py | 21 +- Lib/test/test_collections.py | 202 +- Makefile.pre.in | 1 + Misc/NEWS | 2 + Modules/_collectionsmodule.c | 3 + Objects/dict-common.h | 22 + Objects/dictobject.c | 337 +- Objects/object.c | 15 + Objects/odictobject.c | 2394 ++++++++++++++++++++++ 12 files changed, 2860 insertions(+), 195 deletions(-) diff --git a/Include/Python.h b/Include/Python.h --- a/Include/Python.h +++ b/Include/Python.h @@ -85,6 +85,7 @@ #include "tupleobject.h" #include "listobject.h" #include "dictobject.h" +#include "odictobject.h" #include "enumobject.h" #include "setobject.h" #include "methodobject.h" diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -27,6 +27,11 @@ PyObject **ma_values; } PyDictObject; +typedef struct { + PyObject_HEAD + PyDictObject *dv_dict; +} _PyDictViewObject; + #endif /* Py_LIMITED_API */ PyAPI_DATA(PyTypeObject) PyDict_Type; @@ -40,9 +45,9 @@ #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) -#define PyDictKeys_Check(op) (Py_TYPE(op) == &PyDictKeys_Type) -#define PyDictItems_Check(op) (Py_TYPE(op) == &PyDictItems_Type) -#define PyDictValues_Check(op) (Py_TYPE(op) == &PyDictValues_Type) +#define PyDictKeys_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictKeys_Type)) +#define PyDictItems_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictItems_Type)) +#define PyDictValues_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictValues_Type)) /* This excludes Values, since they are not sets. */ # define PyDictViewSet_Check(op) \ (PyDictKeys_Check(op) || PyDictItems_Check(op)) @@ -75,6 +80,7 @@ PyAPI_FUNC(PyObject *) PyObject_GenericGetDict(PyObject *, void *); PyAPI_FUNC(int) _PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); +PyObject *_PyDictView_New(PyObject *, PyTypeObject *); #endif PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp); PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp); @@ -88,6 +94,9 @@ PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); +PyObject *_PyDict_SizeOf(PyDictObject *); +PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *); +PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) PyAPI_FUNC(int) PyDict_ClearFreeList(void); diff --git a/Include/odictobject.h b/Include/odictobject.h new file mode 100644 --- /dev/null +++ b/Include/odictobject.h @@ -0,0 +1,42 @@ +#ifndef Py_ODICTOBJECT_H +#define Py_ODICTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* OrderedDict */ + +#ifndef Py_LIMITED_API + +typedef struct _odictobject PyODictObject; + +PyAPI_DATA(PyTypeObject) PyODict_Type; +PyAPI_DATA(PyTypeObject) PyODictIter_Type; +PyAPI_DATA(PyTypeObject) PyODictKeys_Type; +PyAPI_DATA(PyTypeObject) PyODictItems_Type; +PyAPI_DATA(PyTypeObject) PyODictValues_Type; + +#endif /* Py_LIMITED_API */ + +#define PyODict_Check(op) PyObject_IsInstance(op, (PyObject *)&PyODict_Type) +#define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) +#define PyODict_SIZE(op) ((PyDictObject *)op)->ma_used +#define PyODict_HasKey(od, key) (PyMapping_HasKey(PyObject *)od, key) + +PyAPI_FUNC(PyObject *) PyODict_New(void); +PyAPI_FUNC(int) PyODict_SetItem(PyObject *od, PyObject *key, PyObject *item); +PyAPI_FUNC(int) PyODict_DelItem(PyObject *od, PyObject *key); + +/* wrappers around PyDict* functions */ +#define PyODict_GetItem(od, key) PyDict_GetItem((PyObject *)od, key) +#define PyODict_Contains(od, key) PyDict_Contains((PyObject *)od, key) +#define PyODict_Size(od) PyDict_Size((PyObject *)od) +#define PyODict_GetItemString(od, key) \ + PyDict_GetItemString((PyObject *)od, key) +#define Py_ODict_GetItemId(od, key) _PyDict_GetItemId((PyObject *)od, key) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ODICTOBJECT_H */ diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -7,7 +7,6 @@ import _collections_abc __all__ += _collections_abc.__all__ -from _collections import deque, defaultdict from operator import itemgetter as _itemgetter, eq as _eq from keyword import iskeyword as _iskeyword import sys as _sys @@ -16,7 +15,18 @@ from itertools import repeat as _repeat, chain as _chain, starmap as _starmap from reprlib import recursive_repr as _recursive_repr -MutableSequence.register(deque) +try: + from _collections import deque +except ImportError: + pass +else: + MutableSequence.register(deque) + +try: + from _collections import defaultdict +except ImportError: + pass + ################################################################################ ### OrderedDict @@ -264,6 +274,13 @@ return dict.__eq__(self, other) +try: + from _collections import OrderedDict +except ImportError: + # Leave the pure Python version in place. + pass + + ################################################################################ ### namedtuple ################################################################################ diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1,7 +1,8 @@ """Unit tests for collections.py.""" import unittest, doctest, operator -from test.support import TESTFN, forget, unlink +from test.support import TESTFN, forget, unlink, import_fresh_module +import contextlib import inspect from test import support from collections import namedtuple, Counter, OrderedDict, _count_elements @@ -1609,9 +1610,24 @@ ### OrderedDict ################################################################################ -class TestOrderedDict(unittest.TestCase): +py_coll = import_fresh_module('collections', blocked=['_collections']) +c_coll = import_fresh_module('collections', fresh=['_collections']) + + + at contextlib.contextmanager +def replaced_module(name, replacement): + original_module = sys.modules[name] + sys.modules[name] = replacement + try: + yield + finally: + sys.modules[name] = original_module + + +class OrderedDictTests: def test_init(self): + OrderedDict = self.module.OrderedDict with self.assertRaises(TypeError): OrderedDict([('a', 1), ('b', 2)], None) # too many args pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] @@ -1635,6 +1651,7 @@ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) def test_update(self): + OrderedDict = self.module.OrderedDict with self.assertRaises(TypeError): OrderedDict().update([('a', 1), ('b', 2)], None) # too many args pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] @@ -1675,11 +1692,17 @@ self.assertRaises(TypeError, OrderedDict().update, (), ()) self.assertRaises(TypeError, OrderedDict.update) + self.assertRaises(TypeError, OrderedDict().update, 42) + self.assertRaises(TypeError, OrderedDict().update, (), ()) + self.assertRaises(TypeError, OrderedDict.update) + def test_abc(self): + OrderedDict = self.module.OrderedDict self.assertIsInstance(OrderedDict(), MutableMapping) self.assertTrue(issubclass(OrderedDict, MutableMapping)) def test_clear(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1688,6 +1711,7 @@ self.assertEqual(len(od), 0) def test_delitem(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] od = OrderedDict(pairs) del od['a'] @@ -1697,6 +1721,7 @@ self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) def test_setitem(self): + OrderedDict = self.module.OrderedDict od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) od['c'] = 10 # existing element od['f'] = 20 # new element @@ -1704,6 +1729,7 @@ [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) def test_iterators(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1720,6 +1746,11 @@ self.assertEqual(list(reversed(od.items())), list(reversed(pairs))) def test_detect_deletion_during_iteration(self): + # XXX This test should also work under cOrderedDict. + if self.module is c_coll: + raise unittest.SkipTest("only valid for pure Python OrderedDict") + + OrderedDict = self.module.OrderedDict od = OrderedDict.fromkeys('abc') it = iter(od) key = next(it) @@ -1729,7 +1760,21 @@ # The only guarantee that the next() will not succeed next(it) + def test_sorted_iterators(self): + OrderedDict = self.module.OrderedDict + with self.assertRaises(TypeError): + OrderedDict([('a', 1), ('b', 2)], None) + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + od = OrderedDict(pairs) + self.assertEqual(sorted(od), [t[0] for t in pairs]) + self.assertEqual(sorted(od.keys()), [t[0] for t in pairs]) + self.assertEqual(sorted(od.values()), [t[1] for t in pairs]) + self.assertEqual(sorted(od.items()), pairs) + self.assertEqual(sorted(reversed(od)), + sorted([t[0] for t in reversed(pairs)])) + def test_popitem(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1739,7 +1784,18 @@ od.popitem() self.assertEqual(len(od), 0) + def test_popitem_last(self): + OrderedDict = self.module.OrderedDict + pairs = [(i, i) for i in range(30)] + + obj = OrderedDict(pairs) + for i in range(8): + obj.popitem(True) + obj.popitem(True) + self.assertEqual(len(obj), 21) + def test_pop(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1764,6 +1820,7 @@ m.pop('a') def test_equality(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od1 = OrderedDict(pairs) @@ -1779,6 +1836,7 @@ self.assertNotEqual(od1, OrderedDict(pairs[:-1])) def test_copying(self): + OrderedDict = self.module.OrderedDict # Check that ordered dicts are copyable, deepcopyable, picklable, # and have a repr/eval round-trip pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1787,12 +1845,17 @@ msg = "\ncopy: %s\nod: %s" % (dup, od) self.assertIsNot(dup, od, msg) self.assertEqual(dup, od) + self.assertEqual(list(dup.items()), list(od.items())) + self.assertEqual(len(dup), len(od)) + self.assertEqual(type(dup), type(od)) check(od.copy()) check(copy.copy(od)) check(copy.deepcopy(od)) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - check(pickle.loads(pickle.dumps(od, proto))) + # pickle directly pulls the module, so we have to fake it + with replaced_module('collections', self.module): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + check(pickle.loads(pickle.dumps(od, proto))) check(eval(repr(od))) update_test = OrderedDict() update_test.update(od) @@ -1800,6 +1863,7 @@ check(OrderedDict(od)) def test_yaml_linkage(self): + OrderedDict = self.module.OrderedDict # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature. # In yaml, lists are native but tuples are not. pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1809,6 +1873,7 @@ self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1])) def test_reduce_not_too_fat(self): + OrderedDict = self.module.OrderedDict # do not save instance dictionary if not needed pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] od = OrderedDict(pairs) @@ -1817,15 +1882,20 @@ self.assertIsNotNone(od.__reduce__()[2]) def test_pickle_recursive(self): + OrderedDict = self.module.OrderedDict od = OrderedDict() od[1] = od - for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): - dup = pickle.loads(pickle.dumps(od, proto)) - self.assertIsNot(dup, od) - self.assertEqual(list(dup.keys()), [1]) - self.assertIs(dup[1], dup) + + # pickle directly pulls the module, so we have to fake it + with replaced_module('collections', self.module): + for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): + dup = pickle.loads(pickle.dumps(od, proto)) + self.assertIsNot(dup, od) + self.assertEqual(list(dup.keys()), [1]) + self.assertIs(dup[1], dup) def test_repr(self): + OrderedDict = self.module.OrderedDict od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) self.assertEqual(repr(od), "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") @@ -1833,6 +1903,7 @@ self.assertEqual(repr(OrderedDict()), "OrderedDict()") def test_repr_recursive(self): + OrderedDict = self.module.OrderedDict # See issue #9826 od = OrderedDict.fromkeys('abc') od['x'] = od @@ -1840,6 +1911,7 @@ "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])") def test_setdefault(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1858,16 +1930,19 @@ self.assertEqual(Missing().setdefault(5, 9), 9) def test_reinsert(self): + OrderedDict = self.module.OrderedDict # Given insert a, insert b, delete a, re-insert a, # verify that a is now later than b. od = OrderedDict() od['a'] = 1 od['b'] = 2 del od['a'] + self.assertEqual(list(od.items()), [('b', 2)]) od['a'] = 1 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) def test_move_to_end(self): + OrderedDict = self.module.OrderedDict od = OrderedDict.fromkeys('abcde') self.assertEqual(list(od), list('abcde')) od.move_to_end('c') @@ -1880,14 +1955,18 @@ self.assertEqual(list(od), list('cabde')) with self.assertRaises(KeyError): od.move_to_end('x') + with self.assertRaises(KeyError): + od.move_to_end('x', 0) def test_sizeof(self): + OrderedDict = self.module.OrderedDict # Wimpy test: Just verify the reported size is larger than a regular dict d = dict(a=1) od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) def test_views(self): + OrderedDict = self.module.OrderedDict # See http://bugs.python.org/issue24286 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() od = OrderedDict.fromkeys(s) @@ -1895,6 +1974,7 @@ self.assertEqual(od.items(), dict(od).items()) def test_override_update(self): + OrderedDict = self.module.OrderedDict # Verify that subclasses can override update() without breaking __init__() class MyOD(OrderedDict): def update(self, *args, **kwds): @@ -1902,18 +1982,101 @@ items = [('a', 1), ('c', 3), ('b', 2)] self.assertEqual(list(MyOD(items).items()), items) -class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): - type2test = OrderedDict + +class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase): + + module = py_coll + + + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase): + + module = c_coll + + def test_delitem_hash_collision(self): + OrderedDict = self.module.OrderedDict + + class Key: + def __init__(self, hash): + self._hash = hash + self.value = str(id(self)) + def __hash__(self): + return self._hash + def __eq__(self, other): + try: + return self.value == other.value + except AttributeError: + return False + def __repr__(self): + return self.value + + def blocking_hash(hash): + # See the collision-handling in lookdict (in Objects/dictobject.c). + MINSIZE = 8 + i = (hash & MINSIZE-1) + return (i << 2) + i + hash + 1 + + COLLIDING = 1 + + key = Key(COLLIDING) + colliding = Key(COLLIDING) + blocking = Key(blocking_hash(COLLIDING)) + + od = OrderedDict() + od[key] = ... + od[blocking] = ... + od[colliding] = ... + od['after'] = ... + + del od[blocking] + del od[colliding] + self.assertEqual(list(od.items()), [(key, ...), ('after', ...)]) + + +class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + cls.type2test = py_coll.OrderedDict def test_popitem(self): d = self._empty_mapping() self.assertRaises(KeyError, d.popitem) -class MyOrderedDict(OrderedDict): - pass -class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): - type2test = MyOrderedDict + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + cls.type2test = c_coll.OrderedDict + + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + + +class PurePythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + class MyOrderedDict(py_coll.OrderedDict): + pass + cls.type2test = MyOrderedDict + + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + + + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + class MyOrderedDict(c_coll.OrderedDict): + pass + cls.type2test = MyOrderedDict def test_popitem(self): d = self._empty_mapping() @@ -1930,8 +2093,11 @@ NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, TestCollectionABCs, TestCounter, TestChainMap, - TestOrderedDict, GeneralMappingTests, SubclassMappingTests, - TestUserObjects] + PurePythonOrderedDictTests, CPythonOrderedDictTests, + PurePythonGeneralMappingTests, CPythonGeneralMappingTests, + PurePythonSubclassMappingTests, CPythonSubclassMappingTests, + TestUserObjects, + ] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -437,6 +437,7 @@ Objects/listobject.o \ Objects/longobject.o \ Objects/dictobject.o \ + Objects/odictobject.o \ Objects/memoryobject.o \ Objects/methodobject.o \ Objects/moduleobject.o \ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,6 +35,8 @@ - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. +- Issue #16991: Add a C implementation of OrderedDict. + What's New in Python 3.5.0 beta 1? ================================== diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2263,6 +2263,9 @@ Py_INCREF(&defdict_type); PyModule_AddObject(m, "defaultdict", (PyObject *)&defdict_type); + Py_INCREF(&PyODict_Type); + PyModule_AddObject(m, "OrderedDict", (PyObject *)&PyODict_Type); + if (PyType_Ready(&dequeiter_type) < 0) return NULL; Py_INCREF(&dequeiter_type); diff --git a/Objects/dict-common.h b/Objects/dict-common.h new file mode 100644 --- /dev/null +++ b/Objects/dict-common.h @@ -0,0 +1,22 @@ +#ifndef Py_DICT_COMMON_H +#define Py_DICT_COMMON_H + +typedef struct { + /* Cached hash code of me_key. */ + Py_hash_t me_hash; + PyObject *me_key; + PyObject *me_value; /* This field is only meaningful for combined tables */ +} PyDictKeyEntry; + +typedef PyDictKeyEntry *(*dict_lookup_func) +(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); + +struct _dictkeysobject { + Py_ssize_t dk_refcnt; + Py_ssize_t dk_size; + dict_lookup_func dk_lookup; + Py_ssize_t dk_usable; + PyDictKeyEntry dk_entries[1]; +}; + +#endif diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -67,6 +67,7 @@ #define PyDict_MINSIZE_COMBINED 8 #include "Python.h" +#include "dict-common.h" #include "stringlib/eq.h" /*[clinic input] @@ -74,24 +75,6 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/ -typedef struct { - /* Cached hash code of me_key. */ - Py_hash_t me_hash; - PyObject *me_key; - PyObject *me_value; /* This field is only meaningful for combined tables */ -} PyDictKeyEntry; - -typedef PyDictKeyEntry *(*dict_lookup_func) -(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); - -struct _dictkeysobject { - Py_ssize_t dk_refcnt; - Py_ssize_t dk_size; - dict_lookup_func dk_lookup; - Py_ssize_t dk_usable; - PyDictKeyEntry dk_entries[1]; -}; - /* To ensure the lookup algorithm terminates, there must be at least one Unused @@ -1425,6 +1408,141 @@ return 1; } +/* Internal version of dict.pop(). */ +PyObject * +_PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) +{ + Py_hash_t hash; + PyObject *old_value, *old_key; + PyDictKeyEntry *ep; + PyObject **value_addr; + + if (mp->ma_used == 0) { + if (deflt) { + Py_INCREF(deflt); + return deflt; + } + _PyErr_SetKeyError(key); + return NULL; + } + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return NULL; + } + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + if (ep == NULL) + return NULL; + old_value = *value_addr; + if (old_value == NULL) { + if (deflt) { + Py_INCREF(deflt); + return deflt; + } + _PyErr_SetKeyError(key); + return NULL; + } + *value_addr = NULL; + mp->ma_used--; + if (!_PyDict_HasSplitTable(mp)) { + ENSURE_ALLOWS_DELETIONS(mp); + old_key = ep->me_key; + Py_INCREF(dummy); + ep->me_key = dummy; + Py_DECREF(old_key); + } + return old_value; +} + +/* Internal version of dict.from_keys(). It is subclass-friendly. */ +PyObject * +_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) +{ + PyObject *it; /* iter(iterable) */ + PyObject *key; + PyObject *d; + int status; + + d = PyObject_CallObject(cls, NULL); + if (d == NULL) + return NULL; + + if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) { + if (PyDict_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + PyObject *oldvalue; + Py_ssize_t pos = 0; + PyObject *key; + Py_hash_t hash; + + if (dictresize(mp, Py_SIZE(iterable))) { + Py_DECREF(d); + return NULL; + } + + while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { + if (insertdict(mp, key, hash, value)) { + Py_DECREF(d); + return NULL; + } + } + return d; + } + if (PyAnySet_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + Py_ssize_t pos = 0; + PyObject *key; + Py_hash_t hash; + + if (dictresize(mp, PySet_GET_SIZE(iterable))) { + Py_DECREF(d); + return NULL; + } + + while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { + if (insertdict(mp, key, hash, value)) { + Py_DECREF(d); + return NULL; + } + } + return d; + } + } + + it = PyObject_GetIter(iterable); + if (it == NULL){ + Py_DECREF(d); + return NULL; + } + + if (PyDict_CheckExact(d)) { + while ((key = PyIter_Next(it)) != NULL) { + status = PyDict_SetItem(d, key, value); + Py_DECREF(key); + if (status < 0) + goto Fail; + } + } else { + while ((key = PyIter_Next(it)) != NULL) { + status = PyObject_SetItem(d, key, value); + Py_DECREF(key); + if (status < 0) + goto Fail; + } + } + + if (PyErr_Occurred()) + goto Fail; + Py_DECREF(it); + return d; + +Fail: + Py_DECREF(it); + Py_DECREF(d); + return NULL; +} + /* Methods */ static void @@ -1763,88 +1881,7 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) /*[clinic end generated code: output=8fb98e4b10384999 input=b85a667f9bf4669d]*/ { - PyObject *it; /* iter(seq) */ - PyObject *key; - PyObject *d; - int status; - - d = PyObject_CallObject((PyObject *)type, NULL); - if (d == NULL) - return NULL; - - if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) { - if (PyDict_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - PyObject *oldvalue; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, Py_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - if (PyAnySet_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, PySet_GET_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - } - - it = PyObject_GetIter(iterable); - if (it == NULL){ - Py_DECREF(d); - return NULL; - } - - if (PyDict_CheckExact(d)) { - while ((key = PyIter_Next(it)) != NULL) { - status = PyDict_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } else { - while ((key = PyIter_Next(it)) != NULL) { - status = PyObject_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } - - if (PyErr_Occurred()) - goto Fail; - Py_DECREF(it); - return d; - -Fail: - Py_DECREF(it); - Py_DECREF(d); - return NULL; + return _PyDict_FromKeys((PyObject *)type, iterable, value); } static int @@ -2356,50 +2393,12 @@ static PyObject * dict_pop(PyDictObject *mp, PyObject *args) { - Py_hash_t hash; - PyObject *old_value, *old_key; PyObject *key, *deflt = NULL; - PyDictKeyEntry *ep; - PyObject **value_addr; if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt)) return NULL; - if (mp->ma_used == 0) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - old_value = *value_addr; - if (old_value == NULL) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - *value_addr = NULL; - mp->ma_used--; - if (!_PyDict_HasSplitTable(mp)) { - ENSURE_ALLOWS_DELETIONS(mp); - old_key = ep->me_key; - Py_INCREF(dummy); - ep->me_key = dummy; - Py_DECREF(old_key); - } - return old_value; + + return _PyDict_Pop(mp, key, deflt); } static PyObject * @@ -2506,8 +2505,8 @@ static PyObject *dictiter_new(PyDictObject *, PyTypeObject *); -static PyObject * -dict_sizeof(PyDictObject *mp) +PyObject * +_PyDict_SizeOf(PyDictObject *mp) { Py_ssize_t size, res; @@ -2575,7 +2574,7 @@ DICT___CONTAINS___METHODDEF {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST, getitem__doc__}, - {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS, + {"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS, sizeof__doc__}, {"get", (PyCFunction)dict_get, METH_VARARGS, get__doc__}, @@ -3104,8 +3103,8 @@ value = *value_ptr; Py_INCREF(key); Py_INCREF(value); - PyTuple_SET_ITEM(result, 0, key); - PyTuple_SET_ITEM(result, 1, value); + PyTuple_SET_ITEM(result, 0, key); /* steals reference */ + PyTuple_SET_ITEM(result, 1, value); /* steals reference */ return result; fail: @@ -3200,28 +3199,22 @@ /* The instance lay-out is the same for all three; but the type differs. */ -typedef struct { - PyObject_HEAD - PyDictObject *dv_dict; -} dictviewobject; - - static void -dictview_dealloc(dictviewobject *dv) +dictview_dealloc(_PyDictViewObject *dv) { Py_XDECREF(dv->dv_dict); PyObject_GC_Del(dv); } static int -dictview_traverse(dictviewobject *dv, visitproc visit, void *arg) +dictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg) { Py_VISIT(dv->dv_dict); return 0; } static Py_ssize_t -dictview_len(dictviewobject *dv) +dictview_len(_PyDictViewObject *dv) { Py_ssize_t len = 0; if (dv->dv_dict != NULL) @@ -3229,10 +3222,10 @@ return len; } -static PyObject * -dictview_new(PyObject *dict, PyTypeObject *type) +PyObject * +_PyDictView_New(PyObject *dict, PyTypeObject *type) { - dictviewobject *dv; + _PyDictViewObject *dv; if (dict == NULL) { PyErr_BadInternalCall(); return NULL; @@ -3244,7 +3237,7 @@ type->tp_name, dict->ob_type->tp_name); return NULL; } - dv = PyObject_GC_New(dictviewobject, type); + dv = PyObject_GC_New(_PyDictViewObject, type); if (dv == NULL) return NULL; Py_INCREF(dict); @@ -3348,7 +3341,7 @@ } static PyObject * -dictview_repr(dictviewobject *dv) +dictview_repr(_PyDictViewObject *dv) { PyObject *seq; PyObject *result; @@ -3365,7 +3358,7 @@ /*** dict_keys ***/ static PyObject * -dictkeys_iter(dictviewobject *dv) +dictkeys_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3374,7 +3367,7 @@ } static int -dictkeys_contains(dictviewobject *dv, PyObject *obj) +dictkeys_contains(_PyDictViewObject *dv, PyObject *obj) { if (dv->dv_dict == NULL) return 0; @@ -3499,7 +3492,7 @@ PyObject *item = NULL; if (self == other) { - if (dictview_len((dictviewobject *)self) == 0) + if (dictview_len((_PyDictViewObject *)self) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -3508,7 +3501,7 @@ /* Iterate over the shorter object (only if other is a set, * because PySequence_Contains may be expensive otherwise): */ if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) { - Py_ssize_t len_self = dictview_len((dictviewobject *)self); + Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self); Py_ssize_t len_other = PyObject_Size(other); if (len_other == -1) return NULL; @@ -3555,7 +3548,7 @@ PyTypeObject PyDictKeys_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_keys", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3588,13 +3581,13 @@ static PyObject * dictkeys_new(PyObject *dict) { - return dictview_new(dict, &PyDictKeys_Type); + return _PyDictView_New(dict, &PyDictKeys_Type); } /*** dict_items ***/ static PyObject * -dictitems_iter(dictviewobject *dv) +dictitems_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3603,7 +3596,7 @@ } static int -dictitems_contains(dictviewobject *dv, PyObject *obj) +dictitems_contains(_PyDictViewObject *dv, PyObject *obj) { PyObject *key, *value, *found; if (dv->dv_dict == NULL) @@ -3641,7 +3634,7 @@ PyTypeObject PyDictItems_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_items", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3674,13 +3667,13 @@ static PyObject * dictitems_new(PyObject *dict) { - return dictview_new(dict, &PyDictItems_Type); + return _PyDictView_New(dict, &PyDictItems_Type); } /*** dict_values ***/ static PyObject * -dictvalues_iter(dictviewobject *dv) +dictvalues_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3706,7 +3699,7 @@ PyTypeObject PyDictValues_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_values", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3739,7 +3732,7 @@ static PyObject * dictvalues_new(PyObject *dict) { - return dictview_new(dict, &PyDictValues_Type); + return _PyDictView_New(dict, &PyDictValues_Type); } /* Returns NULL if cannot allocate a new PyDictKeysObject, diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1607,6 +1607,21 @@ if (PyType_Ready(&PyDict_Type) < 0) Py_FatalError("Can't initialize dict type"); + if (PyType_Ready(&PyODict_Type) < 0) + Py_FatalError("Can't initialize OrderedDict type"); + + if (PyType_Ready(&PyODictKeys_Type) < 0) + Py_FatalError("Can't initialize odict_keys type"); + + if (PyType_Ready(&PyODictItems_Type) < 0) + Py_FatalError("Can't initialize odict_items type"); + + if (PyType_Ready(&PyODictValues_Type) < 0) + Py_FatalError("Can't initialize odict_values type"); + + if (PyType_Ready(&PyODictIter_Type) < 0) + Py_FatalError("Can't initialize odict_keyiterator type"); + if (PyType_Ready(&PySet_Type) < 0) Py_FatalError("Can't initialize set type"); diff --git a/Objects/odictobject.c b/Objects/odictobject.c new file mode 100644 --- /dev/null +++ b/Objects/odictobject.c @@ -0,0 +1,2394 @@ +/* Ordered Dictionary object implementation. + +This implementation is necessarily explicitly equivalent to the pure Python +OrderedDict class in Lib/collections/__init__.py. The strategy there +involves using a doubly-linked-list to capture the order. We keep to that +strategy, using a lower-level linked-list. + +About the Linked-List +===================== + +For the linked list we use a basic doubly-linked-list. Using a circularly- +linked-list does have some benefits, but they don't apply so much here +since OrderedDict is focused on the ends of the list (for the most part). +Furthermore, there are some features of generic linked-lists that we simply +don't need for OrderedDict. Thus a simple custom implementation meets our +needs. Alternatives to our simple approach include the QCIRCLE_* +macros from BSD's queue.h, and the linux's list.h. + +Getting O(1) Node Lookup +------------------------ + +One invariant of Python's OrderedDict is that it preserves time complexity +of dict's methods, particularly the O(1) operations. Simply adding a +linked-list on top of dict is not sufficient here; operations for nodes in +the middle of the linked-list implicitly require finding the node first. +With a simple linked-list like we're using, that is an O(n) operation. +Consequently, methods like __delitem__() would change from O(1) to O(n), +which is unacceptable. + +In order to preserve O(1) performance for node removal (finding nodes), we +must do better than just looping through the linked-list. Here are options +we've considered: + +1. use a second dict to map keys to nodes (a la the pure Python version). +2. keep a simple hash table mirroring the order of dict's, mapping each key + to the corresponding node in the linked-list. +3. use a version of shared keys (split dict) that allows non-unicode keys. +4. have the value stored for each key be a (value, node) pair, and adjust + __getitem__(), get(), etc. accordingly. + +The approach with the least performance impact (time and space) is #2, +mirroring the key order of dict's dk_enties with an array of node pointers. +While lookdict() and friends (dk_lookup) don't give us the index into the +array, we make use of pointer arithmetic to get that index. An alternative +would be to refactor lookdict() to provide the index, explicitly exposing +the implementation detail. We could even just use a custom lookup function +for OrderedDict that facilitates our need. However, both approaches are +significantly more complicated than just using pointer arithmetic. + +The catch with mirroring the hash table ordering is that we have to keep +the ordering in sync through any dict resizes. However, that order only +matters during node lookup. We can simply defer any potential resizing +until we need to do a lookup. + +Linked-List Nodes +----------------- + +The current implementation stores a pointer to the associated key only. +One alternative would be to store a pointer to the PyDictKeyEntry instead. +This would save one pointer de-reference per item, which is nice during +calls to values() and items(). However, it adds unnecessary overhead +otherwise, so we stick with just the key. + +Linked-List API +--------------- + +As noted, the linked-list implemented here does not have all the bells and +whistles. However, we recognize that the implementation may need to +change to accommodate performance improvements or extra functionality. To +that end, We use a simple API to interact with the linked-list. Here's a +summary of the methods/macros: + +Node info: + +* _odictnode_KEY(node) +* _odictnode_VALUE(od, node) +* _odictnode_PREV(node) +* _odictnode_NEXT(node) + +Linked-List info: + +* _odict_FIRST(od) +* _odict_LAST(od) +* _odict_EMPTY(od) +* _odict_FOREACH(od, node) - used in place of `for (node=...)` + +For adding nodes: + +* _odict_add_head(od, node) +* _odict_add_tail(od, node) +* _odict_add_new_node(od, key) + +For removing nodes: + +* _odict_pop_node(od, node, key) +* _odict_clear_node(od, node) +* _odict_clear_nodes(od, clear_each) + +Others: + +* _odict_initialize(od) +* _odict_find_node(od, key) +* _odict_keys_equal(od1, od2) + +Used, but specific to the linked-list implementation: + +* _odict_free_fast_nodes(od) + +And here's a look at how the linked-list relates to the OrderedDict API: + +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === +method key val prev next mem 1st last empty iter find add rmv clr keq +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === +__del__ ~ X +__delitem__ free ~ node +__eq__ ~ X +__iter__ X X +__new__ X X +__reduce__ X ~ X +__repr__ X X X +__reversed__ X X +__setitem__ key +__sizeof__ size X +clear ~ ~ X +copy X X X +items X X X +keys X X +move_to_end X X X ~ h/t key +pop free key +popitem X X free X X node +setdefault ~ ? ~ +values X X +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === + +__delitem__ is the only method that directly relies on finding an arbitrary +node in the linked-list. Everything else is iteration or relates to the +ends of the linked-list. + +Situation that Endangers Consistency +------------------------------------ +Using a raw linked-list for OrderedDict exposes a key situation that can +cause problems. If a node is stored in a variable, there is a chance that +the node may have been deallocated before the variable gets used, thus +potentially leading to a segmentation fault. A key place where this shows +up is during iteration through the linked list (via _odict_FOREACH or +otherwise). + +A number of solutions are available to resolve this situation: + +* defer looking up the node until as late as possible and certainly after + any code that could possibly result in a deletion; +* if the node is needed both before and after a point where the node might + be removed, do a check before using the node at the "after" location to + see if the node is still valid; +* like the last one, but simply pull the node again to ensure it's right; +* keep the key in the variable instead of the node and then look up the + node using the key at the point where the node is needed (this is what + we do for the iterators). + +Another related problem, preserving consistent ordering during iteration, +is described below. That one is not exclusive to using linked-lists. + + +Challenges from Subclassing dict +================================ + +OrderedDict subclasses dict, which is an unusual relationship between two +builtin types (other than the base object type). Doing so results in +some complication and deserves further explanation. There are two things +to consider here. First, in what circumstances or with what adjustments +can OrderedDict be used as a drop-in replacement for dict (at the C level)? +Second, how can the OrderedDict implementation leverage the dict +implementation effectively without introducing unnecessary coupling or +inefficiencies? + +This second point is reflected here and in the implementation, so the +further focus is on the first point. It is worth noting that for +overridden methods, the dict implementation is deferred to as much as +possible. Furthermore, coupling is limited to as little as is reasonable. + +Concrete API Compatibility +-------------------------- + +Use of the concrete C-API for dict (PyDict_*) with OrderedDict is +problematic. (See http://bugs.python.org/issue10977.) The concrete API +has a number of hard-coded assumptions tied to the dict implementation. +This is, in part, due to performance reasons, which is understandable +given the part dict plays in Python. + +Any attempt to replace dict with OrderedDict for any role in the +interpreter (e.g. **kwds) faces a challenge. Such any effort must +recognize that the instances in affected locations currently interact with +the concrete API. + +Here are some ways to address this challenge: + +1. Change the relevant usage of the concrete API in CPython and add + PyDict_CheckExact() calls to each of the concrete API funcions. +2. Adjust the relevant concrete API functions to explicitly accommodate + OrderedDict. +3. As with #1, add the checks, but improve the abstract API with smart fast + paths for dict and OrderedDict, and refactor CPython to use the abstract + API. Improvements to the abstract API would be valuable regardless. + +Adding the checks to the concrete API would help make any interpreter +switch to OrderedDict less painful for extension modules. However, this +won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)` +is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call +the base class's methods, since there is no equivalent of super() in the +C API. Calling into Python for parent class API would work, but some +extension modules already rely on this feature of the concrete API. + +For reference, here is a breakdown of some of the dict concrete API: + +========================== ============= ======================= +concrete API uses abstract API +========================== ============= ======================= +PyDict_Check PyMapping_Check +(PyDict_CheckExact) - +(PyDict_New) - +(PyDictProxy_New) - +PyDict_Clear - +PyDict_Contains PySequence_Contains +PyDict_Copy - +PyDict_SetItem PyObject_SetItem +PyDict_SetItemString PyMapping_SetItemString +PyDict_DelItem PyMapping_DelItem +PyDict_DelItemString PyMapping_DelItemString +PyDict_GetItem - +PyDict_GetItemWithError PyObject_GetItem +_PyDict_GetItemIdWithError - +PyDict_GetItemString PyMapping_GetItemString +PyDict_Items PyMapping_Items +PyDict_Keys PyMapping_Keys +PyDict_Values PyMapping_Values +PyDict_Size PyMapping_Size + PyMapping_Length +PyDict_Next PyIter_Next +_PyDict_Next - +PyDict_Merge - +PyDict_Update - +PyDict_MergeFromSeq2 - +PyDict_ClearFreeList - +- PyMapping_HasKeyString +- PyMapping_HasKey +========================== ============= ======================= + + +The dict Interface Relative to OrderedDict +========================================== + +Since OrderedDict subclasses dict, understanding the various methods and +attributes of dict is important for implementing OrderedDict. + +Relevant Type Slots +------------------- + +================= ================ =================== ================ +slot attribute object dict +================= ================ =================== ================ +tp_dealloc - object_dealloc dict_dealloc +tp_repr __repr__ object_repr dict_repr +sq_contains __contains__ - dict_contains +mp_length __len__ - dict_length +mp_subscript __getitem__ - dict_subscript +mp_ass_subscript __setitem__ - dict_ass_sub + __delitem__ +tp_hash __hash__ _Py_HashPointer ..._HashNotImpl +tp_str __str__ object_str - +tp_getattro __getattribute__ ..._GenericGetAttr (repeated) + __getattr__ +tp_setattro __setattr__ ..._GenericSetAttr (disabled) +tp_doc __doc__ (literal) dictionary_doc +tp_traverse - - dict_traverse +tp_clear - - dict_tp_clear +tp_richcompare __eq__ object_richcompare dict_richcompare + __ne__ +tp_weaklistoffset (__weakref__) - - +tp_iter __iter__ - dict_iter +tp_dictoffset (__dict__) - - +tp_init __init__ object_init dict_init +tp_alloc - PyType_GenericAlloc (repeated) +tp_new __new__ object_new dict_new +tp_free - PyObject_Del PyObject_GC_Del +================= ================ =================== ================ + +Relevant Methods +---------------- + +================ =================== =============== +method object dict +================ =================== =============== +__reduce__ object_reduce - +__sizeof__ object_sizeof dict_sizeof +clear - dict_clear +copy - dict_copy +fromkeys - dict_fromkeys +get - dict_get +items - dictitems_new +keys - dictkeys_new +pop - dict_pop +popitem - dict_popitem +setdefault - dict_setdefault +update - dict_update +values - dictvalues_new +================ =================== =============== + + +Pure Python OrderedDict +======================= + +As already noted, compatibility with the pure Python OrderedDict +implementation is a key goal of this C implementation. To further that +goal, here's a summary of how OrderedDict-specific methods are implemented +in collections/__init__.py. Also provided is an indication of which +methods directly mutate or iterate the object, as well as any relationship +with the underlying linked-list. + +============= ============== == ================ === === ==== +method impl used ll uses inq mut iter +============= ============== == ================ === === ==== +__contains__ dict - - X +__delitem__ OrderedDict Y dict.__delitem__ X +__eq__ OrderedDict N OrderedDict ~ + dict.__eq__ + __iter__ +__getitem__ dict - - X +__iter__ OrderedDict Y - X +__init__ OrderedDict N update +__len__ dict - - X +__ne__ MutableMapping - __eq__ ~ +__reduce__ OrderedDict N OrderedDict ~ + __iter__ + __getitem__ +__repr__ OrderedDict N __class__ ~ + items +__reversed__ OrderedDict Y - X +__setitem__ OrderedDict Y __contains__ X + dict.__setitem__ +__sizeof__ OrderedDict Y __len__ ~ + __dict__ +clear OrderedDict Y dict.clear X +copy OrderedDict N __class__ + __init__ +fromkeys OrderedDict N __setitem__ +get dict - - ~ +items MutableMapping - ItemsView X +keys MutableMapping - KeysView X +move_to_end OrderedDict Y - X +pop OrderedDict N __contains__ X + __getitem__ + __delitem__ +popitem OrderedDict Y dict.pop X +setdefault OrderedDict N __contains__ ~ + __getitem__ + __setitem__ +update MutableMapping - __setitem__ ~ +values MutableMapping - ValuesView X +============= ============== == ================ === === ==== + +__reversed__ and move_to_end are both exclusive to OrderedDict. + + +C OrderedDict Implementation +============================ + +================= ================ +slot impl +================= ================ +tp_dealloc odict_dealloc +tp_repr odict_repr +mp_ass_subscript odict_ass_sub +tp_doc odict_doc +tp_traverse odict_traverse +tp_clear odict_tp_clear +tp_richcompare odict_richcompare +tp_weaklistoffset (offset) +tp_iter odict_iter +tp_dictoffset (offset) +tp_init odict_init +tp_alloc (repeated) +tp_new odict_new +================= ================ + +================= ================ +method impl +================= ================ +__reduce__ odict_reduce +__sizeof__ odict_sizeof +clear odict_clear +copy odict_copy +fromkeys odict_fromkeys +items odictitems_new +keys odictkeys_new +pop odict_pop +popitem odict_popitem +setdefault odict_setdefault +update odict_update +values odictvalues_new +================= ================ + +Inherited unchanged from object/dict: + +================ ========================== +method type field +================ ========================== +- tp_free +__contains__ tp_as_sequence.sq_contains +__getattr__ tp_getattro +__getattribute__ tp_getattro +__getitem__ tp_as_mapping.mp_subscript +__hash__ tp_hash +__len__ tp_as_mapping.mp_length +__setattr__ tp_setattro +__str__ tp_str +get - +================ ========================== + + +Other Challenges +================ + +Preserving Ordering During Iteration +------------------------------------ +During iteration through an OrderedDict, it is possible that items could +get added, removed, or reordered. For a linked-list implementation, as +with some other implementations, that situation may lead to undefined +behavior. The documentation for dict mentions this in the `iter()` section +of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects. +In this implementation we follow dict's lead (as does the pure Python +implementation) for __iter__(), keys(), values(), and items(). + +For internal iteration (using _odict_FOREACH or not), there is still the +risk that not all nodes that we expect to be seen in the loop actually get +seen. Thus, we are careful in each of those places to ensure that they +are. This comes, of course, at a small price at each location. The +solutions are much the same as those detailed in the `Situation that +Endangers Consistency` section above. + + +Potential Optimizations +======================= + +* Allocate the nodes as a block via od_fast_nodes instead of individually. + - Set node->key to NULL to indicate the node is not-in-use. + - Add _odict_EXISTS()? + - How to maintain consistency across resizes? Existing node pointers + would be invalidate after a resize, which is particularly problematic + for the iterators. +* Use a more stream-lined implementation of update() and, likely indirectly, + __init__(). + +*/ + +/* TODO + +sooner: +- reentrancy (make sure everything is at a thread-safe state when calling + into Python). I've already checked this multiple times, but want to + make one more pass. +- add unit tests for reentrancy? + +later: +- make the dict views support the full set API (the pure Python impl does) +- implement a fuller MutableMapping API in C? +- move the MutableMapping implementation to abstract.c? +- optimize mutablemapping_update +- use PyObject_MALLOC (small object allocator) for odict nodes? +- support subclasses better (e.g. in odict_richcompare) + +*/ + +#include "Python.h" +#include "structmember.h" +#include "dict-common.h" +#include + + +typedef struct _odictnode _ODictNode; + +/* PyODictObject */ +struct _odictobject { + /* od_dict is the underlying dict. */ + PyDictObject od_dict; + /* od_first is the first node in the odict, if any. */ + _ODictNode *od_first; + /* od_last is the last node in the odict, if any. */ + _ODictNode *od_last; + /* od_size is the number of entries in od_fast_nodes. */ + Py_ssize_t od_size; /* managed by _odict_resize() */ + /* od_fast_nodes is a hash table that mirrors the dict table. */ + _ODictNode **od_fast_nodes; /* managed by _odict_resize() */ + /* od_inst_dict is OrderedDict().__dict__. */ + PyObject *od_inst_dict; + /* od_weakreflist holds weakrefs to the odict. */ + PyObject *od_weakreflist; +}; + + +/* ---------------------------------------------- + * odict keys (a simple doubly-linked list) + */ + +struct _odictnode { + PyObject *key; + _ODictNode *next; + _ODictNode *prev; +}; + +#define _odictnode_KEY(node) \ + (node->key) +/* borrowed reference */ +#define _odictnode_VALUE(node, od) \ + PyODict_GetItem((PyObject *)od, _odictnode_KEY(node)) +/* If needed we could also have _odictnode_HASH. */ +#define _odictnode_PREV(node) (node->prev) +#define _odictnode_NEXT(node) (node->next) + +#define _odict_FIRST(od) (((PyODictObject *)od)->od_first) +#define _odict_LAST(od) (((PyODictObject *)od)->od_last) +#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL) +#define _odict_FOREACH(od, node) \ + for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node)) + + +static Py_ssize_t _odict_get_index(PyODictObject *, PyObject *); /* forward */ + +static void +_odict_free_fast_nodes(PyODictObject *od) { + if (od->od_fast_nodes) { + PyMem_FREE(od->od_fast_nodes); + } +} + +static int +_odict_resize(PyODictObject *od) { + Py_ssize_t size, prev_size, i; + _ODictNode **fast_nodes, *node; + + /* Initialize a new "fast nodes" table. */ + size = ((PyDictObject *)od)->ma_keys->dk_size; + fast_nodes = PyMem_NEW(_ODictNode *, size); + if (fast_nodes == NULL) { + PyErr_NoMemory(); + return -1; + } + for (i = 0; i < size; i++) + fast_nodes[i] = NULL; + + /* Copy the current nodes into the table. */ + prev_size = od->od_size; + od->od_size = size; + _odict_FOREACH(od, node) { + assert(node != NULL); + i = _odict_get_index(od, _odictnode_KEY(node)); + if (i < 0) { + od->od_size = prev_size; + PyMem_FREE(fast_nodes); + return -1; + } + fast_nodes[i] = node; + } + if (size != ((PyDictObject *)od)->ma_keys->dk_size) { + /* If _odict_get_index triggered a resize then we are already done. */ + PyMem_FREE(fast_nodes); + return 0; + } + + /* Replace the old fast nodes table. */ + _odict_free_fast_nodes(od); + od->od_fast_nodes = fast_nodes; + return 0; +} + +/* Return the index into the hash table, regardless of a valid node. */ +static Py_ssize_t +_odict_get_index(PyODictObject *od, PyObject *key) +{ + Py_hash_t hash; + PyObject **value_addr = NULL; + PyDictKeyEntry *ep; + PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys; + + assert(key != NULL); + do { + /* Ensure od_fast_nodes and dk_entries are in sync. */ + if (keys->dk_size != od->od_size) { + int resize_res = _odict_resize(od); + if (resize_res < 0) + return -1; + } + + /* now get the index */ + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + /* May have resized during the PyObject_Hash() call. */ + keys = ((PyDictObject *)od)->ma_keys; + } while (keys->dk_size != od->od_size); + + ep = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr); + if (ep == NULL) + return -1; + /* We use pointer arithmetic to get the entry's index into the table. */ + return ep - keys->dk_entries; +} + +static int +_odict_initialize(PyODictObject *od) +{ + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + return _odict_resize((PyODictObject *)od); +} + +/* Returns NULL if there was some error or the key was not found. */ +static _ODictNode * +_odict_find_node(PyODictObject *od, PyObject *key) +{ + Py_ssize_t index; + + if (_odict_EMPTY(od)) + return NULL; + index = _odict_get_index(od, key); + if (index < 0) + return NULL; + return od->od_fast_nodes[index]; +} + +static void +_odict_add_head(PyODictObject *od, _ODictNode *node) +{ + if (_odict_FIRST(od) == NULL) { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; + _odict_FIRST(od) = node; + _odict_LAST(od) = node; + } + else { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = _odict_FIRST(od); + _odict_FIRST(od) = node; + _odictnode_PREV(_odict_FIRST(od)) = node; + } +} + +static void +_odict_add_tail(PyODictObject *od, _ODictNode *node) +{ + if (_odict_LAST(od) == NULL) { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; + _odict_FIRST(od) = node; + _odict_LAST(od) = node; + } + else { + _odictnode_PREV(node) = _odict_LAST(od); + _odictnode_NEXT(node) = NULL; + _odictnode_NEXT(_odict_LAST(od)) = node; + _odict_LAST(od) = node; + } +} + +/* adds the node to the end of the list */ +static int +_odict_add_new_node(PyODictObject *od, PyObject *key) +{ + Py_ssize_t i; + _ODictNode *node; + + Py_INCREF(key); + i = _odict_get_index(od, key); + if (i < 0) { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return -1; + } + else if (od->od_fast_nodes[i] != NULL) { + /* We already have a node for the key so there's no need to add one. */ + Py_DECREF(key); + return 0; + } + + /* must not be added yet */ + node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode)); + if (node == NULL) { + Py_DECREF(key); + PyErr_NoMemory(); + return -1; + } + + _odictnode_KEY(node) = key; + _odict_add_tail(od, node); + od->od_fast_nodes[i] = node; + return 0; +} + +/* Putting the decref after the free causes problems. */ +#define _odictnode_DEALLOC(node) \ + do { \ + Py_DECREF(_odictnode_KEY(node)); \ + PyMem_FREE((void *)node); \ + } while (0) + +/* Repeated calls on the same node are no-ops. */ +static void +_odict_remove_node(PyODictObject *od, _ODictNode *node) +{ + if (_odict_FIRST(od) == node) + _odict_FIRST(od) = _odictnode_NEXT(node); + else if (_odictnode_PREV(node) != NULL) + _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node); + + if (_odict_LAST(od) == node) + _odict_LAST(od) = _odictnode_PREV(node); + else if (_odictnode_NEXT(node) != NULL) + _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node); + + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; +} + +static _ODictNode * +_odict_pop_node(PyODictObject *od, _ODictNode *node, PyObject *key) +{ + if (node == NULL) { + node = _odict_find_node(od, key); + if (node == NULL) + return NULL; + } + _odict_remove_node(od, node); + return node; +} + +/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll + get all sorts of problems here. In PyODict_DelItem we make sure to + call _odict_clear_node first. + + This matters in the case of colliding keys. Suppose we add 3 keys: + [A, B, C], where the hash of C collides with A and the next possible + index in the hash table is occupied by B. If we remove B then for C + the dict's looknode func will give us the old index of B instead of + the index we got before deleting B. However, the node for C in + od_fast_nodes is still at the old dict index of C. Thus to be sure + things don't get out of sync, we clear the node in od_fast_nodes + *before* calling PyDict_DelItem. + + The same must be done for any other OrderedDict operations where + we modify od_fast_nodes. +*/ +static int +_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key) +{ + Py_ssize_t i; + + assert(key != NULL); + if (_odict_EMPTY(od)) { + /* Let later code decide if this is a KeyError. */ + return 0; + } + + i = _odict_get_index(od, key); + if (i < 0) + return PyErr_Occurred() ? -1 : 0; + + if (node == NULL) + node = od->od_fast_nodes[i]; + assert(node == od->od_fast_nodes[i]); + if (node == NULL) { + /* Let later code decide if this is a KeyError. */ + return 0; + } + + // Now clear the node. + od->od_fast_nodes[i] = NULL; + _odict_remove_node(od, node); + _odictnode_DEALLOC(node); + return 0; +} + +static void +_odict_clear_nodes(PyODictObject *od) +{ + _ODictNode *node, *next; + + if (!_odict_EMPTY(od)) { + node = _odict_FIRST(od); + while (node != NULL) { + next = _odictnode_NEXT(node); + _odictnode_DEALLOC(node); + node = next; + } + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + } + + _odict_free_fast_nodes(od); + od->od_fast_nodes = NULL; +} + +/* There isn't any memory management of nodes past this point. */ +#undef _odictnode_DEALLOC + +static int +_odict_keys_equal(PyODictObject *a, PyODictObject *b) +{ + _ODictNode *node_a, *node_b; + + node_a = _odict_FIRST(a); + node_b = _odict_FIRST(b); + while (1) { + if (node_a == NULL && node_b == NULL) + /* success: hit the end of each at the same time */ + return 1; + else if (node_a == NULL || node_b == NULL) + /* unequal length */ + return 0; + else { + int res = PyObject_RichCompareBool( + (PyObject *)_odictnode_KEY(node_a), + (PyObject *)_odictnode_KEY(node_b), + Py_EQ); + if (res < 0) + return res; + else if (res == 0) + return 0; + + /* otherwise it must match, so move on to the next one */ + node_a = _odictnode_NEXT(node_a); + node_b = _odictnode_NEXT(node_b); + } + } +} + + +/* ---------------------------------------------- + * OrderedDict mapping methods + */ + +/* mp_ass_subscript: __setitem__() and __delitem__() */ + +static int +odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w) +{ + if (w == NULL) + return PyODict_DelItem((PyObject *)od, v); + else + return PyODict_SetItem((PyObject *)od, v, w); +} + +/* tp_as_mapping */ + +static PyMappingMethods odict_as_mapping = { + 0, /*mp_length*/ + 0, /*mp_subscript*/ + (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/ +}; + + +/* ---------------------------------------------- + * OrderedDict methods + */ + +/* __delitem__() */ + +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\ + while comparison to a regular mapping is order-insensitive.\n\ + "); + +/* forward */ +static PyObject * odict_richcompare(PyObject *v, PyObject *w, int op); + +static PyObject * +odict_eq(PyObject *a, PyObject *b) +{ + return odict_richcompare(a, b, Py_EQ); +} + +/* __init__() */ + +PyDoc_STRVAR(odict_init__doc__, +"Initialize an ordered dictionary. The signature is the same as\n\ + regular dictionaries, but keyword arguments are not recommended because\n\ + their insertion order is arbitrary.\n\ +\n\ + "); + +/* forward */ +static int odict_init(PyObject *self, PyObject *args, PyObject *kwds); + +/* __iter__() */ + +PyDoc_STRVAR(odict_iter__doc__, "od.__iter__() <==> iter(od)"); + +static PyObject * odict_iter(PyODictObject *self); /* forward */ + +/* __ne__() */ + +/* Mapping.__ne__() does not have a docstring. */ +PyDoc_STRVAR(odict_ne__doc__, ""); + +static PyObject * +odict_ne(PyObject *a, PyObject *b) +{ + return odict_richcompare(a, b, Py_NE); +} + +/* __repr__() */ + +PyDoc_STRVAR(odict_repr__doc__, "od.__repr__() <==> repr(od)"); + +static PyObject * odict_repr(PyODictObject *self); /* forward */ + +/* __setitem__() */ + +PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y"); + +/* fromkeys() */ + +PyDoc_STRVAR(odict_fromkeys__doc__, +"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\ + If not specified, the value defaults to None.\n\ +\n\ + "); + +static PyObject * +odict_fromkeys(PyObject *cls, PyObject *args) +{ + PyObject *seq; + PyObject *value = Py_None; + if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value)) /* borrowed */ + return NULL; + return _PyDict_FromKeys(cls, seq, value); +} + +/* __sizeof__() */ + +/* OrderedDict.__sizeof__() does not have a docstring. */ +PyDoc_STRVAR(odict_sizeof__doc__, ""); + +static PyObject * +odict_sizeof(PyODictObject *od) +{ + PyObject *pylong; + Py_ssize_t res; + + pylong = _PyDict_SizeOf((PyDictObject *)od); + if (pylong == NULL) + return NULL; + res = PyLong_AsSsize_t(pylong); + Py_DECREF(pylong); + if (res == -1 && PyErr_Occurred()) + return NULL; + + res += sizeof(PyODictObject) - sizeof(PyDictObject); + + /* instance dict */ + pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict); + if (pylong == NULL) + return NULL; + res += PyLong_AsSsize_t(pylong); + Py_DECREF(pylong); + if (res == -1 && PyErr_Occurred()) + return NULL; + + res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ + if (!_odict_EMPTY(od)) { + res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */ + } + return PyLong_FromSsize_t(res); +} + +/* __reduce__() */ + +PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling"); + +static PyObject * +odict_reduce(register PyODictObject *od) +{ + _Py_IDENTIFIER(__dict__); + _Py_IDENTIFIER(__class__); + PyObject *vars = NULL, *ns = NULL, *result = NULL, *cls = NULL; + PyObject *items_iter = NULL, *items = NULL, *args = NULL; + + /* capture any instance state */ + vars = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__); + if (vars != NULL) { + PyObject *empty, *od_vars, *iterator, *key; + + /* od.__dict__ isn't necessarily a dict... */ + ns = PyObject_CallMethod((PyObject *)vars, "copy", NULL); + if (ns == NULL) + goto Done; + empty = PyODict_New(); + if (empty == NULL) + goto Done; + od_vars = _PyObject_GetAttrId((PyObject *)empty, &PyId___dict__); + Py_DECREF(empty); + if (od_vars == NULL) + goto Done; + iterator = PyObject_GetIter(od_vars); + Py_DECREF(od_vars); + if (iterator == NULL) + goto Done; + + while ( (key = PyIter_Next(iterator)) ) { + if (PyMapping_HasKey(ns, key) && PyMapping_DelItem(ns, key) != 0) { + Py_DECREF(iterator); + Py_DECREF(key); + goto Done; + } + Py_DECREF(key); + } + Py_DECREF(iterator); + if (PyErr_Occurred()) + goto Done; + + if (!PyObject_Length(ns)) { + /* nothing novel to pickle in od.__dict__ */ + Py_DECREF(ns); + ns = NULL; + } + } + + /* build the result */ + cls = _PyObject_GetAttrId((PyObject *)od, &PyId___class__); + if (cls == NULL) + goto Done; + + args = PyTuple_New(0); + if (args == NULL) + goto Done; + + items = PyObject_CallMethod((PyObject *)od, "items", NULL); + if (items == NULL) + goto Done; + + items_iter = PyObject_GetIter(items); + if (items_iter == NULL) + goto Done; + + result = PyTuple_Pack(5, cls, args, ns ? ns : Py_None, Py_None, items_iter); + +Done: + Py_XDECREF(vars); + Py_XDECREF(ns); + Py_XDECREF(cls); + Py_XDECREF(args); + Py_XDECREF(items); + Py_XDECREF(items_iter); + + return result; +} + +/* setdefault() */ + +PyDoc_STRVAR(odict_setdefault__doc__, + "od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od"); + +/* Skips __missing__() calls. */ +static PyObject * +odict_setdefault(register PyODictObject *od, PyObject *args) +{ + _ODictNode *node; + PyObject *key, *result = NULL; + PyObject *failobj = Py_None; + + /* both borrowed */ + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) + return NULL; + Py_INCREF(key); + Py_INCREF(failobj); + + if (PyODict_CheckExact(od)) { + node = _odict_find_node(od, key); + if (node == NULL) { + if (PyErr_Occurred()) { + goto done; + } + else if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) { + result = failobj; + Py_INCREF(failobj); + } + } + else { + result = PyODict_GetItem(od, key); /* borrowed reference */ + Py_XINCREF(result); + } + } + else { + int exists = PySequence_Contains((PyObject *)od, key); + if (exists < 0) { + goto done; + } + else if (exists) { + result = PyObject_GetItem((PyObject *)od, key); + } + else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) { + result = failobj; + Py_INCREF(failobj); + } + } + +done: + Py_DECREF(failobj); + Py_DECREF(key); + return result; +} + +/* pop() */ + +PyDoc_STRVAR(odict_pop__doc__, +"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\ + value. If key is not found, d is returned if given, otherwise KeyError\n\ + is raised.\n\ +\n\ + "); + +/* forward */ +static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *); + +/* Skips __missing__() calls. */ +static PyObject * +odict_pop(PyObject *od, PyObject *args) +{ + PyObject *key, *failobj = NULL; + + if (!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj)) { /* borrowed */ + return NULL; + } + + return _odict_popkey(od, key, failobj); +} + +static PyObject * +_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj) +{ + _ODictNode *node; + PyObject *value = NULL; + + Py_INCREF(key); + Py_XINCREF(failobj); + + /* Pop the node first to avoid a possible dict resize (due to + eval loop reentrancy) and complications due to hash collision + resolution. */ + node = _odict_find_node((PyODictObject *)od, key); + if (node == NULL) { + if (PyErr_Occurred()) + goto done; + } + else { + int res = _odict_clear_node((PyODictObject *)od, node, key); + if (res < 0) { + goto done; + } + } + + /* Now delete the value from the dict. */ + if (PyODict_CheckExact(od)) { + if (node != NULL) { + /* We could do PyDict_GetItem() and PyDict_DelItem() directly... */ + value = _PyDict_Pop((PyDictObject *)od, key, failobj); + } + } + else { + int exists = PySequence_Contains(od, key); + if (exists < 0) + goto done; + if (exists) { + value = PyObject_GetItem(od, key); + if (value != NULL) { + if (PyObject_DelItem(od, key) == -1) { + Py_DECREF(value); + value = NULL; + } + } + } + } + + /* Apply the fallback value, if necessary. */ + if (value == NULL && !PyErr_Occurred()) { + if (failobj) { + value = failobj; + Py_INCREF(failobj); + } + else { + PyErr_SetObject(PyExc_KeyError, key); + } + } + +done: + Py_DECREF(key); + Py_XDECREF(failobj); + return value; +} + +/* popitem() */ + +PyDoc_STRVAR(odict_popitem__doc__, +"od.popitem() -> (k, v), return and remove a (key, value) pair.\n\ + Pairs are returned in LIFO order if last is true or FIFO order if false.\n\ +\n\ + "); + +static PyObject * +odict_popitem(PyObject *od, PyObject *args) +{ + PyObject *key, *value, *item = NULL, *last = NULL; + _ODictNode *node; + + if (_odict_EMPTY((PyODictObject *)od)) { + PyErr_SetString(PyExc_KeyError, "dictionary is empty"); + return NULL; + } + + /* pull the item */ + + if (!PyArg_UnpackTuple(args, "popitem", 0, 1, &last)) /* borrowed */ + return NULL; + Py_XINCREF(last); + + if (last == NULL || last == Py_True) + node = _odict_LAST((PyODictObject *)od); + else + node = _odict_FIRST((PyODictObject *)od); + Py_XDECREF(last); + + key = _odictnode_KEY(node); + value = _odict_popkey(od, key, NULL); + if (value == NULL) + return NULL; + item = PyTuple_Pack(2, key, value); + Py_DECREF(value); + return item; +} + +/* keys() */ + +/* MutableMapping.keys() does not have a docstring. */ +PyDoc_STRVAR(odict_keys__doc__, ""); + +static PyObject * odictkeys_new(PyObject *od); /* forward */ + +/* values() */ + +/* MutableMapping.values() does not have a docstring. */ +PyDoc_STRVAR(odict_values__doc__, ""); + +static PyObject * odictvalues_new(PyObject *od); /* forward */ + +/* items() */ + +/* MutableMapping.items() does not have a docstring. */ +PyDoc_STRVAR(odict_items__doc__, ""); + +static PyObject * odictitems_new(PyObject *od); /* forward */ + +/* update() */ + +/* MutableMapping.update() does not have a docstring. */ +PyDoc_STRVAR(odict_update__doc__, ""); + +/* forward */ +static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *); + +#define odict_update mutablemapping_update + +/* clear() */ + +PyDoc_STRVAR(odict_clear__doc__, + "od.clear() -> None. Remove all items from od."); + +static PyObject * +odict_clear(register PyODictObject *od) +{ + PyDict_Clear((PyObject *)od); + _odict_clear_nodes(od); + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + if (_odict_resize(od) < 0) + return NULL; + Py_RETURN_NONE; +} + +/* copy() */ + +PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od"); + +static PyObject * +odict_copy(register PyODictObject *od) +{ + _ODictNode *node; + PyObject *od_copy; + + if (PyODict_CheckExact(od)) + od_copy = PyODict_New(); + else + od_copy = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(od), NULL); + if (od_copy == NULL) + return NULL; + + if (PyODict_CheckExact(od)) { + _odict_FOREACH(od, node) { + int res = PyODict_SetItem((PyObject *)od_copy, + _odictnode_KEY(node), + _odictnode_VALUE(node, od)); + if (res != 0) + goto fail; + } + } + else { + _odict_FOREACH(od, node) { + int res; + PyObject *value = PyObject_GetItem((PyObject *)od, + _odictnode_KEY(node)); + if (value == NULL) + goto fail; + res = PyObject_SetItem((PyObject *)od_copy, + _odictnode_KEY(node), value); + Py_DECREF(value); + if (res != 0) + goto fail; + } + } + return od_copy; + +fail: + Py_DECREF(od_copy); + return NULL; +} + +/* __reversed__() */ + +PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); + +#define _odict_ITER_REVERSED 1 +#define _odict_ITER_KEYS 2 +#define _odict_ITER_VALUES 4 + +/* forward */ +static PyObject * odictiter_new(PyODictObject *, int); + +static PyObject * +odict_reversed(PyODictObject *od) +{ + if (_odict_EMPTY(od)) { + Py_RETURN_NONE; + } + return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED); +} + +/* move_to_end() */ + +PyDoc_STRVAR(odict_move_to_end__doc__, +"Move an existing element to the end (or beginning if last==False).\n\ +\n\ + Raises KeyError if the element does not exist.\n\ + When last=True, acts like a fast version of self[key]=self.pop(key).\n\ +\n\ + "); + +static PyObject * +odict_move_to_end(PyODictObject *od, PyObject *args) +{ + PyObject *key, *last = NULL; + Py_ssize_t pos = -1; + + /* both borrowed */ + if (!PyArg_UnpackTuple(args, "move_to_end", 1, 2, &key, &last)) + return NULL; + Py_INCREF(key); + if (_odict_EMPTY(od)) { + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + if (last != NULL) { + Py_INCREF(last); + pos = PyObject_IsTrue(last) ? -1 : 0; + Py_DECREF(last); + } + if (pos == 0) { + /* Only move if not already the first one. */ + PyObject *first_key = _odictnode_KEY(_odict_FIRST(od)); + if (PyObject_RichCompareBool(key, first_key, Py_NE)) { + _ODictNode *node = _odict_pop_node(od, NULL, key); + if (node != NULL) { + _odict_add_head(od, node); + } + else { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + } + } + else if (pos == -1) { + /* Only move if not already the last one. */ + PyObject *last_key = _odictnode_KEY(_odict_LAST(od)); + if (PyObject_RichCompareBool(key, last_key, Py_NE)) { + _ODictNode *node = _odict_pop_node(od, NULL, key); + if (node != NULL) { + _odict_add_tail(od, node); + } + else { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + } + } + Py_DECREF(key); + Py_RETURN_NONE; +} + + +/* tp_methods */ + +static PyMethodDef odict_methods[] = { + + /* explicitly defined so we can align docstrings with + * collections.OrderedDict */ + {"__delitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS, + odict_delitem__doc__}, + {"__eq__", (PyCFunction)odict_eq, METH_NOARGS, + odict_eq__doc__}, + {"__init__", (PyCFunction)odict_init, METH_NOARGS, + odict_init__doc__}, + {"__iter__", (PyCFunction)odict_iter, METH_NOARGS, + odict_iter__doc__}, + {"__ne__", (PyCFunction)odict_ne, METH_NOARGS, + odict_ne__doc__}, + {"__repr__", (PyCFunction)odict_repr, METH_NOARGS, + odict_repr__doc__}, + {"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS, + odict_setitem__doc__}, + {"fromkeys", (PyCFunction)odict_fromkeys, METH_VARARGS | METH_CLASS, + odict_fromkeys__doc__}, + + /* overridden dict methods */ + {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS, + odict_sizeof__doc__}, + {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS, + odict_reduce__doc__}, + {"setdefault", (PyCFunction)odict_setdefault, METH_VARARGS, + odict_setdefault__doc__}, + {"pop", (PyCFunction)odict_pop, METH_VARARGS, + odict_pop__doc__}, + {"popitem", (PyCFunction)odict_popitem, METH_VARARGS, + odict_popitem__doc__}, + {"keys", (PyCFunction)odictkeys_new, METH_NOARGS, + odict_keys__doc__}, + {"values", (PyCFunction)odictvalues_new, METH_NOARGS, + odict_values__doc__}, + {"items", (PyCFunction)odictitems_new, METH_NOARGS, + odict_items__doc__}, + {"update", (PyCFunction)odict_update, METH_VARARGS | METH_KEYWORDS, + odict_update__doc__}, + {"clear", (PyCFunction)odict_clear, METH_NOARGS, + odict_clear__doc__}, + {"copy", (PyCFunction)odict_copy, METH_NOARGS, + odict_copy__doc__}, + + /* new methods */ + {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS, + odict_reversed__doc__}, + {"move_to_end", (PyCFunction)odict_move_to_end, METH_VARARGS, + odict_move_to_end__doc__}, + + {NULL, NULL} /* sentinel */ +}; + + +/* ---------------------------------------------- + * OrderedDict members + */ + +/* tp_members */ + +static PyMemberDef odict_members[] = { + {"__dict__", T_OBJECT, offsetof(PyODictObject, od_inst_dict), READONLY}, + {0} +}; + + +/* ---------------------------------------------- + * OrderedDict type slot methods + */ + +/* tp_dealloc */ + +static void +odict_dealloc(PyODictObject *self) +{ + PyObject_GC_UnTrack(self); + Py_TRASHCAN_SAFE_BEGIN(self); + Py_XDECREF(self->od_inst_dict); + if (self->od_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)self); + + _odict_clear_nodes(self); + Py_TRASHCAN_SAFE_END(self); + + /* must be last */ + PyDict_Type.tp_dealloc((PyObject *)self); +}; + +/* tp_repr */ + +static PyObject * +odict_repr(PyODictObject *self) +{ + int i; + const char *formatstr; + _Py_IDENTIFIER(__class__); + _Py_IDENTIFIER(__name__); + Py_ssize_t count = -1; + PyObject *pieces = NULL, *result = NULL, *cls = NULL; + PyObject *classname = NULL, *format = NULL, *args = NULL; + _ODictNode *node; + + i = Py_ReprEnter((PyObject *)self); + if (i != 0) { + return i > 0 ? PyUnicode_FromString("...") : NULL; + } + + if (PyODict_SIZE(self) == 0) { + /* "OrderedDict()" */ + goto Finish; + } + + if (PyODict_CheckExact(self)) { + pieces = PyList_New(PyODict_SIZE(self)); + if (pieces == NULL) + goto Done; + + _odict_FOREACH(self, node) { + PyObject *pair = PyTuple_Pack(2, _odictnode_KEY(node), + _odictnode_VALUE(node, self)); + if (pair == NULL) + goto Done; + + PyList_SET_ITEM(pieces, ++count, pair); /* steals reference */ + } + } + else { + PyObject *items = PyObject_CallMethod((PyObject *)self, "items", NULL); + if (items == NULL) + goto Done; + pieces = PySequence_List(items); + Py_DECREF(items); + if(pieces == NULL) + goto Done; + } + +Finish: + cls = _PyObject_GetAttrId((PyObject *)self, &PyId___class__); + if (cls == NULL) + goto Done; + classname = _PyObject_GetAttrId(cls, &PyId___name__); + if (classname == NULL) + goto Done; + + if (pieces == NULL) { + formatstr = "%s()"; + args = PyTuple_Pack(1, classname); + } + else { + formatstr = "%s(%r)"; + args = PyTuple_Pack(2, classname, pieces); + } + if (args == NULL) + goto Done; + + format = PyUnicode_InternFromString(formatstr); + if (format == NULL) + goto Done; + + result = PyUnicode_Format(format, args); +Done: + Py_XDECREF(pieces); + Py_XDECREF(cls); + Py_XDECREF(classname); + Py_XDECREF(format); + Py_XDECREF(args); + Py_ReprLeave((PyObject *)self); + return result; +}; + +/* tp_doc */ + +PyDoc_STRVAR(odict_doc, + "Dictionary that remembers insertion order"); + +/* tp_traverse */ + +static int +odict_traverse(PyODictObject *od, visitproc visit, void *arg) +{ + Py_VISIT(od->od_inst_dict); + Py_VISIT(od->od_weakreflist); + return PyDict_Type.tp_traverse((PyObject *)od, visit, arg); +} + +/* tp_clear */ + +static int +odict_tp_clear(PyODictObject *od) +{ + PyObject *res; + Py_CLEAR(od->od_inst_dict); + Py_CLEAR(od->od_weakreflist); + res = odict_clear(od); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +/* tp_richcompare */ + +static PyObject * +odict_richcompare(PyObject *v, PyObject *w, int op) +{ + if (!PyODict_Check(v) || !PyDict_Check(w)) { + Py_RETURN_NOTIMPLEMENTED; + } + + if (op == Py_EQ || op == Py_NE) { + PyObject *res, *cmp; + int eq; + + cmp = PyDict_Type.tp_richcompare(v, w, op); + if (cmp == NULL) + return NULL; + if (!PyODict_Check(w)) + return cmp; + if (op == Py_EQ && cmp == Py_False) + return cmp; + if (op == Py_NE && cmp == Py_True) + return cmp; + Py_DECREF(cmp); + + /* Try comparing odict keys. */ + eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w); + if (eq < 0) + return NULL; + + res = (eq == (op == Py_EQ)) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } else { + Py_RETURN_NOTIMPLEMENTED; + } +}; + +/* tp_iter */ + +static PyObject * +odict_iter(PyODictObject *od) +{ + return odictiter_new(od, _odict_ITER_KEYS); +}; + +/* tp_init */ + +static int +odict_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *res; + Py_ssize_t len = PyObject_Length(args); + + if (len == -1) + return -1; + if (len > 1) { + char *msg = "expected at most 1 arguments, got %d"; + PyErr_Format(PyExc_TypeError, msg, len); + return -1; + } + + /* __init__() triggering update() is just the way things are! */ + res = odict_update(self, args, kwds); + if (res == NULL) { + return -1; + } else { + Py_DECREF(res); + return 0; + } +}; + +/* tp_new */ + +static PyObject * +odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *od = PyDict_Type.tp_new(type, args, kwds); + if (od != NULL) { + ((PyODictObject *)od)->od_inst_dict = PyDict_New(); + ((PyODictObject *)od)->od_weakreflist = NULL; + if (_odict_initialize((PyODictObject *)od) < 0) + return NULL; + } + return od; +} + +/* PyODict_Type */ + +PyTypeObject PyODict_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "collections.OrderedDict", /* tp_name */ + sizeof(PyODictObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)odict_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)odict_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &odict_as_mapping, /* tp_as_mapping */ + 0, /* 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_HAVE_GC,/* tp_flags */ + odict_doc, /* tp_doc */ + (traverseproc)odict_traverse, /* tp_traverse */ + (inquiry)odict_tp_clear, /* tp_clear */ + (richcmpfunc)odict_richcompare, /* tp_richcompare */ + offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */ + (getiterfunc)odict_iter, /* tp_iter */ + 0, /* tp_iternext */ + odict_methods, /* tp_methods */ + odict_members, /* tp_members */ + 0, /* tp_getset */ + &PyDict_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */ + (initproc)odict_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + (newfunc)odict_new, /* tp_new */ + 0, /* tp_free */ +}; + + +/* ---------------------------------------------- + * the public OrderedDict API + */ + +PyObject * +PyODict_New(void) { + return odict_new(&PyODict_Type, NULL, NULL); +}; + +int +PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value) { + int res = PyDict_SetItem(od, key, value); + if (res == 0) { + res = _odict_add_new_node((PyODictObject *)od, key); + } + return res; +}; + +int +PyODict_DelItem(PyObject *od, PyObject *key) { + int res = _odict_clear_node((PyODictObject *)od, NULL, key); + if (res < 0) + return -1; + return PyDict_DelItem(od, key); +}; + + +/* ------------------------------------------- + * The OrderedDict views (keys/values/items) + */ + +typedef struct { + PyObject_HEAD + int kind; + PyODictObject *di_odict; + PyObject *di_current; + PyObject *di_result; /* reusable result tuple for iteritems */ +} odictiterobject; + +static void +odictiter_dealloc(odictiterobject *di) +{ + _PyObject_GC_UNTRACK(di); + Py_DECREF(di->di_odict); + Py_XDECREF(di->di_current); + if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + Py_DECREF(di->di_result); + } + PyObject_GC_Del(di); +} + +static int +odictiter_traverse(odictiterobject *di, visitproc visit, void *arg) +{ + Py_VISIT(di->di_odict); + Py_VISIT(di->di_current); /* A key could be any type, not just str. */ + Py_VISIT(di->di_result); + return 0; +} + +static PyObject * +odictiter_nextkey(odictiterobject *di) +{ + PyObject *key; + _ODictNode *node; + int reversed = di->kind & _odict_ITER_REVERSED; + + /* Get the key. */ + if (di->di_current == NULL) + return NULL; + node = _odict_find_node(di->di_odict, di->di_current); + if (node == NULL) { + /* Must have been deleted. */ + Py_DECREF(di->di_current); + di->di_current = NULL; + return NULL; + } + key = di->di_current; + + /* Advance to the next key. */ + node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node); + if (node == NULL) { + /* Reached the end. */ + di->di_current = NULL; + } + else { + di->di_current = _odictnode_KEY(node); + Py_INCREF(di->di_current); + } + + return key; +} + +static PyObject * +odictiter_iternext(odictiterobject *di) +{ + PyObject *value; + PyObject *key = odictiter_nextkey(di); /* new reference */ + + if (key == NULL) + return NULL; + + /* Handle the keys case. */ + if (! (di->kind & _odict_ITER_VALUES)) { + return key; + } + + /* Handle the items case. */ + if (di->kind & _odict_ITER_KEYS) { + PyObject *result = di->di_result; + + value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ + + if (result->ob_refcnt == 1) { + /* not in use so we can reuse it + * (the common case during iteration) */ + Py_INCREF(result); + Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */ + Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */ + } + else { + result = PyTuple_New(2); + if (result == NULL) + return NULL; + } + + Py_INCREF(value); + PyTuple_SET_ITEM(result, 0, key); /* steals reference */ + PyTuple_SET_ITEM(result, 1, value); /* steals reference */ + + return result; + } + /* Handle the values case. */ + else { + value = PyODict_GetItem((PyObject *)di->di_odict, key); + Py_XINCREF(value); + Py_DECREF(key); + return value; + } +} + +/* No need for tp_clear because odictiterobject is not mutable. */ + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling"); + +static PyObject * +odictiter_reduce(odictiterobject *di) +{ + PyObject *list; + + list = PyList_New(0); + if (!list) + return NULL; + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = odictiter_iternext(di); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + return NULL; + } + Py_DECREF(element); + } + else { + /* done iterating? */ + break; + } + } + if (PyErr_Occurred()) { + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); +} + +static PyMethodDef odictiter_methods[] = { + {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictIter_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_iterator", /* tp_name */ + sizeof(odictiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)odictiter_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_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)odictiter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)odictiter_iternext, /* tp_iternext */ + odictiter_methods, /* tp_methods */ + 0, +}; + +static PyObject * +odictiter_new(PyODictObject *od, int kind) +{ + odictiterobject *di; + _ODictNode *node; + int reversed = kind & _odict_ITER_REVERSED; + + di = PyObject_GC_New(odictiterobject, &PyODictIter_Type); + if (di == NULL) + return NULL; + + if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + di->di_result = PyTuple_Pack(2, Py_None, Py_None); + if (di->di_result == NULL) { + Py_DECREF(di); + return NULL; + } + } + else + di->di_result = NULL; + + di->kind = kind; + node = reversed ? _odict_LAST(od) : _odict_FIRST(od); + di->di_current = node ? _odictnode_KEY(node) : NULL; + Py_XINCREF(di->di_current); + di->di_odict = od; + Py_INCREF(od); + + _PyObject_GC_TRACK(di); + return (PyObject *)di; +} + +/* keys() */ + +static PyObject * +odictkeys_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS); +} + +static PyObject * +odictkeys_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_REVERSED); +} + +static PyMethodDef odictkeys_methods[] = { + {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictKeys_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_keys", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictkeys_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictkeys_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictKeys_Type, /* tp_base */ +}; + +static PyObject * +odictkeys_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictKeys_Type); +} + +/* items() */ + +static PyObject * +odictitems_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_VALUES); +} + +static PyObject * +odictitems_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED); +} + +static PyMethodDef odictitems_methods[] = { + {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictItems_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_items", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictitems_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictitems_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictItems_Type, /* tp_base */ +}; + +static PyObject * +odictitems_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictItems_Type); +} + +/* values() */ + +static PyObject * +odictvalues_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_VALUES); +} + +static PyObject * +odictvalues_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_VALUES|_odict_ITER_REVERSED); +} + +static PyMethodDef odictvalues_methods[] = { + {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictValues_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_values", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictvalues_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictvalues_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictValues_Type, /* tp_base */ +}; + +static PyObject * +odictvalues_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictValues_Type); +} + + +/* ---------------------------------------------- + MutableMappping implementations + +Mapping: + +============ =========== +method uses +============ =========== +__contains__ __getitem__ +__eq__ items +__getitem__ + +__iter__ + +__len__ + +__ne__ __eq__ +get __getitem__ +items ItemsView +keys KeysView +values ValuesView +============ =========== + +ItemsView uses __len__, __iter__, and __getitem__. +KeysView uses __len__, __iter__, and __contains__. +ValuesView uses __len__, __iter__, and __getitem__. + +MutableMapping: + +============ =========== +method uses +============ =========== +__delitem__ + +__setitem__ + +clear popitem +pop __getitem__ + __delitem__ +popitem __iter__ + _getitem__ + __delitem__ +setdefault __getitem__ + __setitem__ +update __setitem__ +============ =========== +*/ + +static int +mutablemapping_add_pairs(PyObject *self, PyObject *pairs) +{ + PyObject *pair, *iterator, *unexpected; + int res = 0; + + iterator = PyObject_GetIter(pairs); + if (iterator == NULL) + return -1; + PyErr_Clear(); + + while ((pair = PyIter_Next(iterator)) != NULL) { + /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */ + PyObject * key, *value = NULL; + PyObject *pair_iterator = PyObject_GetIter(pair); + + key = PyIter_Next(pair_iterator); + if (key == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "need more than 0 values to unpack"); + goto Done; + } + + value = PyIter_Next(pair_iterator); + if (value == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "need more than 1 value to unpack"); + goto Done; + } + + unexpected = PyIter_Next(pair_iterator); + if (unexpected != NULL) { + Py_DECREF(unexpected); + PyErr_SetString(PyExc_ValueError, + "too many values to unpack (expected 2)"); + goto Done; + } + else if (PyErr_Occurred()) + goto Done; + + res = PyObject_SetItem(self, key, value); + +Done: + Py_DECREF(pair); + Py_DECREF(pair_iterator); + Py_XDECREF(key); + Py_XDECREF(value); + if (PyErr_Occurred()) + break; + } + Py_DECREF(iterator); + + if (res < 0 || PyErr_Occurred() != NULL) + return -1; + else + return 0; +} + +static PyObject * +mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int res = 0; + Py_ssize_t len = (args != NULL) ? PyObject_Size(args) : 0; + + /* first handle args, if any */ + if (len < 0) + return NULL; + else if (len > 1) { + char *msg = "update() takes at most 1 positional argument (%d given)"; + PyErr_Format(PyExc_TypeError, msg, len); + return NULL; + } + else if (len == 1) { + PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */ + if (other == NULL) + return NULL; + Py_INCREF(other); + if (PyObject_HasAttrString(other, "items")) { + PyObject *items = PyMapping_Items(other); + Py_DECREF(other); + if (items == NULL) + return NULL; + res = mutablemapping_add_pairs(self, items); + Py_DECREF(items); + if (res == -1) + return NULL; + } + else if (PyObject_HasAttrString(other, "keys")) { + PyObject *keys, *iterator, *key; + keys = PyObject_CallMethod(other, "keys", NULL); + Py_DECREF(other); + if (keys == NULL) + return NULL; + iterator = PyObject_GetIter(keys); + Py_DECREF(keys); + if (iterator == NULL) + return NULL; + while (res == 0 && (key = PyIter_Next(iterator))) { + PyObject *value = PyObject_GetItem(other, key); + if (value != NULL) { + res = PyObject_SetItem(self, key, value); + Py_DECREF(value); + } + else { + res = -1; + } + Py_DECREF(key); + } + Py_DECREF(iterator); + if (res != 0 || PyErr_Occurred()) + return NULL; + } + else { + res = mutablemapping_add_pairs(self, other); + Py_DECREF(other); + if (res != 0) + return NULL; + } + } + + /* now handle kwargs */ + len = (kwargs != NULL) ? PyObject_Size(kwargs) : 0; + if (len < 0) + return NULL; + else if (len > 0) { + PyObject *items; + if (!PyMapping_Check(kwargs)) { + PyErr_SetString(PyExc_TypeError, "expected mapping for kwargs"); + return NULL; + } + items = PyMapping_Items(kwargs); + if (items == NULL) + return NULL; + res = mutablemapping_add_pairs(self, items); + Py_DECREF(items); + if (res == -1) + return NULL; + } + + Py_RETURN_NONE; +} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 06:34:20 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 04:34:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Add_a_C_implementation_of_collections=2EOrderedDict=2E?= Message-ID: <20150530043420.27658.46785@psf.io> https://hg.python.org/cpython/rev/b85028c9d4b9 changeset: 96363:b85028c9d4b9 branch: 3.5 parent: 96360:8428cb297d15 user: Eric Snow date: Fri May 29 22:21:39 2015 -0600 summary: Issue #16991: Add a C implementation of collections.OrderedDict. files: Include/Python.h | 1 + Include/dictobject.h | 15 +- Include/odictobject.h | 42 + Lib/collections/__init__.py | 21 +- Lib/test/test_collections.py | 202 +- Makefile.pre.in | 1 + Misc/NEWS | 2 + Modules/_collectionsmodule.c | 3 + Objects/dict-common.h | 22 + Objects/dictobject.c | 337 +- Objects/object.c | 15 + Objects/odictobject.c | 2394 ++++++++++++++++++++++ 12 files changed, 2860 insertions(+), 195 deletions(-) diff --git a/Include/Python.h b/Include/Python.h --- a/Include/Python.h +++ b/Include/Python.h @@ -85,6 +85,7 @@ #include "tupleobject.h" #include "listobject.h" #include "dictobject.h" +#include "odictobject.h" #include "enumobject.h" #include "setobject.h" #include "methodobject.h" diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -27,6 +27,11 @@ PyObject **ma_values; } PyDictObject; +typedef struct { + PyObject_HEAD + PyDictObject *dv_dict; +} _PyDictViewObject; + #endif /* Py_LIMITED_API */ PyAPI_DATA(PyTypeObject) PyDict_Type; @@ -40,9 +45,9 @@ #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) -#define PyDictKeys_Check(op) (Py_TYPE(op) == &PyDictKeys_Type) -#define PyDictItems_Check(op) (Py_TYPE(op) == &PyDictItems_Type) -#define PyDictValues_Check(op) (Py_TYPE(op) == &PyDictValues_Type) +#define PyDictKeys_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictKeys_Type)) +#define PyDictItems_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictItems_Type)) +#define PyDictValues_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictValues_Type)) /* This excludes Values, since they are not sets. */ # define PyDictViewSet_Check(op) \ (PyDictKeys_Check(op) || PyDictItems_Check(op)) @@ -75,6 +80,7 @@ PyAPI_FUNC(PyObject *) PyObject_GenericGetDict(PyObject *, void *); PyAPI_FUNC(int) _PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); +PyObject *_PyDictView_New(PyObject *, PyTypeObject *); #endif PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp); PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp); @@ -88,6 +94,9 @@ PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); +PyObject *_PyDict_SizeOf(PyDictObject *); +PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *); +PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) PyAPI_FUNC(int) PyDict_ClearFreeList(void); diff --git a/Include/odictobject.h b/Include/odictobject.h new file mode 100644 --- /dev/null +++ b/Include/odictobject.h @@ -0,0 +1,42 @@ +#ifndef Py_ODICTOBJECT_H +#define Py_ODICTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* OrderedDict */ + +#ifndef Py_LIMITED_API + +typedef struct _odictobject PyODictObject; + +PyAPI_DATA(PyTypeObject) PyODict_Type; +PyAPI_DATA(PyTypeObject) PyODictIter_Type; +PyAPI_DATA(PyTypeObject) PyODictKeys_Type; +PyAPI_DATA(PyTypeObject) PyODictItems_Type; +PyAPI_DATA(PyTypeObject) PyODictValues_Type; + +#endif /* Py_LIMITED_API */ + +#define PyODict_Check(op) PyObject_IsInstance(op, (PyObject *)&PyODict_Type) +#define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) +#define PyODict_SIZE(op) ((PyDictObject *)op)->ma_used +#define PyODict_HasKey(od, key) (PyMapping_HasKey(PyObject *)od, key) + +PyAPI_FUNC(PyObject *) PyODict_New(void); +PyAPI_FUNC(int) PyODict_SetItem(PyObject *od, PyObject *key, PyObject *item); +PyAPI_FUNC(int) PyODict_DelItem(PyObject *od, PyObject *key); + +/* wrappers around PyDict* functions */ +#define PyODict_GetItem(od, key) PyDict_GetItem((PyObject *)od, key) +#define PyODict_Contains(od, key) PyDict_Contains((PyObject *)od, key) +#define PyODict_Size(od) PyDict_Size((PyObject *)od) +#define PyODict_GetItemString(od, key) \ + PyDict_GetItemString((PyObject *)od, key) +#define Py_ODict_GetItemId(od, key) _PyDict_GetItemId((PyObject *)od, key) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ODICTOBJECT_H */ diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -7,7 +7,6 @@ import _collections_abc __all__ += _collections_abc.__all__ -from _collections import deque, defaultdict from operator import itemgetter as _itemgetter, eq as _eq from keyword import iskeyword as _iskeyword import sys as _sys @@ -16,7 +15,18 @@ from itertools import repeat as _repeat, chain as _chain, starmap as _starmap from reprlib import recursive_repr as _recursive_repr -MutableSequence.register(deque) +try: + from _collections import deque +except ImportError: + pass +else: + MutableSequence.register(deque) + +try: + from _collections import defaultdict +except ImportError: + pass + ################################################################################ ### OrderedDict @@ -264,6 +274,13 @@ return dict.__eq__(self, other) +try: + from _collections import OrderedDict +except ImportError: + # Leave the pure Python version in place. + pass + + ################################################################################ ### namedtuple ################################################################################ diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1,7 +1,8 @@ """Unit tests for collections.py.""" import unittest, doctest, operator -from test.support import TESTFN, forget, unlink +from test.support import TESTFN, forget, unlink, import_fresh_module +import contextlib import inspect from test import support from collections import namedtuple, Counter, OrderedDict, _count_elements @@ -1609,9 +1610,24 @@ ### OrderedDict ################################################################################ -class TestOrderedDict(unittest.TestCase): +py_coll = import_fresh_module('collections', blocked=['_collections']) +c_coll = import_fresh_module('collections', fresh=['_collections']) + + + at contextlib.contextmanager +def replaced_module(name, replacement): + original_module = sys.modules[name] + sys.modules[name] = replacement + try: + yield + finally: + sys.modules[name] = original_module + + +class OrderedDictTests: def test_init(self): + OrderedDict = self.module.OrderedDict with self.assertRaises(TypeError): OrderedDict([('a', 1), ('b', 2)], None) # too many args pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] @@ -1635,6 +1651,7 @@ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) def test_update(self): + OrderedDict = self.module.OrderedDict with self.assertRaises(TypeError): OrderedDict().update([('a', 1), ('b', 2)], None) # too many args pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] @@ -1675,11 +1692,17 @@ self.assertRaises(TypeError, OrderedDict().update, (), ()) self.assertRaises(TypeError, OrderedDict.update) + self.assertRaises(TypeError, OrderedDict().update, 42) + self.assertRaises(TypeError, OrderedDict().update, (), ()) + self.assertRaises(TypeError, OrderedDict.update) + def test_abc(self): + OrderedDict = self.module.OrderedDict self.assertIsInstance(OrderedDict(), MutableMapping) self.assertTrue(issubclass(OrderedDict, MutableMapping)) def test_clear(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1688,6 +1711,7 @@ self.assertEqual(len(od), 0) def test_delitem(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] od = OrderedDict(pairs) del od['a'] @@ -1697,6 +1721,7 @@ self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) def test_setitem(self): + OrderedDict = self.module.OrderedDict od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) od['c'] = 10 # existing element od['f'] = 20 # new element @@ -1704,6 +1729,7 @@ [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) def test_iterators(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1720,6 +1746,11 @@ self.assertEqual(list(reversed(od.items())), list(reversed(pairs))) def test_detect_deletion_during_iteration(self): + # XXX This test should also work under cOrderedDict. + if self.module is c_coll: + raise unittest.SkipTest("only valid for pure Python OrderedDict") + + OrderedDict = self.module.OrderedDict od = OrderedDict.fromkeys('abc') it = iter(od) key = next(it) @@ -1729,7 +1760,21 @@ # The only guarantee that the next() will not succeed next(it) + def test_sorted_iterators(self): + OrderedDict = self.module.OrderedDict + with self.assertRaises(TypeError): + OrderedDict([('a', 1), ('b', 2)], None) + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + od = OrderedDict(pairs) + self.assertEqual(sorted(od), [t[0] for t in pairs]) + self.assertEqual(sorted(od.keys()), [t[0] for t in pairs]) + self.assertEqual(sorted(od.values()), [t[1] for t in pairs]) + self.assertEqual(sorted(od.items()), pairs) + self.assertEqual(sorted(reversed(od)), + sorted([t[0] for t in reversed(pairs)])) + def test_popitem(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1739,7 +1784,18 @@ od.popitem() self.assertEqual(len(od), 0) + def test_popitem_last(self): + OrderedDict = self.module.OrderedDict + pairs = [(i, i) for i in range(30)] + + obj = OrderedDict(pairs) + for i in range(8): + obj.popitem(True) + obj.popitem(True) + self.assertEqual(len(obj), 21) + def test_pop(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1764,6 +1820,7 @@ m.pop('a') def test_equality(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od1 = OrderedDict(pairs) @@ -1779,6 +1836,7 @@ self.assertNotEqual(od1, OrderedDict(pairs[:-1])) def test_copying(self): + OrderedDict = self.module.OrderedDict # Check that ordered dicts are copyable, deepcopyable, picklable, # and have a repr/eval round-trip pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1787,12 +1845,17 @@ msg = "\ncopy: %s\nod: %s" % (dup, od) self.assertIsNot(dup, od, msg) self.assertEqual(dup, od) + self.assertEqual(list(dup.items()), list(od.items())) + self.assertEqual(len(dup), len(od)) + self.assertEqual(type(dup), type(od)) check(od.copy()) check(copy.copy(od)) check(copy.deepcopy(od)) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(proto=proto): - check(pickle.loads(pickle.dumps(od, proto))) + # pickle directly pulls the module, so we have to fake it + with replaced_module('collections', self.module): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + check(pickle.loads(pickle.dumps(od, proto))) check(eval(repr(od))) update_test = OrderedDict() update_test.update(od) @@ -1800,6 +1863,7 @@ check(OrderedDict(od)) def test_yaml_linkage(self): + OrderedDict = self.module.OrderedDict # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature. # In yaml, lists are native but tuples are not. pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1809,6 +1873,7 @@ self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1])) def test_reduce_not_too_fat(self): + OrderedDict = self.module.OrderedDict # do not save instance dictionary if not needed pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] od = OrderedDict(pairs) @@ -1817,15 +1882,20 @@ self.assertIsNotNone(od.__reduce__()[2]) def test_pickle_recursive(self): + OrderedDict = self.module.OrderedDict od = OrderedDict() od[1] = od - for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): - dup = pickle.loads(pickle.dumps(od, proto)) - self.assertIsNot(dup, od) - self.assertEqual(list(dup.keys()), [1]) - self.assertIs(dup[1], dup) + + # pickle directly pulls the module, so we have to fake it + with replaced_module('collections', self.module): + for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1): + dup = pickle.loads(pickle.dumps(od, proto)) + self.assertIsNot(dup, od) + self.assertEqual(list(dup.keys()), [1]) + self.assertIs(dup[1], dup) def test_repr(self): + OrderedDict = self.module.OrderedDict od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) self.assertEqual(repr(od), "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") @@ -1833,6 +1903,7 @@ self.assertEqual(repr(OrderedDict()), "OrderedDict()") def test_repr_recursive(self): + OrderedDict = self.module.OrderedDict # See issue #9826 od = OrderedDict.fromkeys('abc') od['x'] = od @@ -1840,6 +1911,7 @@ "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])") def test_setdefault(self): + OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) od = OrderedDict(pairs) @@ -1858,16 +1930,19 @@ self.assertEqual(Missing().setdefault(5, 9), 9) def test_reinsert(self): + OrderedDict = self.module.OrderedDict # Given insert a, insert b, delete a, re-insert a, # verify that a is now later than b. od = OrderedDict() od['a'] = 1 od['b'] = 2 del od['a'] + self.assertEqual(list(od.items()), [('b', 2)]) od['a'] = 1 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) def test_move_to_end(self): + OrderedDict = self.module.OrderedDict od = OrderedDict.fromkeys('abcde') self.assertEqual(list(od), list('abcde')) od.move_to_end('c') @@ -1880,14 +1955,19 @@ self.assertEqual(list(od), list('cabde')) with self.assertRaises(KeyError): od.move_to_end('x') + with self.assertRaises(KeyError): + od.move_to_end('x', 0) def test_sizeof(self): + OrderedDict = self.module.OrderedDict # Wimpy test: Just verify the reported size is larger than a regular dict d = dict(a=1) od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) + OrderedDict = self.module.OrderedDict def test_override_update(self): + OrderedDict = self.module.OrderedDict # Verify that subclasses can override update() without breaking __init__() class MyOD(OrderedDict): def update(self, *args, **kwds): @@ -1895,18 +1975,101 @@ items = [('a', 1), ('c', 3), ('b', 2)] self.assertEqual(list(MyOD(items).items()), items) -class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): - type2test = OrderedDict + +class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase): + + module = py_coll + + + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase): + + module = c_coll + + def test_delitem_hash_collision(self): + OrderedDict = self.module.OrderedDict + + class Key: + def __init__(self, hash): + self._hash = hash + self.value = str(id(self)) + def __hash__(self): + return self._hash + def __eq__(self, other): + try: + return self.value == other.value + except AttributeError: + return False + def __repr__(self): + return self.value + + def blocking_hash(hash): + # See the collision-handling in lookdict (in Objects/dictobject.c). + MINSIZE = 8 + i = (hash & MINSIZE-1) + return (i << 2) + i + hash + 1 + + COLLIDING = 1 + + key = Key(COLLIDING) + colliding = Key(COLLIDING) + blocking = Key(blocking_hash(COLLIDING)) + + od = OrderedDict() + od[key] = ... + od[blocking] = ... + od[colliding] = ... + od['after'] = ... + + del od[blocking] + del od[colliding] + self.assertEqual(list(od.items()), [(key, ...), ('after', ...)]) + + +class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + cls.type2test = py_coll.OrderedDict def test_popitem(self): d = self._empty_mapping() self.assertRaises(KeyError, d.popitem) -class MyOrderedDict(OrderedDict): - pass -class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): - type2test = MyOrderedDict + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + cls.type2test = c_coll.OrderedDict + + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + + +class PurePythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + class MyOrderedDict(py_coll.OrderedDict): + pass + cls.type2test = MyOrderedDict + + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + + + at unittest.skipUnless(c_coll, 'requires the C version of the collections module') +class CPythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + + @classmethod + def setUpClass(cls): + class MyOrderedDict(c_coll.OrderedDict): + pass + cls.type2test = MyOrderedDict def test_popitem(self): d = self._empty_mapping() @@ -1923,8 +2086,11 @@ NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, TestCollectionABCs, TestCounter, TestChainMap, - TestOrderedDict, GeneralMappingTests, SubclassMappingTests, - TestUserObjects] + PurePythonOrderedDictTests, CPythonOrderedDictTests, + PurePythonGeneralMappingTests, CPythonGeneralMappingTests, + PurePythonSubclassMappingTests, CPythonSubclassMappingTests, + TestUserObjects, + ] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -437,6 +437,7 @@ Objects/listobject.o \ Objects/longobject.o \ Objects/dictobject.o \ + Objects/odictobject.o \ Objects/memoryobject.o \ Objects/methodobject.o \ Objects/moduleobject.o \ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,8 @@ - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. +- Issue #16991: Add a C implementation of OrderedDict. + What's New in Python 3.5.0 beta 1? ================================== diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2263,6 +2263,9 @@ Py_INCREF(&defdict_type); PyModule_AddObject(m, "defaultdict", (PyObject *)&defdict_type); + Py_INCREF(&PyODict_Type); + PyModule_AddObject(m, "OrderedDict", (PyObject *)&PyODict_Type); + if (PyType_Ready(&dequeiter_type) < 0) return NULL; Py_INCREF(&dequeiter_type); diff --git a/Objects/dict-common.h b/Objects/dict-common.h new file mode 100644 --- /dev/null +++ b/Objects/dict-common.h @@ -0,0 +1,22 @@ +#ifndef Py_DICT_COMMON_H +#define Py_DICT_COMMON_H + +typedef struct { + /* Cached hash code of me_key. */ + Py_hash_t me_hash; + PyObject *me_key; + PyObject *me_value; /* This field is only meaningful for combined tables */ +} PyDictKeyEntry; + +typedef PyDictKeyEntry *(*dict_lookup_func) +(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); + +struct _dictkeysobject { + Py_ssize_t dk_refcnt; + Py_ssize_t dk_size; + dict_lookup_func dk_lookup; + Py_ssize_t dk_usable; + PyDictKeyEntry dk_entries[1]; +}; + +#endif diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -67,6 +67,7 @@ #define PyDict_MINSIZE_COMBINED 8 #include "Python.h" +#include "dict-common.h" #include "stringlib/eq.h" /*[clinic input] @@ -74,24 +75,6 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/ -typedef struct { - /* Cached hash code of me_key. */ - Py_hash_t me_hash; - PyObject *me_key; - PyObject *me_value; /* This field is only meaningful for combined tables */ -} PyDictKeyEntry; - -typedef PyDictKeyEntry *(*dict_lookup_func) -(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr); - -struct _dictkeysobject { - Py_ssize_t dk_refcnt; - Py_ssize_t dk_size; - dict_lookup_func dk_lookup; - Py_ssize_t dk_usable; - PyDictKeyEntry dk_entries[1]; -}; - /* To ensure the lookup algorithm terminates, there must be at least one Unused @@ -1425,6 +1408,141 @@ return 1; } +/* Internal version of dict.pop(). */ +PyObject * +_PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) +{ + Py_hash_t hash; + PyObject *old_value, *old_key; + PyDictKeyEntry *ep; + PyObject **value_addr; + + if (mp->ma_used == 0) { + if (deflt) { + Py_INCREF(deflt); + return deflt; + } + _PyErr_SetKeyError(key); + return NULL; + } + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return NULL; + } + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + if (ep == NULL) + return NULL; + old_value = *value_addr; + if (old_value == NULL) { + if (deflt) { + Py_INCREF(deflt); + return deflt; + } + _PyErr_SetKeyError(key); + return NULL; + } + *value_addr = NULL; + mp->ma_used--; + if (!_PyDict_HasSplitTable(mp)) { + ENSURE_ALLOWS_DELETIONS(mp); + old_key = ep->me_key; + Py_INCREF(dummy); + ep->me_key = dummy; + Py_DECREF(old_key); + } + return old_value; +} + +/* Internal version of dict.from_keys(). It is subclass-friendly. */ +PyObject * +_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) +{ + PyObject *it; /* iter(iterable) */ + PyObject *key; + PyObject *d; + int status; + + d = PyObject_CallObject(cls, NULL); + if (d == NULL) + return NULL; + + if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) { + if (PyDict_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + PyObject *oldvalue; + Py_ssize_t pos = 0; + PyObject *key; + Py_hash_t hash; + + if (dictresize(mp, Py_SIZE(iterable))) { + Py_DECREF(d); + return NULL; + } + + while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { + if (insertdict(mp, key, hash, value)) { + Py_DECREF(d); + return NULL; + } + } + return d; + } + if (PyAnySet_CheckExact(iterable)) { + PyDictObject *mp = (PyDictObject *)d; + Py_ssize_t pos = 0; + PyObject *key; + Py_hash_t hash; + + if (dictresize(mp, PySet_GET_SIZE(iterable))) { + Py_DECREF(d); + return NULL; + } + + while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { + if (insertdict(mp, key, hash, value)) { + Py_DECREF(d); + return NULL; + } + } + return d; + } + } + + it = PyObject_GetIter(iterable); + if (it == NULL){ + Py_DECREF(d); + return NULL; + } + + if (PyDict_CheckExact(d)) { + while ((key = PyIter_Next(it)) != NULL) { + status = PyDict_SetItem(d, key, value); + Py_DECREF(key); + if (status < 0) + goto Fail; + } + } else { + while ((key = PyIter_Next(it)) != NULL) { + status = PyObject_SetItem(d, key, value); + Py_DECREF(key); + if (status < 0) + goto Fail; + } + } + + if (PyErr_Occurred()) + goto Fail; + Py_DECREF(it); + return d; + +Fail: + Py_DECREF(it); + Py_DECREF(d); + return NULL; +} + /* Methods */ static void @@ -1763,88 +1881,7 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) /*[clinic end generated code: output=8fb98e4b10384999 input=b85a667f9bf4669d]*/ { - PyObject *it; /* iter(seq) */ - PyObject *key; - PyObject *d; - int status; - - d = PyObject_CallObject((PyObject *)type, NULL); - if (d == NULL) - return NULL; - - if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) { - if (PyDict_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - PyObject *oldvalue; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, Py_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - if (PyAnySet_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, PySet_GET_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - } - - it = PyObject_GetIter(iterable); - if (it == NULL){ - Py_DECREF(d); - return NULL; - } - - if (PyDict_CheckExact(d)) { - while ((key = PyIter_Next(it)) != NULL) { - status = PyDict_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } else { - while ((key = PyIter_Next(it)) != NULL) { - status = PyObject_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } - - if (PyErr_Occurred()) - goto Fail; - Py_DECREF(it); - return d; - -Fail: - Py_DECREF(it); - Py_DECREF(d); - return NULL; + return _PyDict_FromKeys((PyObject *)type, iterable, value); } static int @@ -2356,50 +2393,12 @@ static PyObject * dict_pop(PyDictObject *mp, PyObject *args) { - Py_hash_t hash; - PyObject *old_value, *old_key; PyObject *key, *deflt = NULL; - PyDictKeyEntry *ep; - PyObject **value_addr; if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt)) return NULL; - if (mp->ma_used == 0) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - old_value = *value_addr; - if (old_value == NULL) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - *value_addr = NULL; - mp->ma_used--; - if (!_PyDict_HasSplitTable(mp)) { - ENSURE_ALLOWS_DELETIONS(mp); - old_key = ep->me_key; - Py_INCREF(dummy); - ep->me_key = dummy; - Py_DECREF(old_key); - } - return old_value; + + return _PyDict_Pop(mp, key, deflt); } static PyObject * @@ -2506,8 +2505,8 @@ static PyObject *dictiter_new(PyDictObject *, PyTypeObject *); -static PyObject * -dict_sizeof(PyDictObject *mp) +PyObject * +_PyDict_SizeOf(PyDictObject *mp) { Py_ssize_t size, res; @@ -2575,7 +2574,7 @@ DICT___CONTAINS___METHODDEF {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST, getitem__doc__}, - {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS, + {"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS, sizeof__doc__}, {"get", (PyCFunction)dict_get, METH_VARARGS, get__doc__}, @@ -3104,8 +3103,8 @@ value = *value_ptr; Py_INCREF(key); Py_INCREF(value); - PyTuple_SET_ITEM(result, 0, key); - PyTuple_SET_ITEM(result, 1, value); + PyTuple_SET_ITEM(result, 0, key); /* steals reference */ + PyTuple_SET_ITEM(result, 1, value); /* steals reference */ return result; fail: @@ -3200,28 +3199,22 @@ /* The instance lay-out is the same for all three; but the type differs. */ -typedef struct { - PyObject_HEAD - PyDictObject *dv_dict; -} dictviewobject; - - static void -dictview_dealloc(dictviewobject *dv) +dictview_dealloc(_PyDictViewObject *dv) { Py_XDECREF(dv->dv_dict); PyObject_GC_Del(dv); } static int -dictview_traverse(dictviewobject *dv, visitproc visit, void *arg) +dictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg) { Py_VISIT(dv->dv_dict); return 0; } static Py_ssize_t -dictview_len(dictviewobject *dv) +dictview_len(_PyDictViewObject *dv) { Py_ssize_t len = 0; if (dv->dv_dict != NULL) @@ -3229,10 +3222,10 @@ return len; } -static PyObject * -dictview_new(PyObject *dict, PyTypeObject *type) +PyObject * +_PyDictView_New(PyObject *dict, PyTypeObject *type) { - dictviewobject *dv; + _PyDictViewObject *dv; if (dict == NULL) { PyErr_BadInternalCall(); return NULL; @@ -3244,7 +3237,7 @@ type->tp_name, dict->ob_type->tp_name); return NULL; } - dv = PyObject_GC_New(dictviewobject, type); + dv = PyObject_GC_New(_PyDictViewObject, type); if (dv == NULL) return NULL; Py_INCREF(dict); @@ -3348,7 +3341,7 @@ } static PyObject * -dictview_repr(dictviewobject *dv) +dictview_repr(_PyDictViewObject *dv) { PyObject *seq; PyObject *result; @@ -3365,7 +3358,7 @@ /*** dict_keys ***/ static PyObject * -dictkeys_iter(dictviewobject *dv) +dictkeys_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3374,7 +3367,7 @@ } static int -dictkeys_contains(dictviewobject *dv, PyObject *obj) +dictkeys_contains(_PyDictViewObject *dv, PyObject *obj) { if (dv->dv_dict == NULL) return 0; @@ -3499,7 +3492,7 @@ PyObject *item = NULL; if (self == other) { - if (dictview_len((dictviewobject *)self) == 0) + if (dictview_len((_PyDictViewObject *)self) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -3508,7 +3501,7 @@ /* Iterate over the shorter object (only if other is a set, * because PySequence_Contains may be expensive otherwise): */ if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) { - Py_ssize_t len_self = dictview_len((dictviewobject *)self); + Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self); Py_ssize_t len_other = PyObject_Size(other); if (len_other == -1) return NULL; @@ -3555,7 +3548,7 @@ PyTypeObject PyDictKeys_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_keys", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3588,13 +3581,13 @@ static PyObject * dictkeys_new(PyObject *dict) { - return dictview_new(dict, &PyDictKeys_Type); + return _PyDictView_New(dict, &PyDictKeys_Type); } /*** dict_items ***/ static PyObject * -dictitems_iter(dictviewobject *dv) +dictitems_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3603,7 +3596,7 @@ } static int -dictitems_contains(dictviewobject *dv, PyObject *obj) +dictitems_contains(_PyDictViewObject *dv, PyObject *obj) { PyObject *key, *value, *found; if (dv->dv_dict == NULL) @@ -3641,7 +3634,7 @@ PyTypeObject PyDictItems_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_items", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3674,13 +3667,13 @@ static PyObject * dictitems_new(PyObject *dict) { - return dictview_new(dict, &PyDictItems_Type); + return _PyDictView_New(dict, &PyDictItems_Type); } /*** dict_values ***/ static PyObject * -dictvalues_iter(dictviewobject *dv) +dictvalues_iter(_PyDictViewObject *dv) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -3706,7 +3699,7 @@ PyTypeObject PyDictValues_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "dict_values", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ + sizeof(_PyDictViewObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)dictview_dealloc, /* tp_dealloc */ @@ -3739,7 +3732,7 @@ static PyObject * dictvalues_new(PyObject *dict) { - return dictview_new(dict, &PyDictValues_Type); + return _PyDictView_New(dict, &PyDictValues_Type); } /* Returns NULL if cannot allocate a new PyDictKeysObject, diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1607,6 +1607,21 @@ if (PyType_Ready(&PyDict_Type) < 0) Py_FatalError("Can't initialize dict type"); + if (PyType_Ready(&PyODict_Type) < 0) + Py_FatalError("Can't initialize OrderedDict type"); + + if (PyType_Ready(&PyODictKeys_Type) < 0) + Py_FatalError("Can't initialize odict_keys type"); + + if (PyType_Ready(&PyODictItems_Type) < 0) + Py_FatalError("Can't initialize odict_items type"); + + if (PyType_Ready(&PyODictValues_Type) < 0) + Py_FatalError("Can't initialize odict_values type"); + + if (PyType_Ready(&PyODictIter_Type) < 0) + Py_FatalError("Can't initialize odict_keyiterator type"); + if (PyType_Ready(&PySet_Type) < 0) Py_FatalError("Can't initialize set type"); diff --git a/Objects/odictobject.c b/Objects/odictobject.c new file mode 100644 --- /dev/null +++ b/Objects/odictobject.c @@ -0,0 +1,2394 @@ +/* Ordered Dictionary object implementation. + +This implementation is necessarily explicitly equivalent to the pure Python +OrderedDict class in Lib/collections/__init__.py. The strategy there +involves using a doubly-linked-list to capture the order. We keep to that +strategy, using a lower-level linked-list. + +About the Linked-List +===================== + +For the linked list we use a basic doubly-linked-list. Using a circularly- +linked-list does have some benefits, but they don't apply so much here +since OrderedDict is focused on the ends of the list (for the most part). +Furthermore, there are some features of generic linked-lists that we simply +don't need for OrderedDict. Thus a simple custom implementation meets our +needs. Alternatives to our simple approach include the QCIRCLE_* +macros from BSD's queue.h, and the linux's list.h. + +Getting O(1) Node Lookup +------------------------ + +One invariant of Python's OrderedDict is that it preserves time complexity +of dict's methods, particularly the O(1) operations. Simply adding a +linked-list on top of dict is not sufficient here; operations for nodes in +the middle of the linked-list implicitly require finding the node first. +With a simple linked-list like we're using, that is an O(n) operation. +Consequently, methods like __delitem__() would change from O(1) to O(n), +which is unacceptable. + +In order to preserve O(1) performance for node removal (finding nodes), we +must do better than just looping through the linked-list. Here are options +we've considered: + +1. use a second dict to map keys to nodes (a la the pure Python version). +2. keep a simple hash table mirroring the order of dict's, mapping each key + to the corresponding node in the linked-list. +3. use a version of shared keys (split dict) that allows non-unicode keys. +4. have the value stored for each key be a (value, node) pair, and adjust + __getitem__(), get(), etc. accordingly. + +The approach with the least performance impact (time and space) is #2, +mirroring the key order of dict's dk_enties with an array of node pointers. +While lookdict() and friends (dk_lookup) don't give us the index into the +array, we make use of pointer arithmetic to get that index. An alternative +would be to refactor lookdict() to provide the index, explicitly exposing +the implementation detail. We could even just use a custom lookup function +for OrderedDict that facilitates our need. However, both approaches are +significantly more complicated than just using pointer arithmetic. + +The catch with mirroring the hash table ordering is that we have to keep +the ordering in sync through any dict resizes. However, that order only +matters during node lookup. We can simply defer any potential resizing +until we need to do a lookup. + +Linked-List Nodes +----------------- + +The current implementation stores a pointer to the associated key only. +One alternative would be to store a pointer to the PyDictKeyEntry instead. +This would save one pointer de-reference per item, which is nice during +calls to values() and items(). However, it adds unnecessary overhead +otherwise, so we stick with just the key. + +Linked-List API +--------------- + +As noted, the linked-list implemented here does not have all the bells and +whistles. However, we recognize that the implementation may need to +change to accommodate performance improvements or extra functionality. To +that end, We use a simple API to interact with the linked-list. Here's a +summary of the methods/macros: + +Node info: + +* _odictnode_KEY(node) +* _odictnode_VALUE(od, node) +* _odictnode_PREV(node) +* _odictnode_NEXT(node) + +Linked-List info: + +* _odict_FIRST(od) +* _odict_LAST(od) +* _odict_EMPTY(od) +* _odict_FOREACH(od, node) - used in place of `for (node=...)` + +For adding nodes: + +* _odict_add_head(od, node) +* _odict_add_tail(od, node) +* _odict_add_new_node(od, key) + +For removing nodes: + +* _odict_pop_node(od, node, key) +* _odict_clear_node(od, node) +* _odict_clear_nodes(od, clear_each) + +Others: + +* _odict_initialize(od) +* _odict_find_node(od, key) +* _odict_keys_equal(od1, od2) + +Used, but specific to the linked-list implementation: + +* _odict_free_fast_nodes(od) + +And here's a look at how the linked-list relates to the OrderedDict API: + +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === +method key val prev next mem 1st last empty iter find add rmv clr keq +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === +__del__ ~ X +__delitem__ free ~ node +__eq__ ~ X +__iter__ X X +__new__ X X +__reduce__ X ~ X +__repr__ X X X +__reversed__ X X +__setitem__ key +__sizeof__ size X +clear ~ ~ X +copy X X X +items X X X +keys X X +move_to_end X X X ~ h/t key +pop free key +popitem X X free X X node +setdefault ~ ? ~ +values X X +============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === === + +__delitem__ is the only method that directly relies on finding an arbitrary +node in the linked-list. Everything else is iteration or relates to the +ends of the linked-list. + +Situation that Endangers Consistency +------------------------------------ +Using a raw linked-list for OrderedDict exposes a key situation that can +cause problems. If a node is stored in a variable, there is a chance that +the node may have been deallocated before the variable gets used, thus +potentially leading to a segmentation fault. A key place where this shows +up is during iteration through the linked list (via _odict_FOREACH or +otherwise). + +A number of solutions are available to resolve this situation: + +* defer looking up the node until as late as possible and certainly after + any code that could possibly result in a deletion; +* if the node is needed both before and after a point where the node might + be removed, do a check before using the node at the "after" location to + see if the node is still valid; +* like the last one, but simply pull the node again to ensure it's right; +* keep the key in the variable instead of the node and then look up the + node using the key at the point where the node is needed (this is what + we do for the iterators). + +Another related problem, preserving consistent ordering during iteration, +is described below. That one is not exclusive to using linked-lists. + + +Challenges from Subclassing dict +================================ + +OrderedDict subclasses dict, which is an unusual relationship between two +builtin types (other than the base object type). Doing so results in +some complication and deserves further explanation. There are two things +to consider here. First, in what circumstances or with what adjustments +can OrderedDict be used as a drop-in replacement for dict (at the C level)? +Second, how can the OrderedDict implementation leverage the dict +implementation effectively without introducing unnecessary coupling or +inefficiencies? + +This second point is reflected here and in the implementation, so the +further focus is on the first point. It is worth noting that for +overridden methods, the dict implementation is deferred to as much as +possible. Furthermore, coupling is limited to as little as is reasonable. + +Concrete API Compatibility +-------------------------- + +Use of the concrete C-API for dict (PyDict_*) with OrderedDict is +problematic. (See http://bugs.python.org/issue10977.) The concrete API +has a number of hard-coded assumptions tied to the dict implementation. +This is, in part, due to performance reasons, which is understandable +given the part dict plays in Python. + +Any attempt to replace dict with OrderedDict for any role in the +interpreter (e.g. **kwds) faces a challenge. Such any effort must +recognize that the instances in affected locations currently interact with +the concrete API. + +Here are some ways to address this challenge: + +1. Change the relevant usage of the concrete API in CPython and add + PyDict_CheckExact() calls to each of the concrete API funcions. +2. Adjust the relevant concrete API functions to explicitly accommodate + OrderedDict. +3. As with #1, add the checks, but improve the abstract API with smart fast + paths for dict and OrderedDict, and refactor CPython to use the abstract + API. Improvements to the abstract API would be valuable regardless. + +Adding the checks to the concrete API would help make any interpreter +switch to OrderedDict less painful for extension modules. However, this +won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)` +is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call +the base class's methods, since there is no equivalent of super() in the +C API. Calling into Python for parent class API would work, but some +extension modules already rely on this feature of the concrete API. + +For reference, here is a breakdown of some of the dict concrete API: + +========================== ============= ======================= +concrete API uses abstract API +========================== ============= ======================= +PyDict_Check PyMapping_Check +(PyDict_CheckExact) - +(PyDict_New) - +(PyDictProxy_New) - +PyDict_Clear - +PyDict_Contains PySequence_Contains +PyDict_Copy - +PyDict_SetItem PyObject_SetItem +PyDict_SetItemString PyMapping_SetItemString +PyDict_DelItem PyMapping_DelItem +PyDict_DelItemString PyMapping_DelItemString +PyDict_GetItem - +PyDict_GetItemWithError PyObject_GetItem +_PyDict_GetItemIdWithError - +PyDict_GetItemString PyMapping_GetItemString +PyDict_Items PyMapping_Items +PyDict_Keys PyMapping_Keys +PyDict_Values PyMapping_Values +PyDict_Size PyMapping_Size + PyMapping_Length +PyDict_Next PyIter_Next +_PyDict_Next - +PyDict_Merge - +PyDict_Update - +PyDict_MergeFromSeq2 - +PyDict_ClearFreeList - +- PyMapping_HasKeyString +- PyMapping_HasKey +========================== ============= ======================= + + +The dict Interface Relative to OrderedDict +========================================== + +Since OrderedDict subclasses dict, understanding the various methods and +attributes of dict is important for implementing OrderedDict. + +Relevant Type Slots +------------------- + +================= ================ =================== ================ +slot attribute object dict +================= ================ =================== ================ +tp_dealloc - object_dealloc dict_dealloc +tp_repr __repr__ object_repr dict_repr +sq_contains __contains__ - dict_contains +mp_length __len__ - dict_length +mp_subscript __getitem__ - dict_subscript +mp_ass_subscript __setitem__ - dict_ass_sub + __delitem__ +tp_hash __hash__ _Py_HashPointer ..._HashNotImpl +tp_str __str__ object_str - +tp_getattro __getattribute__ ..._GenericGetAttr (repeated) + __getattr__ +tp_setattro __setattr__ ..._GenericSetAttr (disabled) +tp_doc __doc__ (literal) dictionary_doc +tp_traverse - - dict_traverse +tp_clear - - dict_tp_clear +tp_richcompare __eq__ object_richcompare dict_richcompare + __ne__ +tp_weaklistoffset (__weakref__) - - +tp_iter __iter__ - dict_iter +tp_dictoffset (__dict__) - - +tp_init __init__ object_init dict_init +tp_alloc - PyType_GenericAlloc (repeated) +tp_new __new__ object_new dict_new +tp_free - PyObject_Del PyObject_GC_Del +================= ================ =================== ================ + +Relevant Methods +---------------- + +================ =================== =============== +method object dict +================ =================== =============== +__reduce__ object_reduce - +__sizeof__ object_sizeof dict_sizeof +clear - dict_clear +copy - dict_copy +fromkeys - dict_fromkeys +get - dict_get +items - dictitems_new +keys - dictkeys_new +pop - dict_pop +popitem - dict_popitem +setdefault - dict_setdefault +update - dict_update +values - dictvalues_new +================ =================== =============== + + +Pure Python OrderedDict +======================= + +As already noted, compatibility with the pure Python OrderedDict +implementation is a key goal of this C implementation. To further that +goal, here's a summary of how OrderedDict-specific methods are implemented +in collections/__init__.py. Also provided is an indication of which +methods directly mutate or iterate the object, as well as any relationship +with the underlying linked-list. + +============= ============== == ================ === === ==== +method impl used ll uses inq mut iter +============= ============== == ================ === === ==== +__contains__ dict - - X +__delitem__ OrderedDict Y dict.__delitem__ X +__eq__ OrderedDict N OrderedDict ~ + dict.__eq__ + __iter__ +__getitem__ dict - - X +__iter__ OrderedDict Y - X +__init__ OrderedDict N update +__len__ dict - - X +__ne__ MutableMapping - __eq__ ~ +__reduce__ OrderedDict N OrderedDict ~ + __iter__ + __getitem__ +__repr__ OrderedDict N __class__ ~ + items +__reversed__ OrderedDict Y - X +__setitem__ OrderedDict Y __contains__ X + dict.__setitem__ +__sizeof__ OrderedDict Y __len__ ~ + __dict__ +clear OrderedDict Y dict.clear X +copy OrderedDict N __class__ + __init__ +fromkeys OrderedDict N __setitem__ +get dict - - ~ +items MutableMapping - ItemsView X +keys MutableMapping - KeysView X +move_to_end OrderedDict Y - X +pop OrderedDict N __contains__ X + __getitem__ + __delitem__ +popitem OrderedDict Y dict.pop X +setdefault OrderedDict N __contains__ ~ + __getitem__ + __setitem__ +update MutableMapping - __setitem__ ~ +values MutableMapping - ValuesView X +============= ============== == ================ === === ==== + +__reversed__ and move_to_end are both exclusive to OrderedDict. + + +C OrderedDict Implementation +============================ + +================= ================ +slot impl +================= ================ +tp_dealloc odict_dealloc +tp_repr odict_repr +mp_ass_subscript odict_ass_sub +tp_doc odict_doc +tp_traverse odict_traverse +tp_clear odict_tp_clear +tp_richcompare odict_richcompare +tp_weaklistoffset (offset) +tp_iter odict_iter +tp_dictoffset (offset) +tp_init odict_init +tp_alloc (repeated) +tp_new odict_new +================= ================ + +================= ================ +method impl +================= ================ +__reduce__ odict_reduce +__sizeof__ odict_sizeof +clear odict_clear +copy odict_copy +fromkeys odict_fromkeys +items odictitems_new +keys odictkeys_new +pop odict_pop +popitem odict_popitem +setdefault odict_setdefault +update odict_update +values odictvalues_new +================= ================ + +Inherited unchanged from object/dict: + +================ ========================== +method type field +================ ========================== +- tp_free +__contains__ tp_as_sequence.sq_contains +__getattr__ tp_getattro +__getattribute__ tp_getattro +__getitem__ tp_as_mapping.mp_subscript +__hash__ tp_hash +__len__ tp_as_mapping.mp_length +__setattr__ tp_setattro +__str__ tp_str +get - +================ ========================== + + +Other Challenges +================ + +Preserving Ordering During Iteration +------------------------------------ +During iteration through an OrderedDict, it is possible that items could +get added, removed, or reordered. For a linked-list implementation, as +with some other implementations, that situation may lead to undefined +behavior. The documentation for dict mentions this in the `iter()` section +of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects. +In this implementation we follow dict's lead (as does the pure Python +implementation) for __iter__(), keys(), values(), and items(). + +For internal iteration (using _odict_FOREACH or not), there is still the +risk that not all nodes that we expect to be seen in the loop actually get +seen. Thus, we are careful in each of those places to ensure that they +are. This comes, of course, at a small price at each location. The +solutions are much the same as those detailed in the `Situation that +Endangers Consistency` section above. + + +Potential Optimizations +======================= + +* Allocate the nodes as a block via od_fast_nodes instead of individually. + - Set node->key to NULL to indicate the node is not-in-use. + - Add _odict_EXISTS()? + - How to maintain consistency across resizes? Existing node pointers + would be invalidate after a resize, which is particularly problematic + for the iterators. +* Use a more stream-lined implementation of update() and, likely indirectly, + __init__(). + +*/ + +/* TODO + +sooner: +- reentrancy (make sure everything is at a thread-safe state when calling + into Python). I've already checked this multiple times, but want to + make one more pass. +- add unit tests for reentrancy? + +later: +- make the dict views support the full set API (the pure Python impl does) +- implement a fuller MutableMapping API in C? +- move the MutableMapping implementation to abstract.c? +- optimize mutablemapping_update +- use PyObject_MALLOC (small object allocator) for odict nodes? +- support subclasses better (e.g. in odict_richcompare) + +*/ + +#include "Python.h" +#include "structmember.h" +#include "dict-common.h" +#include + + +typedef struct _odictnode _ODictNode; + +/* PyODictObject */ +struct _odictobject { + /* od_dict is the underlying dict. */ + PyDictObject od_dict; + /* od_first is the first node in the odict, if any. */ + _ODictNode *od_first; + /* od_last is the last node in the odict, if any. */ + _ODictNode *od_last; + /* od_size is the number of entries in od_fast_nodes. */ + Py_ssize_t od_size; /* managed by _odict_resize() */ + /* od_fast_nodes is a hash table that mirrors the dict table. */ + _ODictNode **od_fast_nodes; /* managed by _odict_resize() */ + /* od_inst_dict is OrderedDict().__dict__. */ + PyObject *od_inst_dict; + /* od_weakreflist holds weakrefs to the odict. */ + PyObject *od_weakreflist; +}; + + +/* ---------------------------------------------- + * odict keys (a simple doubly-linked list) + */ + +struct _odictnode { + PyObject *key; + _ODictNode *next; + _ODictNode *prev; +}; + +#define _odictnode_KEY(node) \ + (node->key) +/* borrowed reference */ +#define _odictnode_VALUE(node, od) \ + PyODict_GetItem((PyObject *)od, _odictnode_KEY(node)) +/* If needed we could also have _odictnode_HASH. */ +#define _odictnode_PREV(node) (node->prev) +#define _odictnode_NEXT(node) (node->next) + +#define _odict_FIRST(od) (((PyODictObject *)od)->od_first) +#define _odict_LAST(od) (((PyODictObject *)od)->od_last) +#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL) +#define _odict_FOREACH(od, node) \ + for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node)) + + +static Py_ssize_t _odict_get_index(PyODictObject *, PyObject *); /* forward */ + +static void +_odict_free_fast_nodes(PyODictObject *od) { + if (od->od_fast_nodes) { + PyMem_FREE(od->od_fast_nodes); + } +} + +static int +_odict_resize(PyODictObject *od) { + Py_ssize_t size, prev_size, i; + _ODictNode **fast_nodes, *node; + + /* Initialize a new "fast nodes" table. */ + size = ((PyDictObject *)od)->ma_keys->dk_size; + fast_nodes = PyMem_NEW(_ODictNode *, size); + if (fast_nodes == NULL) { + PyErr_NoMemory(); + return -1; + } + for (i = 0; i < size; i++) + fast_nodes[i] = NULL; + + /* Copy the current nodes into the table. */ + prev_size = od->od_size; + od->od_size = size; + _odict_FOREACH(od, node) { + assert(node != NULL); + i = _odict_get_index(od, _odictnode_KEY(node)); + if (i < 0) { + od->od_size = prev_size; + PyMem_FREE(fast_nodes); + return -1; + } + fast_nodes[i] = node; + } + if (size != ((PyDictObject *)od)->ma_keys->dk_size) { + /* If _odict_get_index triggered a resize then we are already done. */ + PyMem_FREE(fast_nodes); + return 0; + } + + /* Replace the old fast nodes table. */ + _odict_free_fast_nodes(od); + od->od_fast_nodes = fast_nodes; + return 0; +} + +/* Return the index into the hash table, regardless of a valid node. */ +static Py_ssize_t +_odict_get_index(PyODictObject *od, PyObject *key) +{ + Py_hash_t hash; + PyObject **value_addr = NULL; + PyDictKeyEntry *ep; + PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys; + + assert(key != NULL); + do { + /* Ensure od_fast_nodes and dk_entries are in sync. */ + if (keys->dk_size != od->od_size) { + int resize_res = _odict_resize(od); + if (resize_res < 0) + return -1; + } + + /* now get the index */ + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + /* May have resized during the PyObject_Hash() call. */ + keys = ((PyDictObject *)od)->ma_keys; + } while (keys->dk_size != od->od_size); + + ep = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr); + if (ep == NULL) + return -1; + /* We use pointer arithmetic to get the entry's index into the table. */ + return ep - keys->dk_entries; +} + +static int +_odict_initialize(PyODictObject *od) +{ + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + return _odict_resize((PyODictObject *)od); +} + +/* Returns NULL if there was some error or the key was not found. */ +static _ODictNode * +_odict_find_node(PyODictObject *od, PyObject *key) +{ + Py_ssize_t index; + + if (_odict_EMPTY(od)) + return NULL; + index = _odict_get_index(od, key); + if (index < 0) + return NULL; + return od->od_fast_nodes[index]; +} + +static void +_odict_add_head(PyODictObject *od, _ODictNode *node) +{ + if (_odict_FIRST(od) == NULL) { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; + _odict_FIRST(od) = node; + _odict_LAST(od) = node; + } + else { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = _odict_FIRST(od); + _odict_FIRST(od) = node; + _odictnode_PREV(_odict_FIRST(od)) = node; + } +} + +static void +_odict_add_tail(PyODictObject *od, _ODictNode *node) +{ + if (_odict_LAST(od) == NULL) { + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; + _odict_FIRST(od) = node; + _odict_LAST(od) = node; + } + else { + _odictnode_PREV(node) = _odict_LAST(od); + _odictnode_NEXT(node) = NULL; + _odictnode_NEXT(_odict_LAST(od)) = node; + _odict_LAST(od) = node; + } +} + +/* adds the node to the end of the list */ +static int +_odict_add_new_node(PyODictObject *od, PyObject *key) +{ + Py_ssize_t i; + _ODictNode *node; + + Py_INCREF(key); + i = _odict_get_index(od, key); + if (i < 0) { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return -1; + } + else if (od->od_fast_nodes[i] != NULL) { + /* We already have a node for the key so there's no need to add one. */ + Py_DECREF(key); + return 0; + } + + /* must not be added yet */ + node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode)); + if (node == NULL) { + Py_DECREF(key); + PyErr_NoMemory(); + return -1; + } + + _odictnode_KEY(node) = key; + _odict_add_tail(od, node); + od->od_fast_nodes[i] = node; + return 0; +} + +/* Putting the decref after the free causes problems. */ +#define _odictnode_DEALLOC(node) \ + do { \ + Py_DECREF(_odictnode_KEY(node)); \ + PyMem_FREE((void *)node); \ + } while (0) + +/* Repeated calls on the same node are no-ops. */ +static void +_odict_remove_node(PyODictObject *od, _ODictNode *node) +{ + if (_odict_FIRST(od) == node) + _odict_FIRST(od) = _odictnode_NEXT(node); + else if (_odictnode_PREV(node) != NULL) + _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node); + + if (_odict_LAST(od) == node) + _odict_LAST(od) = _odictnode_PREV(node); + else if (_odictnode_NEXT(node) != NULL) + _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node); + + _odictnode_PREV(node) = NULL; + _odictnode_NEXT(node) = NULL; +} + +static _ODictNode * +_odict_pop_node(PyODictObject *od, _ODictNode *node, PyObject *key) +{ + if (node == NULL) { + node = _odict_find_node(od, key); + if (node == NULL) + return NULL; + } + _odict_remove_node(od, node); + return node; +} + +/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll + get all sorts of problems here. In PyODict_DelItem we make sure to + call _odict_clear_node first. + + This matters in the case of colliding keys. Suppose we add 3 keys: + [A, B, C], where the hash of C collides with A and the next possible + index in the hash table is occupied by B. If we remove B then for C + the dict's looknode func will give us the old index of B instead of + the index we got before deleting B. However, the node for C in + od_fast_nodes is still at the old dict index of C. Thus to be sure + things don't get out of sync, we clear the node in od_fast_nodes + *before* calling PyDict_DelItem. + + The same must be done for any other OrderedDict operations where + we modify od_fast_nodes. +*/ +static int +_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key) +{ + Py_ssize_t i; + + assert(key != NULL); + if (_odict_EMPTY(od)) { + /* Let later code decide if this is a KeyError. */ + return 0; + } + + i = _odict_get_index(od, key); + if (i < 0) + return PyErr_Occurred() ? -1 : 0; + + if (node == NULL) + node = od->od_fast_nodes[i]; + assert(node == od->od_fast_nodes[i]); + if (node == NULL) { + /* Let later code decide if this is a KeyError. */ + return 0; + } + + // Now clear the node. + od->od_fast_nodes[i] = NULL; + _odict_remove_node(od, node); + _odictnode_DEALLOC(node); + return 0; +} + +static void +_odict_clear_nodes(PyODictObject *od) +{ + _ODictNode *node, *next; + + if (!_odict_EMPTY(od)) { + node = _odict_FIRST(od); + while (node != NULL) { + next = _odictnode_NEXT(node); + _odictnode_DEALLOC(node); + node = next; + } + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + } + + _odict_free_fast_nodes(od); + od->od_fast_nodes = NULL; +} + +/* There isn't any memory management of nodes past this point. */ +#undef _odictnode_DEALLOC + +static int +_odict_keys_equal(PyODictObject *a, PyODictObject *b) +{ + _ODictNode *node_a, *node_b; + + node_a = _odict_FIRST(a); + node_b = _odict_FIRST(b); + while (1) { + if (node_a == NULL && node_b == NULL) + /* success: hit the end of each at the same time */ + return 1; + else if (node_a == NULL || node_b == NULL) + /* unequal length */ + return 0; + else { + int res = PyObject_RichCompareBool( + (PyObject *)_odictnode_KEY(node_a), + (PyObject *)_odictnode_KEY(node_b), + Py_EQ); + if (res < 0) + return res; + else if (res == 0) + return 0; + + /* otherwise it must match, so move on to the next one */ + node_a = _odictnode_NEXT(node_a); + node_b = _odictnode_NEXT(node_b); + } + } +} + + +/* ---------------------------------------------- + * OrderedDict mapping methods + */ + +/* mp_ass_subscript: __setitem__() and __delitem__() */ + +static int +odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w) +{ + if (w == NULL) + return PyODict_DelItem((PyObject *)od, v); + else + return PyODict_SetItem((PyObject *)od, v, w); +} + +/* tp_as_mapping */ + +static PyMappingMethods odict_as_mapping = { + 0, /*mp_length*/ + 0, /*mp_subscript*/ + (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/ +}; + + +/* ---------------------------------------------- + * OrderedDict methods + */ + +/* __delitem__() */ + +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\ + while comparison to a regular mapping is order-insensitive.\n\ + "); + +/* forward */ +static PyObject * odict_richcompare(PyObject *v, PyObject *w, int op); + +static PyObject * +odict_eq(PyObject *a, PyObject *b) +{ + return odict_richcompare(a, b, Py_EQ); +} + +/* __init__() */ + +PyDoc_STRVAR(odict_init__doc__, +"Initialize an ordered dictionary. The signature is the same as\n\ + regular dictionaries, but keyword arguments are not recommended because\n\ + their insertion order is arbitrary.\n\ +\n\ + "); + +/* forward */ +static int odict_init(PyObject *self, PyObject *args, PyObject *kwds); + +/* __iter__() */ + +PyDoc_STRVAR(odict_iter__doc__, "od.__iter__() <==> iter(od)"); + +static PyObject * odict_iter(PyODictObject *self); /* forward */ + +/* __ne__() */ + +/* Mapping.__ne__() does not have a docstring. */ +PyDoc_STRVAR(odict_ne__doc__, ""); + +static PyObject * +odict_ne(PyObject *a, PyObject *b) +{ + return odict_richcompare(a, b, Py_NE); +} + +/* __repr__() */ + +PyDoc_STRVAR(odict_repr__doc__, "od.__repr__() <==> repr(od)"); + +static PyObject * odict_repr(PyODictObject *self); /* forward */ + +/* __setitem__() */ + +PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y"); + +/* fromkeys() */ + +PyDoc_STRVAR(odict_fromkeys__doc__, +"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\ + If not specified, the value defaults to None.\n\ +\n\ + "); + +static PyObject * +odict_fromkeys(PyObject *cls, PyObject *args) +{ + PyObject *seq; + PyObject *value = Py_None; + if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value)) /* borrowed */ + return NULL; + return _PyDict_FromKeys(cls, seq, value); +} + +/* __sizeof__() */ + +/* OrderedDict.__sizeof__() does not have a docstring. */ +PyDoc_STRVAR(odict_sizeof__doc__, ""); + +static PyObject * +odict_sizeof(PyODictObject *od) +{ + PyObject *pylong; + Py_ssize_t res; + + pylong = _PyDict_SizeOf((PyDictObject *)od); + if (pylong == NULL) + return NULL; + res = PyLong_AsSsize_t(pylong); + Py_DECREF(pylong); + if (res == -1 && PyErr_Occurred()) + return NULL; + + res += sizeof(PyODictObject) - sizeof(PyDictObject); + + /* instance dict */ + pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict); + if (pylong == NULL) + return NULL; + res += PyLong_AsSsize_t(pylong); + Py_DECREF(pylong); + if (res == -1 && PyErr_Occurred()) + return NULL; + + res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ + if (!_odict_EMPTY(od)) { + res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */ + } + return PyLong_FromSsize_t(res); +} + +/* __reduce__() */ + +PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling"); + +static PyObject * +odict_reduce(register PyODictObject *od) +{ + _Py_IDENTIFIER(__dict__); + _Py_IDENTIFIER(__class__); + PyObject *vars = NULL, *ns = NULL, *result = NULL, *cls = NULL; + PyObject *items_iter = NULL, *items = NULL, *args = NULL; + + /* capture any instance state */ + vars = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__); + if (vars != NULL) { + PyObject *empty, *od_vars, *iterator, *key; + + /* od.__dict__ isn't necessarily a dict... */ + ns = PyObject_CallMethod((PyObject *)vars, "copy", NULL); + if (ns == NULL) + goto Done; + empty = PyODict_New(); + if (empty == NULL) + goto Done; + od_vars = _PyObject_GetAttrId((PyObject *)empty, &PyId___dict__); + Py_DECREF(empty); + if (od_vars == NULL) + goto Done; + iterator = PyObject_GetIter(od_vars); + Py_DECREF(od_vars); + if (iterator == NULL) + goto Done; + + while ( (key = PyIter_Next(iterator)) ) { + if (PyMapping_HasKey(ns, key) && PyMapping_DelItem(ns, key) != 0) { + Py_DECREF(iterator); + Py_DECREF(key); + goto Done; + } + Py_DECREF(key); + } + Py_DECREF(iterator); + if (PyErr_Occurred()) + goto Done; + + if (!PyObject_Length(ns)) { + /* nothing novel to pickle in od.__dict__ */ + Py_DECREF(ns); + ns = NULL; + } + } + + /* build the result */ + cls = _PyObject_GetAttrId((PyObject *)od, &PyId___class__); + if (cls == NULL) + goto Done; + + args = PyTuple_New(0); + if (args == NULL) + goto Done; + + items = PyObject_CallMethod((PyObject *)od, "items", NULL); + if (items == NULL) + goto Done; + + items_iter = PyObject_GetIter(items); + if (items_iter == NULL) + goto Done; + + result = PyTuple_Pack(5, cls, args, ns ? ns : Py_None, Py_None, items_iter); + +Done: + Py_XDECREF(vars); + Py_XDECREF(ns); + Py_XDECREF(cls); + Py_XDECREF(args); + Py_XDECREF(items); + Py_XDECREF(items_iter); + + return result; +} + +/* setdefault() */ + +PyDoc_STRVAR(odict_setdefault__doc__, + "od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od"); + +/* Skips __missing__() calls. */ +static PyObject * +odict_setdefault(register PyODictObject *od, PyObject *args) +{ + _ODictNode *node; + PyObject *key, *result = NULL; + PyObject *failobj = Py_None; + + /* both borrowed */ + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) + return NULL; + Py_INCREF(key); + Py_INCREF(failobj); + + if (PyODict_CheckExact(od)) { + node = _odict_find_node(od, key); + if (node == NULL) { + if (PyErr_Occurred()) { + goto done; + } + else if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) { + result = failobj; + Py_INCREF(failobj); + } + } + else { + result = PyODict_GetItem(od, key); /* borrowed reference */ + Py_XINCREF(result); + } + } + else { + int exists = PySequence_Contains((PyObject *)od, key); + if (exists < 0) { + goto done; + } + else if (exists) { + result = PyObject_GetItem((PyObject *)od, key); + } + else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) { + result = failobj; + Py_INCREF(failobj); + } + } + +done: + Py_DECREF(failobj); + Py_DECREF(key); + return result; +} + +/* pop() */ + +PyDoc_STRVAR(odict_pop__doc__, +"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\ + value. If key is not found, d is returned if given, otherwise KeyError\n\ + is raised.\n\ +\n\ + "); + +/* forward */ +static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *); + +/* Skips __missing__() calls. */ +static PyObject * +odict_pop(PyObject *od, PyObject *args) +{ + PyObject *key, *failobj = NULL; + + if (!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj)) { /* borrowed */ + return NULL; + } + + return _odict_popkey(od, key, failobj); +} + +static PyObject * +_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj) +{ + _ODictNode *node; + PyObject *value = NULL; + + Py_INCREF(key); + Py_XINCREF(failobj); + + /* Pop the node first to avoid a possible dict resize (due to + eval loop reentrancy) and complications due to hash collision + resolution. */ + node = _odict_find_node((PyODictObject *)od, key); + if (node == NULL) { + if (PyErr_Occurred()) + goto done; + } + else { + int res = _odict_clear_node((PyODictObject *)od, node, key); + if (res < 0) { + goto done; + } + } + + /* Now delete the value from the dict. */ + if (PyODict_CheckExact(od)) { + if (node != NULL) { + /* We could do PyDict_GetItem() and PyDict_DelItem() directly... */ + value = _PyDict_Pop((PyDictObject *)od, key, failobj); + } + } + else { + int exists = PySequence_Contains(od, key); + if (exists < 0) + goto done; + if (exists) { + value = PyObject_GetItem(od, key); + if (value != NULL) { + if (PyObject_DelItem(od, key) == -1) { + Py_DECREF(value); + value = NULL; + } + } + } + } + + /* Apply the fallback value, if necessary. */ + if (value == NULL && !PyErr_Occurred()) { + if (failobj) { + value = failobj; + Py_INCREF(failobj); + } + else { + PyErr_SetObject(PyExc_KeyError, key); + } + } + +done: + Py_DECREF(key); + Py_XDECREF(failobj); + return value; +} + +/* popitem() */ + +PyDoc_STRVAR(odict_popitem__doc__, +"od.popitem() -> (k, v), return and remove a (key, value) pair.\n\ + Pairs are returned in LIFO order if last is true or FIFO order if false.\n\ +\n\ + "); + +static PyObject * +odict_popitem(PyObject *od, PyObject *args) +{ + PyObject *key, *value, *item = NULL, *last = NULL; + _ODictNode *node; + + if (_odict_EMPTY((PyODictObject *)od)) { + PyErr_SetString(PyExc_KeyError, "dictionary is empty"); + return NULL; + } + + /* pull the item */ + + if (!PyArg_UnpackTuple(args, "popitem", 0, 1, &last)) /* borrowed */ + return NULL; + Py_XINCREF(last); + + if (last == NULL || last == Py_True) + node = _odict_LAST((PyODictObject *)od); + else + node = _odict_FIRST((PyODictObject *)od); + Py_XDECREF(last); + + key = _odictnode_KEY(node); + value = _odict_popkey(od, key, NULL); + if (value == NULL) + return NULL; + item = PyTuple_Pack(2, key, value); + Py_DECREF(value); + return item; +} + +/* keys() */ + +/* MutableMapping.keys() does not have a docstring. */ +PyDoc_STRVAR(odict_keys__doc__, ""); + +static PyObject * odictkeys_new(PyObject *od); /* forward */ + +/* values() */ + +/* MutableMapping.values() does not have a docstring. */ +PyDoc_STRVAR(odict_values__doc__, ""); + +static PyObject * odictvalues_new(PyObject *od); /* forward */ + +/* items() */ + +/* MutableMapping.items() does not have a docstring. */ +PyDoc_STRVAR(odict_items__doc__, ""); + +static PyObject * odictitems_new(PyObject *od); /* forward */ + +/* update() */ + +/* MutableMapping.update() does not have a docstring. */ +PyDoc_STRVAR(odict_update__doc__, ""); + +/* forward */ +static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *); + +#define odict_update mutablemapping_update + +/* clear() */ + +PyDoc_STRVAR(odict_clear__doc__, + "od.clear() -> None. Remove all items from od."); + +static PyObject * +odict_clear(register PyODictObject *od) +{ + PyDict_Clear((PyObject *)od); + _odict_clear_nodes(od); + _odict_FIRST(od) = NULL; + _odict_LAST(od) = NULL; + if (_odict_resize(od) < 0) + return NULL; + Py_RETURN_NONE; +} + +/* copy() */ + +PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od"); + +static PyObject * +odict_copy(register PyODictObject *od) +{ + _ODictNode *node; + PyObject *od_copy; + + if (PyODict_CheckExact(od)) + od_copy = PyODict_New(); + else + od_copy = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(od), NULL); + if (od_copy == NULL) + return NULL; + + if (PyODict_CheckExact(od)) { + _odict_FOREACH(od, node) { + int res = PyODict_SetItem((PyObject *)od_copy, + _odictnode_KEY(node), + _odictnode_VALUE(node, od)); + if (res != 0) + goto fail; + } + } + else { + _odict_FOREACH(od, node) { + int res; + PyObject *value = PyObject_GetItem((PyObject *)od, + _odictnode_KEY(node)); + if (value == NULL) + goto fail; + res = PyObject_SetItem((PyObject *)od_copy, + _odictnode_KEY(node), value); + Py_DECREF(value); + if (res != 0) + goto fail; + } + } + return od_copy; + +fail: + Py_DECREF(od_copy); + return NULL; +} + +/* __reversed__() */ + +PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); + +#define _odict_ITER_REVERSED 1 +#define _odict_ITER_KEYS 2 +#define _odict_ITER_VALUES 4 + +/* forward */ +static PyObject * odictiter_new(PyODictObject *, int); + +static PyObject * +odict_reversed(PyODictObject *od) +{ + if (_odict_EMPTY(od)) { + Py_RETURN_NONE; + } + return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED); +} + +/* move_to_end() */ + +PyDoc_STRVAR(odict_move_to_end__doc__, +"Move an existing element to the end (or beginning if last==False).\n\ +\n\ + Raises KeyError if the element does not exist.\n\ + When last=True, acts like a fast version of self[key]=self.pop(key).\n\ +\n\ + "); + +static PyObject * +odict_move_to_end(PyODictObject *od, PyObject *args) +{ + PyObject *key, *last = NULL; + Py_ssize_t pos = -1; + + /* both borrowed */ + if (!PyArg_UnpackTuple(args, "move_to_end", 1, 2, &key, &last)) + return NULL; + Py_INCREF(key); + if (_odict_EMPTY(od)) { + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + if (last != NULL) { + Py_INCREF(last); + pos = PyObject_IsTrue(last) ? -1 : 0; + Py_DECREF(last); + } + if (pos == 0) { + /* Only move if not already the first one. */ + PyObject *first_key = _odictnode_KEY(_odict_FIRST(od)); + if (PyObject_RichCompareBool(key, first_key, Py_NE)) { + _ODictNode *node = _odict_pop_node(od, NULL, key); + if (node != NULL) { + _odict_add_head(od, node); + } + else { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + } + } + else if (pos == -1) { + /* Only move if not already the last one. */ + PyObject *last_key = _odictnode_KEY(_odict_LAST(od)); + if (PyObject_RichCompareBool(key, last_key, Py_NE)) { + _ODictNode *node = _odict_pop_node(od, NULL, key); + if (node != NULL) { + _odict_add_tail(od, node); + } + else { + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_KeyError, key); + Py_DECREF(key); + return NULL; + } + } + } + Py_DECREF(key); + Py_RETURN_NONE; +} + + +/* tp_methods */ + +static PyMethodDef odict_methods[] = { + + /* explicitly defined so we can align docstrings with + * collections.OrderedDict */ + {"__delitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS, + odict_delitem__doc__}, + {"__eq__", (PyCFunction)odict_eq, METH_NOARGS, + odict_eq__doc__}, + {"__init__", (PyCFunction)odict_init, METH_NOARGS, + odict_init__doc__}, + {"__iter__", (PyCFunction)odict_iter, METH_NOARGS, + odict_iter__doc__}, + {"__ne__", (PyCFunction)odict_ne, METH_NOARGS, + odict_ne__doc__}, + {"__repr__", (PyCFunction)odict_repr, METH_NOARGS, + odict_repr__doc__}, + {"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS, + odict_setitem__doc__}, + {"fromkeys", (PyCFunction)odict_fromkeys, METH_VARARGS | METH_CLASS, + odict_fromkeys__doc__}, + + /* overridden dict methods */ + {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS, + odict_sizeof__doc__}, + {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS, + odict_reduce__doc__}, + {"setdefault", (PyCFunction)odict_setdefault, METH_VARARGS, + odict_setdefault__doc__}, + {"pop", (PyCFunction)odict_pop, METH_VARARGS, + odict_pop__doc__}, + {"popitem", (PyCFunction)odict_popitem, METH_VARARGS, + odict_popitem__doc__}, + {"keys", (PyCFunction)odictkeys_new, METH_NOARGS, + odict_keys__doc__}, + {"values", (PyCFunction)odictvalues_new, METH_NOARGS, + odict_values__doc__}, + {"items", (PyCFunction)odictitems_new, METH_NOARGS, + odict_items__doc__}, + {"update", (PyCFunction)odict_update, METH_VARARGS | METH_KEYWORDS, + odict_update__doc__}, + {"clear", (PyCFunction)odict_clear, METH_NOARGS, + odict_clear__doc__}, + {"copy", (PyCFunction)odict_copy, METH_NOARGS, + odict_copy__doc__}, + + /* new methods */ + {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS, + odict_reversed__doc__}, + {"move_to_end", (PyCFunction)odict_move_to_end, METH_VARARGS, + odict_move_to_end__doc__}, + + {NULL, NULL} /* sentinel */ +}; + + +/* ---------------------------------------------- + * OrderedDict members + */ + +/* tp_members */ + +static PyMemberDef odict_members[] = { + {"__dict__", T_OBJECT, offsetof(PyODictObject, od_inst_dict), READONLY}, + {0} +}; + + +/* ---------------------------------------------- + * OrderedDict type slot methods + */ + +/* tp_dealloc */ + +static void +odict_dealloc(PyODictObject *self) +{ + PyObject_GC_UnTrack(self); + Py_TRASHCAN_SAFE_BEGIN(self); + Py_XDECREF(self->od_inst_dict); + if (self->od_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)self); + + _odict_clear_nodes(self); + Py_TRASHCAN_SAFE_END(self); + + /* must be last */ + PyDict_Type.tp_dealloc((PyObject *)self); +}; + +/* tp_repr */ + +static PyObject * +odict_repr(PyODictObject *self) +{ + int i; + const char *formatstr; + _Py_IDENTIFIER(__class__); + _Py_IDENTIFIER(__name__); + Py_ssize_t count = -1; + PyObject *pieces = NULL, *result = NULL, *cls = NULL; + PyObject *classname = NULL, *format = NULL, *args = NULL; + _ODictNode *node; + + i = Py_ReprEnter((PyObject *)self); + if (i != 0) { + return i > 0 ? PyUnicode_FromString("...") : NULL; + } + + if (PyODict_SIZE(self) == 0) { + /* "OrderedDict()" */ + goto Finish; + } + + if (PyODict_CheckExact(self)) { + pieces = PyList_New(PyODict_SIZE(self)); + if (pieces == NULL) + goto Done; + + _odict_FOREACH(self, node) { + PyObject *pair = PyTuple_Pack(2, _odictnode_KEY(node), + _odictnode_VALUE(node, self)); + if (pair == NULL) + goto Done; + + PyList_SET_ITEM(pieces, ++count, pair); /* steals reference */ + } + } + else { + PyObject *items = PyObject_CallMethod((PyObject *)self, "items", NULL); + if (items == NULL) + goto Done; + pieces = PySequence_List(items); + Py_DECREF(items); + if(pieces == NULL) + goto Done; + } + +Finish: + cls = _PyObject_GetAttrId((PyObject *)self, &PyId___class__); + if (cls == NULL) + goto Done; + classname = _PyObject_GetAttrId(cls, &PyId___name__); + if (classname == NULL) + goto Done; + + if (pieces == NULL) { + formatstr = "%s()"; + args = PyTuple_Pack(1, classname); + } + else { + formatstr = "%s(%r)"; + args = PyTuple_Pack(2, classname, pieces); + } + if (args == NULL) + goto Done; + + format = PyUnicode_InternFromString(formatstr); + if (format == NULL) + goto Done; + + result = PyUnicode_Format(format, args); +Done: + Py_XDECREF(pieces); + Py_XDECREF(cls); + Py_XDECREF(classname); + Py_XDECREF(format); + Py_XDECREF(args); + Py_ReprLeave((PyObject *)self); + return result; +}; + +/* tp_doc */ + +PyDoc_STRVAR(odict_doc, + "Dictionary that remembers insertion order"); + +/* tp_traverse */ + +static int +odict_traverse(PyODictObject *od, visitproc visit, void *arg) +{ + Py_VISIT(od->od_inst_dict); + Py_VISIT(od->od_weakreflist); + return PyDict_Type.tp_traverse((PyObject *)od, visit, arg); +} + +/* tp_clear */ + +static int +odict_tp_clear(PyODictObject *od) +{ + PyObject *res; + Py_CLEAR(od->od_inst_dict); + Py_CLEAR(od->od_weakreflist); + res = odict_clear(od); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +/* tp_richcompare */ + +static PyObject * +odict_richcompare(PyObject *v, PyObject *w, int op) +{ + if (!PyODict_Check(v) || !PyDict_Check(w)) { + Py_RETURN_NOTIMPLEMENTED; + } + + if (op == Py_EQ || op == Py_NE) { + PyObject *res, *cmp; + int eq; + + cmp = PyDict_Type.tp_richcompare(v, w, op); + if (cmp == NULL) + return NULL; + if (!PyODict_Check(w)) + return cmp; + if (op == Py_EQ && cmp == Py_False) + return cmp; + if (op == Py_NE && cmp == Py_True) + return cmp; + Py_DECREF(cmp); + + /* Try comparing odict keys. */ + eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w); + if (eq < 0) + return NULL; + + res = (eq == (op == Py_EQ)) ? Py_True : Py_False; + Py_INCREF(res); + return res; + } else { + Py_RETURN_NOTIMPLEMENTED; + } +}; + +/* tp_iter */ + +static PyObject * +odict_iter(PyODictObject *od) +{ + return odictiter_new(od, _odict_ITER_KEYS); +}; + +/* tp_init */ + +static int +odict_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *res; + Py_ssize_t len = PyObject_Length(args); + + if (len == -1) + return -1; + if (len > 1) { + char *msg = "expected at most 1 arguments, got %d"; + PyErr_Format(PyExc_TypeError, msg, len); + return -1; + } + + /* __init__() triggering update() is just the way things are! */ + res = odict_update(self, args, kwds); + if (res == NULL) { + return -1; + } else { + Py_DECREF(res); + return 0; + } +}; + +/* tp_new */ + +static PyObject * +odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *od = PyDict_Type.tp_new(type, args, kwds); + if (od != NULL) { + ((PyODictObject *)od)->od_inst_dict = PyDict_New(); + ((PyODictObject *)od)->od_weakreflist = NULL; + if (_odict_initialize((PyODictObject *)od) < 0) + return NULL; + } + return od; +} + +/* PyODict_Type */ + +PyTypeObject PyODict_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "collections.OrderedDict", /* tp_name */ + sizeof(PyODictObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)odict_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)odict_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &odict_as_mapping, /* tp_as_mapping */ + 0, /* 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_HAVE_GC,/* tp_flags */ + odict_doc, /* tp_doc */ + (traverseproc)odict_traverse, /* tp_traverse */ + (inquiry)odict_tp_clear, /* tp_clear */ + (richcmpfunc)odict_richcompare, /* tp_richcompare */ + offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */ + (getiterfunc)odict_iter, /* tp_iter */ + 0, /* tp_iternext */ + odict_methods, /* tp_methods */ + odict_members, /* tp_members */ + 0, /* tp_getset */ + &PyDict_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */ + (initproc)odict_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + (newfunc)odict_new, /* tp_new */ + 0, /* tp_free */ +}; + + +/* ---------------------------------------------- + * the public OrderedDict API + */ + +PyObject * +PyODict_New(void) { + return odict_new(&PyODict_Type, NULL, NULL); +}; + +int +PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value) { + int res = PyDict_SetItem(od, key, value); + if (res == 0) { + res = _odict_add_new_node((PyODictObject *)od, key); + } + return res; +}; + +int +PyODict_DelItem(PyObject *od, PyObject *key) { + int res = _odict_clear_node((PyODictObject *)od, NULL, key); + if (res < 0) + return -1; + return PyDict_DelItem(od, key); +}; + + +/* ------------------------------------------- + * The OrderedDict views (keys/values/items) + */ + +typedef struct { + PyObject_HEAD + int kind; + PyODictObject *di_odict; + PyObject *di_current; + PyObject *di_result; /* reusable result tuple for iteritems */ +} odictiterobject; + +static void +odictiter_dealloc(odictiterobject *di) +{ + _PyObject_GC_UNTRACK(di); + Py_DECREF(di->di_odict); + Py_XDECREF(di->di_current); + if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + Py_DECREF(di->di_result); + } + PyObject_GC_Del(di); +} + +static int +odictiter_traverse(odictiterobject *di, visitproc visit, void *arg) +{ + Py_VISIT(di->di_odict); + Py_VISIT(di->di_current); /* A key could be any type, not just str. */ + Py_VISIT(di->di_result); + return 0; +} + +static PyObject * +odictiter_nextkey(odictiterobject *di) +{ + PyObject *key; + _ODictNode *node; + int reversed = di->kind & _odict_ITER_REVERSED; + + /* Get the key. */ + if (di->di_current == NULL) + return NULL; + node = _odict_find_node(di->di_odict, di->di_current); + if (node == NULL) { + /* Must have been deleted. */ + Py_DECREF(di->di_current); + di->di_current = NULL; + return NULL; + } + key = di->di_current; + + /* Advance to the next key. */ + node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node); + if (node == NULL) { + /* Reached the end. */ + di->di_current = NULL; + } + else { + di->di_current = _odictnode_KEY(node); + Py_INCREF(di->di_current); + } + + return key; +} + +static PyObject * +odictiter_iternext(odictiterobject *di) +{ + PyObject *value; + PyObject *key = odictiter_nextkey(di); /* new reference */ + + if (key == NULL) + return NULL; + + /* Handle the keys case. */ + if (! (di->kind & _odict_ITER_VALUES)) { + return key; + } + + /* Handle the items case. */ + if (di->kind & _odict_ITER_KEYS) { + PyObject *result = di->di_result; + + value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ + + if (result->ob_refcnt == 1) { + /* not in use so we can reuse it + * (the common case during iteration) */ + Py_INCREF(result); + Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */ + Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */ + } + else { + result = PyTuple_New(2); + if (result == NULL) + return NULL; + } + + Py_INCREF(value); + PyTuple_SET_ITEM(result, 0, key); /* steals reference */ + PyTuple_SET_ITEM(result, 1, value); /* steals reference */ + + return result; + } + /* Handle the values case. */ + else { + value = PyODict_GetItem((PyObject *)di->di_odict, key); + Py_XINCREF(value); + Py_DECREF(key); + return value; + } +} + +/* No need for tp_clear because odictiterobject is not mutable. */ + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling"); + +static PyObject * +odictiter_reduce(odictiterobject *di) +{ + PyObject *list; + + list = PyList_New(0); + if (!list) + return NULL; + + /* iterate the temporary into a list */ + for(;;) { + PyObject *element = odictiter_iternext(di); + if (element) { + if (PyList_Append(list, element)) { + Py_DECREF(element); + Py_DECREF(list); + return NULL; + } + Py_DECREF(element); + } + else { + /* done iterating? */ + break; + } + } + if (PyErr_Occurred()) { + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); +} + +static PyMethodDef odictiter_methods[] = { + {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictIter_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_iterator", /* tp_name */ + sizeof(odictiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)odictiter_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_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)odictiter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)odictiter_iternext, /* tp_iternext */ + odictiter_methods, /* tp_methods */ + 0, +}; + +static PyObject * +odictiter_new(PyODictObject *od, int kind) +{ + odictiterobject *di; + _ODictNode *node; + int reversed = kind & _odict_ITER_REVERSED; + + di = PyObject_GC_New(odictiterobject, &PyODictIter_Type); + if (di == NULL) + return NULL; + + if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + di->di_result = PyTuple_Pack(2, Py_None, Py_None); + if (di->di_result == NULL) { + Py_DECREF(di); + return NULL; + } + } + else + di->di_result = NULL; + + di->kind = kind; + node = reversed ? _odict_LAST(od) : _odict_FIRST(od); + di->di_current = node ? _odictnode_KEY(node) : NULL; + Py_XINCREF(di->di_current); + di->di_odict = od; + Py_INCREF(od); + + _PyObject_GC_TRACK(di); + return (PyObject *)di; +} + +/* keys() */ + +static PyObject * +odictkeys_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS); +} + +static PyObject * +odictkeys_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_REVERSED); +} + +static PyMethodDef odictkeys_methods[] = { + {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictKeys_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_keys", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictkeys_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictkeys_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictKeys_Type, /* tp_base */ +}; + +static PyObject * +odictkeys_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictKeys_Type); +} + +/* items() */ + +static PyObject * +odictitems_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_VALUES); +} + +static PyObject * +odictitems_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED); +} + +static PyMethodDef odictitems_methods[] = { + {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictItems_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_items", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictitems_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictitems_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictItems_Type, /* tp_base */ +}; + +static PyObject * +odictitems_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictItems_Type); +} + +/* values() */ + +static PyObject * +odictvalues_iter(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_VALUES); +} + +static PyObject * +odictvalues_reversed(_PyDictViewObject *dv) +{ + if (dv->dv_dict == NULL) { + Py_RETURN_NONE; + } + return odictiter_new((PyODictObject *)dv->dv_dict, + _odict_ITER_VALUES|_odict_ITER_REVERSED); +} + +static PyMethodDef odictvalues_methods[] = { + {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyODictValues_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "odict_values", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)odictvalues_iter, /* tp_iter */ + 0, /* tp_iternext */ + odictvalues_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyDictValues_Type, /* tp_base */ +}; + +static PyObject * +odictvalues_new(PyObject *od) +{ + return _PyDictView_New(od, &PyODictValues_Type); +} + + +/* ---------------------------------------------- + MutableMappping implementations + +Mapping: + +============ =========== +method uses +============ =========== +__contains__ __getitem__ +__eq__ items +__getitem__ + +__iter__ + +__len__ + +__ne__ __eq__ +get __getitem__ +items ItemsView +keys KeysView +values ValuesView +============ =========== + +ItemsView uses __len__, __iter__, and __getitem__. +KeysView uses __len__, __iter__, and __contains__. +ValuesView uses __len__, __iter__, and __getitem__. + +MutableMapping: + +============ =========== +method uses +============ =========== +__delitem__ + +__setitem__ + +clear popitem +pop __getitem__ + __delitem__ +popitem __iter__ + _getitem__ + __delitem__ +setdefault __getitem__ + __setitem__ +update __setitem__ +============ =========== +*/ + +static int +mutablemapping_add_pairs(PyObject *self, PyObject *pairs) +{ + PyObject *pair, *iterator, *unexpected; + int res = 0; + + iterator = PyObject_GetIter(pairs); + if (iterator == NULL) + return -1; + PyErr_Clear(); + + while ((pair = PyIter_Next(iterator)) != NULL) { + /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */ + PyObject * key, *value = NULL; + PyObject *pair_iterator = PyObject_GetIter(pair); + + key = PyIter_Next(pair_iterator); + if (key == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "need more than 0 values to unpack"); + goto Done; + } + + value = PyIter_Next(pair_iterator); + if (value == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "need more than 1 value to unpack"); + goto Done; + } + + unexpected = PyIter_Next(pair_iterator); + if (unexpected != NULL) { + Py_DECREF(unexpected); + PyErr_SetString(PyExc_ValueError, + "too many values to unpack (expected 2)"); + goto Done; + } + else if (PyErr_Occurred()) + goto Done; + + res = PyObject_SetItem(self, key, value); + +Done: + Py_DECREF(pair); + Py_DECREF(pair_iterator); + Py_XDECREF(key); + Py_XDECREF(value); + if (PyErr_Occurred()) + break; + } + Py_DECREF(iterator); + + if (res < 0 || PyErr_Occurred() != NULL) + return -1; + else + return 0; +} + +static PyObject * +mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int res = 0; + Py_ssize_t len = (args != NULL) ? PyObject_Size(args) : 0; + + /* first handle args, if any */ + if (len < 0) + return NULL; + else if (len > 1) { + char *msg = "update() takes at most 1 positional argument (%d given)"; + PyErr_Format(PyExc_TypeError, msg, len); + return NULL; + } + else if (len == 1) { + PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */ + if (other == NULL) + return NULL; + Py_INCREF(other); + if (PyObject_HasAttrString(other, "items")) { + PyObject *items = PyMapping_Items(other); + Py_DECREF(other); + if (items == NULL) + return NULL; + res = mutablemapping_add_pairs(self, items); + Py_DECREF(items); + if (res == -1) + return NULL; + } + else if (PyObject_HasAttrString(other, "keys")) { + PyObject *keys, *iterator, *key; + keys = PyObject_CallMethod(other, "keys", NULL); + Py_DECREF(other); + if (keys == NULL) + return NULL; + iterator = PyObject_GetIter(keys); + Py_DECREF(keys); + if (iterator == NULL) + return NULL; + while (res == 0 && (key = PyIter_Next(iterator))) { + PyObject *value = PyObject_GetItem(other, key); + if (value != NULL) { + res = PyObject_SetItem(self, key, value); + Py_DECREF(value); + } + else { + res = -1; + } + Py_DECREF(key); + } + Py_DECREF(iterator); + if (res != 0 || PyErr_Occurred()) + return NULL; + } + else { + res = mutablemapping_add_pairs(self, other); + Py_DECREF(other); + if (res != 0) + return NULL; + } + } + + /* now handle kwargs */ + len = (kwargs != NULL) ? PyObject_Size(kwargs) : 0; + if (len < 0) + return NULL; + else if (len > 0) { + PyObject *items; + if (!PyMapping_Check(kwargs)) { + PyErr_SetString(PyExc_TypeError, "expected mapping for kwargs"); + return NULL; + } + items = PyMapping_Items(kwargs); + if (items == NULL) + return NULL; + res = mutablemapping_add_pairs(self, items); + Py_DECREF(items); + if (res == -1) + return NULL; + } + + Py_RETURN_NONE; +} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 06:34:21 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 04:34:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E5?= Message-ID: <20150530043420.91773.78225@psf.io> https://hg.python.org/cpython/rev/242a7cafc5e7 changeset: 96364:242a7cafc5e7 parent: 96362:e7af362b78df parent: 96363:b85028c9d4b9 user: Eric Snow date: Fri May 29 22:34:01 2015 -0600 summary: Merge from 3.5 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 07:02:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 30 May 2015 05:02:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_use_assert_met?= =?utf-8?q?hod_in_another_place?= Message-ID: <20150530050229.91771.40545@psf.io> https://hg.python.org/cpython/rev/c794af63feef changeset: 96365:c794af63feef branch: 3.5 parent: 96363:b85028c9d4b9 user: Benjamin Peterson date: Sat May 30 00:02:17 2015 -0500 summary: use assert method in another place files: Lib/test/test_importlib/extension/test_loader.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -217,7 +217,7 @@ name = self.name + '_null_slots' module = self.load_module_by_name(name) self.assertIsInstance(module, types.ModuleType) - assert module.__name__ == name + self.assertEqual(module.__name__, name) def test_bad_modules(self): '''Test SystemError is raised for misbehaving extensions''' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 07:02:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 30 May 2015 05:02:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150530050229.24073.45044@psf.io> https://hg.python.org/cpython/rev/696033db8f94 changeset: 96366:696033db8f94 parent: 96364:242a7cafc5e7 parent: 96365:c794af63feef user: Benjamin Peterson date: Sat May 30 00:02:25 2015 -0500 summary: Merge 3.5 files: Lib/test/test_importlib/extension/test_loader.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -217,7 +217,7 @@ name = self.name + '_null_slots' module = self.load_module_by_name(name) self.assertIsInstance(module, types.ModuleType) - assert module.__name__ == name + self.assertEqual(module.__name__, name) def test_bad_modules(self): '''Test SystemError is raised for misbehaving extensions''' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 07:14:17 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 30 May 2015 05:14:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNTA5?= =?utf-8?q?=3A_Speed_up_Counter_operators?= Message-ID: <20150530051417.4354.11934@psf.io> https://hg.python.org/cpython/rev/fe4efc0032b5 changeset: 96367:fe4efc0032b5 branch: 3.5 parent: 96365:c794af63feef user: Raymond Hettinger date: Fri May 29 22:14:07 2015 -0700 summary: Issue #23509: Speed up Counter operators (Based on patch by Serhiy Storchaka.) files: Lib/collections/__init__.py | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -753,14 +753,22 @@ def __pos__(self): 'Adds an empty counter, effectively stripping negative and zero counts' - return self + Counter() + result = Counter() + for elem, count in self.items(): + if count > 0: + result[elem] = count + return result def __neg__(self): '''Subtracts from an empty counter. Strips positive and zero counts, and flips the sign on negative counts. ''' - return Counter() - self + result = Counter() + for elem, count in self.items(): + if count < 0: + result[elem] = 0 - count + return result def _keep_positive(self): '''Internal method to strip elements with a negative or zero count''' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 07:14:55 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 30 May 2015 05:14:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150530051455.18151.49673@psf.io> https://hg.python.org/cpython/rev/4a8bee4fe050 changeset: 96368:4a8bee4fe050 parent: 96366:696033db8f94 parent: 96367:fe4efc0032b5 user: Raymond Hettinger date: Fri May 29 22:14:50 2015 -0700 summary: merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 10:33:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 08:33:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Specify_defaul?= =?utf-8?q?t_values_of_semantic_booleans_in_Argument_Clinic_generated?= Message-ID: <20150530083338.24081.7116@psf.io> https://hg.python.org/cpython/rev/f0487d3db275 changeset: 96371:f0487d3db275 branch: 3.5 parent: 96369:f089b060688d user: Serhiy Storchaka date: Sat May 30 11:30:39 2015 +0300 summary: Specify default values of semantic booleans in Argument Clinic generated signatures as booleans. files: Modules/cjkcodecs/clinic/multibytecodec.c.h | 6 ++-- Modules/cjkcodecs/multibytecodec.c | 8 +++--- Modules/clinic/pyexpat.c.h | 12 +++++----- Modules/pyexpat.c | 8 +++--- Objects/bytearrayobject.c | 4 +- Objects/bytesobject.c | 4 +- Python/bltinmodule.c | 8 +++--- Python/clinic/bltinmodule.c.h | 10 ++++---- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -79,7 +79,7 @@ } PyDoc_STRVAR(_multibytecodec_MultibyteIncrementalEncoder_encode__doc__, -"encode($self, /, input, final=0)\n" +"encode($self, /, input, final=False)\n" "--\n" "\n"); @@ -126,7 +126,7 @@ } PyDoc_STRVAR(_multibytecodec_MultibyteIncrementalDecoder_decode__doc__, -"decode($self, /, input, final=0)\n" +"decode($self, /, input, final=False)\n" "--\n" "\n"); @@ -317,4 +317,4 @@ #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=c104f5fd548c1ac5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eebb21e18c3043d1 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -884,14 +884,14 @@ _multibytecodec.MultibyteIncrementalEncoder.encode input: object - final: int = 0 + final: int(c_default="0") = False [clinic start generated code]*/ static PyObject * _multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, PyObject *input, int final) -/*[clinic end generated code: output=123361b6c505e2c1 input=456b76d73e464661]*/ +/*[clinic end generated code: output=123361b6c505e2c1 input=a345c688fa664f92]*/ { return encoder_encode_stateful(STATEFUL_ECTX(self), input, final); } @@ -1041,14 +1041,14 @@ _multibytecodec.MultibyteIncrementalDecoder.decode input: Py_buffer - final: int = 0 + final: int(c_default="0") = False [clinic start generated code]*/ static PyObject * _multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, Py_buffer *input, int final) -/*[clinic end generated code: output=b9b9090e8a9ce2ba input=eb18c2f6e83589e1]*/ +/*[clinic end generated code: output=b9b9090e8a9ce2ba input=576631c61906d39d]*/ { MultibyteDecodeBuffer buf; char *data, *wdata = NULL; diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -3,7 +3,7 @@ [clinic start generated code]*/ PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, -"Parse($self, data, isFinal=0, /)\n" +"Parse($self, data, isfinal=False, /)\n" "--\n" "\n" "Parse XML data.\n" @@ -15,19 +15,19 @@ static PyObject * pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isFinal); + int isfinal); static PyObject * pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *args) { PyObject *return_value = NULL; PyObject *data; - int isFinal = 0; + int isfinal = 0; if (!PyArg_ParseTuple(args, "O|i:Parse", - &data, &isFinal)) + &data, &isfinal)) goto exit; - return_value = pyexpat_xmlparser_Parse_impl(self, data, isFinal); + return_value = pyexpat_xmlparser_Parse_impl(self, data, isfinal); exit: return return_value; @@ -281,4 +281,4 @@ #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=958c0faa1b855fc7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bf4d99c9702d8a6c input=a9049054013a1b77]*/ diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -707,7 +707,7 @@ pyexpat.xmlparser.Parse data: object - isFinal: int = 0 + isfinal: int(c_default="0") = False / Parse XML data. @@ -717,8 +717,8 @@ static PyObject * pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isFinal) -/*[clinic end generated code: output=37e105d55645b0f2 input=e37b81b8948ca7e0]*/ + int isfinal) +/*[clinic end generated code: output=f4db843dd1f4ed4b input=199d9e8e92ebbb4b]*/ { const char *s; Py_ssize_t slen; @@ -748,7 +748,7 @@ slen -= MAX_CHUNK_SIZE; } assert(MAX_CHUNK_SIZE < INT_MAX && slen < INT_MAX); - rc = XML_Parse(self->itself, s, (int)slen, isFinal); + rc = XML_Parse(self->itself, s, (int)slen, isfinal); done: if (view.buf != NULL) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2773,7 +2773,7 @@ /*[clinic input] bytearray.splitlines - keepends: int(py_default="False") = 0 + keepends: int(c_default="0") = False Return a list of the lines in the bytearray, breaking at line boundaries. @@ -2783,7 +2783,7 @@ static PyObject * bytearray_splitlines_impl(PyByteArrayObject *self, int keepends) -/*[clinic end generated code: output=4223c94b895f6ad9 input=36f0b25bc792f6c0]*/ +/*[clinic end generated code: output=4223c94b895f6ad9 input=8ccade941e5ea0bd]*/ { return stringlib_splitlines( (PyObject*) self, PyByteArray_AS_STRING(self), diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2942,7 +2942,7 @@ /*[clinic input] bytes.splitlines - keepends: int(py_default="False") = 0 + keepends: int(c_default="0") = False Return a list of the lines in the bytes, breaking at line boundaries. @@ -2952,7 +2952,7 @@ static PyObject * bytes_splitlines_impl(PyBytesObject*self, int keepends) -/*[clinic end generated code: output=995c3598f7833cad input=ddb93e3351080c8c]*/ +/*[clinic end generated code: output=995c3598f7833cad input=7f4aac67144f9944]*/ { return stringlib_splitlines( (PyObject*) self, PyBytes_AS_STRING(self), diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -637,7 +637,7 @@ filename: object(converter="PyUnicode_FSDecoder") mode: str flags: int = 0 - dont_inherit: int = 0 + dont_inherit: int(c_default="0") = False optimize: int = -1 Compile source into a code object that can be executed by exec() or eval(). @@ -648,9 +648,9 @@ single (interactive) statement, or 'eval' to compile an expression. The flags argument, if present, controls which future statements influence the compilation of the code. -The dont_inherit argument, if non-zero, stops the compilation inheriting +The dont_inherit argument, if true, stops the compilation inheriting the effects of any future statements in effect in the code calling -compile; if absent or zero these statements do influence the compilation, +compile; if absent or false these statements do influence the compilation, in addition to any features explicitly specified. [clinic start generated code]*/ @@ -658,7 +658,7 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=31881762c1bb90c4 input=7faa105f669fefcf]*/ +/*[clinic end generated code: output=31881762c1bb90c4 input=9d53e8cfb3c86414]*/ { Py_buffer view = {NULL, NULL}; const char *str; diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -129,8 +129,8 @@ } PyDoc_STRVAR(builtin_compile__doc__, -"compile($module, /, source, filename, mode, flags=0, dont_inherit=0,\n" -" optimize=-1)\n" +"compile($module, /, source, filename, mode, flags=0,\n" +" dont_inherit=False, optimize=-1)\n" "--\n" "\n" "Compile source into a code object that can be executed by exec() or eval().\n" @@ -141,9 +141,9 @@ "single (interactive) statement, or \'eval\' to compile an expression.\n" "The flags argument, if present, controls which future statements influence\n" "the compilation of the code.\n" -"The dont_inherit argument, if non-zero, stops the compilation inheriting\n" +"The dont_inherit argument, if true, stops the compilation inheriting\n" "the effects of any future statements in effect in the code calling\n" -"compile; if absent or zero these statements do influence the compilation,\n" +"compile; if absent or false these statements do influence the compilation,\n" "in addition to any features explicitly specified."); #define BUILTIN_COMPILE_METHODDEF \ @@ -660,4 +660,4 @@ exit: return return_value; } -/*[clinic end generated code: output=9b34d1ca57effad8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bec3399c0aee98d7 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 10:33:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 08:33:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Use_converter_names_instead_of_format_units_in_Argument_?= =?utf-8?q?Clinic_descriptions?= Message-ID: <20150530083337.18149.3748@psf.io> https://hg.python.org/cpython/rev/7654696dbc5a changeset: 96370:7654696dbc5a parent: 96368:4a8bee4fe050 parent: 96369:f089b060688d user: Serhiy Storchaka date: Sat May 30 11:10:58 2015 +0300 summary: Use converter names instead of format units in Argument Clinic descriptions in builtin and _crypt modules. files: Modules/_cryptmodule.c | 6 +- Python/bltinmodule.c | 144 ++++++++++++++-------------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -17,8 +17,8 @@ /*[clinic input] crypt.crypt - word: 's' - salt: 's' + word: str + salt: str / Hash a *word* with the given *salt* and return the hashed password. @@ -32,7 +32,7 @@ static PyObject * crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt) -/*[clinic end generated code: output=995ad1e854d83069 input=4d93b6d0f41fbf58]*/ +/*[clinic end generated code: output=995ad1e854d83069 input=0e8edec9c364352b]*/ { /* On some platforms (AtheOS) crypt returns NULL for an invalid salt. Return None in that case. XXX Maybe raise an exception? */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -235,7 +235,7 @@ /*[clinic input] abs as builtin_abs - x: 'O' + x: object / Return the absolute value of the argument. @@ -243,7 +243,7 @@ static PyObject * builtin_abs(PyModuleDef *module, PyObject *x) -/*[clinic end generated code: output=6833047c493ecea2 input=aa29cc07869b4732]*/ +/*[clinic end generated code: output=6833047c493ecea2 input=bed4ca14e29c20d1]*/ { return PyNumber_Absolute(x); } @@ -251,7 +251,7 @@ /*[clinic input] all as builtin_all - iterable: 'O' + iterable: object / Return True if bool(x) is True for all values x in the iterable. @@ -261,7 +261,7 @@ static PyObject * builtin_all(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=089e6d1b7bde27b1 input=dd506dc9998d42bd]*/ +/*[clinic end generated code: output=089e6d1b7bde27b1 input=1a7c5d1bc3438a21]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -300,7 +300,7 @@ /*[clinic input] any as builtin_any - iterable: 'O' + iterable: object / Return True if bool(x) is True for any x in the iterable. @@ -310,7 +310,7 @@ static PyObject * builtin_any(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=1be994b2c2307492 input=8fe8460f3fbbced8]*/ +/*[clinic end generated code: output=1be994b2c2307492 input=41d7451c23384f24]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -349,7 +349,7 @@ /*[clinic input] ascii as builtin_ascii - obj: 'O' + obj: object / Return an ASCII-only representation of an object. @@ -362,7 +362,7 @@ static PyObject * builtin_ascii(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=d4e862c48af2a933 input=0cbdc1420a306325]*/ +/*[clinic end generated code: output=d4e862c48af2a933 input=4c62732e1b3a3cc9]*/ { return PyObject_ASCII(obj); } @@ -371,7 +371,7 @@ /*[clinic input] bin as builtin_bin - number: 'O' + number: object / Return the binary representation of an integer. @@ -382,7 +382,7 @@ static PyObject * builtin_bin(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=25ee26c6cf3bbb54 input=2a6362ae9a9c9203]*/ +/*[clinic end generated code: output=25ee26c6cf3bbb54 input=53f8a0264bacaf90]*/ { return PyNumber_ToBase(number, 2); } @@ -391,7 +391,7 @@ /*[clinic input] callable as builtin_callable - obj: 'O' + obj: object / Return whether the object is callable (i.e., some kind of function). @@ -402,7 +402,7 @@ static PyObject * builtin_callable(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=f4df2ce92364b656 input=bb3bb528fffdade4]*/ +/*[clinic end generated code: output=f4df2ce92364b656 input=1423bab99cc41f58]*/ { return PyBool_FromLong((long)PyCallable_Check(obj)); } @@ -564,7 +564,7 @@ /*[clinic input] format as builtin_format - value: 'O' + value: object format_spec: unicode(c_default="NULL") = '' / @@ -576,7 +576,7 @@ static PyObject * builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec) -/*[clinic end generated code: output=4341fd78a5f01764 input=e23f2f11e0098c64]*/ +/*[clinic end generated code: output=4341fd78a5f01764 input=6325e751a1b29b86]*/ { return PyObject_Format(value, format_spec); } @@ -584,7 +584,7 @@ /*[clinic input] chr as builtin_chr - i: 'i' + i: int / Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff. @@ -592,7 +592,7 @@ static PyObject * builtin_chr_impl(PyModuleDef *module, int i) -/*[clinic end generated code: output=67fe4d87e690f373 input=9b1ced29615adf66]*/ +/*[clinic end generated code: output=67fe4d87e690f373 input=3f604ef45a70750d]*/ { return PyUnicode_FromOrdinal(i); } @@ -633,12 +633,12 @@ /*[clinic input] compile as builtin_compile - source: 'O' + source: object filename: object(converter="PyUnicode_FSDecoder") - mode: 's' - flags: 'i' = 0 - dont_inherit: 'i' = 0 - optimize: 'i' = -1 + mode: str + flags: int = 0 + dont_inherit: int = 0 + optimize: int = -1 Compile source into a code object that can be executed by exec() or eval(). @@ -658,7 +658,7 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=31881762c1bb90c4 input=c6212a9d21472f7e]*/ +/*[clinic end generated code: output=31881762c1bb90c4 input=7faa105f669fefcf]*/ { Py_buffer view = {NULL, NULL}; const char *str; @@ -775,8 +775,8 @@ /*[clinic input] divmod as builtin_divmod - x: 'O' - y: 'O' + x: object + y: object / Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. @@ -784,7 +784,7 @@ static PyObject * builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) -/*[clinic end generated code: output=9ad0076120ebf9ac input=c9c617b7bb74c615]*/ +/*[clinic end generated code: output=9ad0076120ebf9ac input=7fdb15f8a97a5fe7]*/ { return PyNumber_Divmod(x, y); } @@ -793,9 +793,9 @@ /*[clinic input] eval as builtin_eval - source: 'O' - globals: 'O' = None - locals: 'O' = None + source: object + globals: object = None + locals: object = None / Evaluate the given source in the context of globals and locals. @@ -810,7 +810,7 @@ static PyObject * builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=7284501fb7b4d666 input=31e42c1d2125b50b]*/ +/*[clinic end generated code: output=7284501fb7b4d666 input=11ee718a8640e527]*/ { PyObject *result, *tmp = NULL; Py_buffer view = {NULL, NULL}; @@ -878,9 +878,9 @@ /*[clinic input] exec as builtin_exec - source: 'O' - globals: 'O' = None - locals: 'O' = None + source: object + globals: object = None + locals: object = None / Execute the given source in the context of globals and locals. @@ -895,7 +895,7 @@ static PyObject * builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=83d574ef9d5d0b46 input=536e057b5e00d89e]*/ +/*[clinic end generated code: output=83d574ef9d5d0b46 input=01ca3e1c01692829]*/ { PyObject *v; @@ -1022,8 +1022,8 @@ /*[clinic input] hasattr as builtin_hasattr - obj: 'O' - name: 'O' + obj: object + name: object / Return whether the object has an attribute with the given name. @@ -1033,7 +1033,7 @@ static PyObject * builtin_hasattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=81154fdd63634696 input=b50bad5f739ea10d]*/ +/*[clinic end generated code: output=81154fdd63634696 input=0faec9787d979542]*/ { PyObject *v; @@ -1063,7 +1063,7 @@ id as builtin_id self: self(type="PyModuleDef *") - obj as v: 'O' + obj as v: object / Return the identity of an object. @@ -1074,7 +1074,7 @@ static PyObject * builtin_id(PyModuleDef *self, PyObject *v) -/*[clinic end generated code: output=0aa640785f697f65 input=a1f988d98357341d]*/ +/*[clinic end generated code: output=0aa640785f697f65 input=5a534136419631f4]*/ { return PyLong_FromVoidPtr(v); } @@ -1297,9 +1297,9 @@ /*[clinic input] setattr as builtin_setattr - obj: 'O' - name: 'O' - value: 'O' + obj: object + name: object + value: object / Sets the named attribute on the given object to the specified value. @@ -1310,7 +1310,7 @@ static PyObject * builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d881c655c0f7e34f input=fbe7e53403116b93]*/ +/*[clinic end generated code: output=d881c655c0f7e34f input=bd2b7ca6875a1899]*/ { if (PyObject_SetAttr(obj, name, value) != 0) return NULL; @@ -1322,8 +1322,8 @@ /*[clinic input] delattr as builtin_delattr - obj: 'O' - name: 'O' + obj: object + name: object / Deletes the named attribute from the given object. @@ -1333,7 +1333,7 @@ static PyObject * builtin_delattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=ef653e698a0b4187 input=647af2ce9183a823]*/ +/*[clinic end generated code: output=ef653e698a0b4187 input=db16685d6b4b9410]*/ { if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0) return NULL; @@ -1345,7 +1345,7 @@ /*[clinic input] hash as builtin_hash - obj: 'O' + obj: object / Return the hash value for the given object. @@ -1356,7 +1356,7 @@ static PyObject * builtin_hash(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=1f32ff154c1f751a input=ccc4d2b9a351df4e]*/ +/*[clinic end generated code: output=1f32ff154c1f751a input=58c48be822bf9c54]*/ { Py_hash_t x; @@ -1370,7 +1370,7 @@ /*[clinic input] hex as builtin_hex - number: 'O' + number: object / Return the hexadecimal representation of an integer. @@ -1381,7 +1381,7 @@ static PyObject * builtin_hex(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=618489ce3cbc5858 input=e816200b0a728ebe]*/ +/*[clinic end generated code: output=618489ce3cbc5858 input=e645aff5fc7d540e]*/ { return PyNumber_ToBase(number, 16); } @@ -1417,7 +1417,7 @@ /*[clinic input] len as builtin_len - obj: 'O' + obj: object / Return the number of items in a container. @@ -1425,7 +1425,7 @@ static PyObject * builtin_len(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=8e5837b6f81d915b input=2e5ff15db9a2de22]*/ +/*[clinic end generated code: output=8e5837b6f81d915b input=bc55598da9e9c9b5]*/ { Py_ssize_t res; @@ -1596,7 +1596,7 @@ /*[clinic input] oct as builtin_oct - number: 'O' + number: object / Return the octal representation of an integer. @@ -1607,7 +1607,7 @@ static PyObject * builtin_oct(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=18f701bc6d8f804a input=a3a372b521b3dd13]*/ +/*[clinic end generated code: output=18f701bc6d8f804a input=ad6b274af4016c72]*/ { return PyNumber_ToBase(number, 8); } @@ -1616,7 +1616,7 @@ /*[clinic input] ord as builtin_ord - c: 'O' + c: object / Return the Unicode code point for a one-character string. @@ -1624,7 +1624,7 @@ static PyObject * builtin_ord(PyModuleDef *module, PyObject *c) -/*[clinic end generated code: output=04fd27272d9462f6 input=762355f87451efa3]*/ +/*[clinic end generated code: output=04fd27272d9462f6 input=3064e5d6203ad012]*/ { long ord; Py_ssize_t size; @@ -1671,9 +1671,9 @@ /*[clinic input] pow as builtin_pow - x: 'O' - y: 'O' - z: 'O' = None + x: object + y: object + z: object = None / Equivalent to x**y (with two arguments) or x**y % z (with three arguments) @@ -1684,7 +1684,7 @@ static PyObject * builtin_pow_impl(PyModuleDef *module, PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=1fba268adba9b45f input=561a942d5f5c1899]*/ +/*[clinic end generated code: output=1fba268adba9b45f input=653d57d38d41fc07]*/ { return PyNumber_Power(x, y, z); } @@ -1978,7 +1978,7 @@ /*[clinic input] repr as builtin_repr - obj: 'O' + obj: object / Return the canonical string representation of the object. @@ -1988,7 +1988,7 @@ static PyObject * builtin_repr(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=dc41784fa4341834 input=a2bca0f38a5a924d]*/ +/*[clinic end generated code: output=dc41784fa4341834 input=1c9e6d66d3e3be04]*/ { return PyObject_Repr(obj); } @@ -2045,9 +2045,9 @@ /* [disabled clinic input] sorted as builtin_sorted - iterable as seq: 'O' - key as keyfunc: 'O' = None - reverse: 'O' = False + iterable as seq: object + key as keyfunc: object = None + reverse: object = False Return a new list containing all items from the iterable in ascending order. @@ -2145,7 +2145,7 @@ /*[clinic input] sum as builtin_sum - iterable: 'O' + iterable: object start: object(c_default="NULL") = 0 / @@ -2158,7 +2158,7 @@ static PyObject * builtin_sum_impl(PyModuleDef *module, PyObject *iterable, PyObject *start) -/*[clinic end generated code: output=33655b248b21d581 input=90ae7a242cfcf025]*/ +/*[clinic end generated code: output=33655b248b21d581 input=3b5b7a9d7611c73a]*/ { PyObject *result = start; PyObject *temp, *item, *iter; @@ -2322,8 +2322,8 @@ /*[clinic input] isinstance as builtin_isinstance - obj: 'O' - class_or_tuple: 'O' + obj: object + class_or_tuple: object / Return whether an object is an instance of a class or of a subclass thereof. @@ -2336,7 +2336,7 @@ static PyObject * builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple) -/*[clinic end generated code: output=f960b7c12dbbeda0 input=cf9eb0ad6bb9bad6]*/ +/*[clinic end generated code: output=f960b7c12dbbeda0 input=ffa743db1daf7549]*/ { int retval; @@ -2350,8 +2350,8 @@ /*[clinic input] issubclass as builtin_issubclass - cls: 'O' - class_or_tuple: 'O' + cls: object + class_or_tuple: object / Return whether 'cls' is a derived from another class or is the same class. @@ -2364,7 +2364,7 @@ static PyObject * builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple) -/*[clinic end generated code: output=8b012a151940bbf2 input=923d03fa41fc352a]*/ +/*[clinic end generated code: output=8b012a151940bbf2 input=af5f35e9ceaddaf6]*/ { int retval; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 10:33:37 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 08:33:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Use_converter_?= =?utf-8?q?names_instead_of_format_units_in_Argument_Clinic_descriptions?= Message-ID: <20150530083337.83491.42316@psf.io> https://hg.python.org/cpython/rev/f089b060688d changeset: 96369:f089b060688d branch: 3.5 parent: 96367:fe4efc0032b5 user: Serhiy Storchaka date: Sat May 30 11:09:35 2015 +0300 summary: Use converter names instead of format units in Argument Clinic descriptions in builtin and _crypt modules. files: Modules/_cryptmodule.c | 6 +- Python/bltinmodule.c | 144 ++++++++++++++-------------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -17,8 +17,8 @@ /*[clinic input] crypt.crypt - word: 's' - salt: 's' + word: str + salt: str / Hash a *word* with the given *salt* and return the hashed password. @@ -32,7 +32,7 @@ static PyObject * crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt) -/*[clinic end generated code: output=995ad1e854d83069 input=4d93b6d0f41fbf58]*/ +/*[clinic end generated code: output=995ad1e854d83069 input=0e8edec9c364352b]*/ { /* On some platforms (AtheOS) crypt returns NULL for an invalid salt. Return None in that case. XXX Maybe raise an exception? */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -235,7 +235,7 @@ /*[clinic input] abs as builtin_abs - x: 'O' + x: object / Return the absolute value of the argument. @@ -243,7 +243,7 @@ static PyObject * builtin_abs(PyModuleDef *module, PyObject *x) -/*[clinic end generated code: output=6833047c493ecea2 input=aa29cc07869b4732]*/ +/*[clinic end generated code: output=6833047c493ecea2 input=bed4ca14e29c20d1]*/ { return PyNumber_Absolute(x); } @@ -251,7 +251,7 @@ /*[clinic input] all as builtin_all - iterable: 'O' + iterable: object / Return True if bool(x) is True for all values x in the iterable. @@ -261,7 +261,7 @@ static PyObject * builtin_all(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=089e6d1b7bde27b1 input=dd506dc9998d42bd]*/ +/*[clinic end generated code: output=089e6d1b7bde27b1 input=1a7c5d1bc3438a21]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -300,7 +300,7 @@ /*[clinic input] any as builtin_any - iterable: 'O' + iterable: object / Return True if bool(x) is True for any x in the iterable. @@ -310,7 +310,7 @@ static PyObject * builtin_any(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=1be994b2c2307492 input=8fe8460f3fbbced8]*/ +/*[clinic end generated code: output=1be994b2c2307492 input=41d7451c23384f24]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -349,7 +349,7 @@ /*[clinic input] ascii as builtin_ascii - obj: 'O' + obj: object / Return an ASCII-only representation of an object. @@ -362,7 +362,7 @@ static PyObject * builtin_ascii(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=d4e862c48af2a933 input=0cbdc1420a306325]*/ +/*[clinic end generated code: output=d4e862c48af2a933 input=4c62732e1b3a3cc9]*/ { return PyObject_ASCII(obj); } @@ -371,7 +371,7 @@ /*[clinic input] bin as builtin_bin - number: 'O' + number: object / Return the binary representation of an integer. @@ -382,7 +382,7 @@ static PyObject * builtin_bin(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=25ee26c6cf3bbb54 input=2a6362ae9a9c9203]*/ +/*[clinic end generated code: output=25ee26c6cf3bbb54 input=53f8a0264bacaf90]*/ { return PyNumber_ToBase(number, 2); } @@ -391,7 +391,7 @@ /*[clinic input] callable as builtin_callable - obj: 'O' + obj: object / Return whether the object is callable (i.e., some kind of function). @@ -402,7 +402,7 @@ static PyObject * builtin_callable(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=f4df2ce92364b656 input=bb3bb528fffdade4]*/ +/*[clinic end generated code: output=f4df2ce92364b656 input=1423bab99cc41f58]*/ { return PyBool_FromLong((long)PyCallable_Check(obj)); } @@ -564,7 +564,7 @@ /*[clinic input] format as builtin_format - value: 'O' + value: object format_spec: unicode(c_default="NULL") = '' / @@ -576,7 +576,7 @@ static PyObject * builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec) -/*[clinic end generated code: output=4341fd78a5f01764 input=e23f2f11e0098c64]*/ +/*[clinic end generated code: output=4341fd78a5f01764 input=6325e751a1b29b86]*/ { return PyObject_Format(value, format_spec); } @@ -584,7 +584,7 @@ /*[clinic input] chr as builtin_chr - i: 'i' + i: int / Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff. @@ -592,7 +592,7 @@ static PyObject * builtin_chr_impl(PyModuleDef *module, int i) -/*[clinic end generated code: output=67fe4d87e690f373 input=9b1ced29615adf66]*/ +/*[clinic end generated code: output=67fe4d87e690f373 input=3f604ef45a70750d]*/ { return PyUnicode_FromOrdinal(i); } @@ -633,12 +633,12 @@ /*[clinic input] compile as builtin_compile - source: 'O' + source: object filename: object(converter="PyUnicode_FSDecoder") - mode: 's' - flags: 'i' = 0 - dont_inherit: 'i' = 0 - optimize: 'i' = -1 + mode: str + flags: int = 0 + dont_inherit: int = 0 + optimize: int = -1 Compile source into a code object that can be executed by exec() or eval(). @@ -658,7 +658,7 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=31881762c1bb90c4 input=c6212a9d21472f7e]*/ +/*[clinic end generated code: output=31881762c1bb90c4 input=7faa105f669fefcf]*/ { Py_buffer view = {NULL, NULL}; const char *str; @@ -775,8 +775,8 @@ /*[clinic input] divmod as builtin_divmod - x: 'O' - y: 'O' + x: object + y: object / Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. @@ -784,7 +784,7 @@ static PyObject * builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) -/*[clinic end generated code: output=9ad0076120ebf9ac input=c9c617b7bb74c615]*/ +/*[clinic end generated code: output=9ad0076120ebf9ac input=7fdb15f8a97a5fe7]*/ { return PyNumber_Divmod(x, y); } @@ -793,9 +793,9 @@ /*[clinic input] eval as builtin_eval - source: 'O' - globals: 'O' = None - locals: 'O' = None + source: object + globals: object = None + locals: object = None / Evaluate the given source in the context of globals and locals. @@ -810,7 +810,7 @@ static PyObject * builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=7284501fb7b4d666 input=31e42c1d2125b50b]*/ +/*[clinic end generated code: output=7284501fb7b4d666 input=11ee718a8640e527]*/ { PyObject *result, *tmp = NULL; Py_buffer view = {NULL, NULL}; @@ -878,9 +878,9 @@ /*[clinic input] exec as builtin_exec - source: 'O' - globals: 'O' = None - locals: 'O' = None + source: object + globals: object = None + locals: object = None / Execute the given source in the context of globals and locals. @@ -895,7 +895,7 @@ static PyObject * builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=83d574ef9d5d0b46 input=536e057b5e00d89e]*/ +/*[clinic end generated code: output=83d574ef9d5d0b46 input=01ca3e1c01692829]*/ { PyObject *v; @@ -1022,8 +1022,8 @@ /*[clinic input] hasattr as builtin_hasattr - obj: 'O' - name: 'O' + obj: object + name: object / Return whether the object has an attribute with the given name. @@ -1033,7 +1033,7 @@ static PyObject * builtin_hasattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=81154fdd63634696 input=b50bad5f739ea10d]*/ +/*[clinic end generated code: output=81154fdd63634696 input=0faec9787d979542]*/ { PyObject *v; @@ -1063,7 +1063,7 @@ id as builtin_id self: self(type="PyModuleDef *") - obj as v: 'O' + obj as v: object / Return the identity of an object. @@ -1074,7 +1074,7 @@ static PyObject * builtin_id(PyModuleDef *self, PyObject *v) -/*[clinic end generated code: output=0aa640785f697f65 input=a1f988d98357341d]*/ +/*[clinic end generated code: output=0aa640785f697f65 input=5a534136419631f4]*/ { return PyLong_FromVoidPtr(v); } @@ -1297,9 +1297,9 @@ /*[clinic input] setattr as builtin_setattr - obj: 'O' - name: 'O' - value: 'O' + obj: object + name: object + value: object / Sets the named attribute on the given object to the specified value. @@ -1310,7 +1310,7 @@ static PyObject * builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d881c655c0f7e34f input=fbe7e53403116b93]*/ +/*[clinic end generated code: output=d881c655c0f7e34f input=bd2b7ca6875a1899]*/ { if (PyObject_SetAttr(obj, name, value) != 0) return NULL; @@ -1322,8 +1322,8 @@ /*[clinic input] delattr as builtin_delattr - obj: 'O' - name: 'O' + obj: object + name: object / Deletes the named attribute from the given object. @@ -1333,7 +1333,7 @@ static PyObject * builtin_delattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=ef653e698a0b4187 input=647af2ce9183a823]*/ +/*[clinic end generated code: output=ef653e698a0b4187 input=db16685d6b4b9410]*/ { if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0) return NULL; @@ -1345,7 +1345,7 @@ /*[clinic input] hash as builtin_hash - obj: 'O' + obj: object / Return the hash value for the given object. @@ -1356,7 +1356,7 @@ static PyObject * builtin_hash(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=1f32ff154c1f751a input=ccc4d2b9a351df4e]*/ +/*[clinic end generated code: output=1f32ff154c1f751a input=58c48be822bf9c54]*/ { Py_hash_t x; @@ -1370,7 +1370,7 @@ /*[clinic input] hex as builtin_hex - number: 'O' + number: object / Return the hexadecimal representation of an integer. @@ -1381,7 +1381,7 @@ static PyObject * builtin_hex(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=618489ce3cbc5858 input=e816200b0a728ebe]*/ +/*[clinic end generated code: output=618489ce3cbc5858 input=e645aff5fc7d540e]*/ { return PyNumber_ToBase(number, 16); } @@ -1417,7 +1417,7 @@ /*[clinic input] len as builtin_len - obj: 'O' + obj: object / Return the number of items in a container. @@ -1425,7 +1425,7 @@ static PyObject * builtin_len(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=8e5837b6f81d915b input=2e5ff15db9a2de22]*/ +/*[clinic end generated code: output=8e5837b6f81d915b input=bc55598da9e9c9b5]*/ { Py_ssize_t res; @@ -1596,7 +1596,7 @@ /*[clinic input] oct as builtin_oct - number: 'O' + number: object / Return the octal representation of an integer. @@ -1607,7 +1607,7 @@ static PyObject * builtin_oct(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=18f701bc6d8f804a input=a3a372b521b3dd13]*/ +/*[clinic end generated code: output=18f701bc6d8f804a input=ad6b274af4016c72]*/ { return PyNumber_ToBase(number, 8); } @@ -1616,7 +1616,7 @@ /*[clinic input] ord as builtin_ord - c: 'O' + c: object / Return the Unicode code point for a one-character string. @@ -1624,7 +1624,7 @@ static PyObject * builtin_ord(PyModuleDef *module, PyObject *c) -/*[clinic end generated code: output=04fd27272d9462f6 input=762355f87451efa3]*/ +/*[clinic end generated code: output=04fd27272d9462f6 input=3064e5d6203ad012]*/ { long ord; Py_ssize_t size; @@ -1671,9 +1671,9 @@ /*[clinic input] pow as builtin_pow - x: 'O' - y: 'O' - z: 'O' = None + x: object + y: object + z: object = None / Equivalent to x**y (with two arguments) or x**y % z (with three arguments) @@ -1684,7 +1684,7 @@ static PyObject * builtin_pow_impl(PyModuleDef *module, PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=1fba268adba9b45f input=561a942d5f5c1899]*/ +/*[clinic end generated code: output=1fba268adba9b45f input=653d57d38d41fc07]*/ { return PyNumber_Power(x, y, z); } @@ -1978,7 +1978,7 @@ /*[clinic input] repr as builtin_repr - obj: 'O' + obj: object / Return the canonical string representation of the object. @@ -1988,7 +1988,7 @@ static PyObject * builtin_repr(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=dc41784fa4341834 input=a2bca0f38a5a924d]*/ +/*[clinic end generated code: output=dc41784fa4341834 input=1c9e6d66d3e3be04]*/ { return PyObject_Repr(obj); } @@ -2045,9 +2045,9 @@ /* [disabled clinic input] sorted as builtin_sorted - iterable as seq: 'O' - key as keyfunc: 'O' = None - reverse: 'O' = False + iterable as seq: object + key as keyfunc: object = None + reverse: object = False Return a new list containing all items from the iterable in ascending order. @@ -2145,7 +2145,7 @@ /*[clinic input] sum as builtin_sum - iterable: 'O' + iterable: object start: object(c_default="NULL") = 0 / @@ -2158,7 +2158,7 @@ static PyObject * builtin_sum_impl(PyModuleDef *module, PyObject *iterable, PyObject *start) -/*[clinic end generated code: output=33655b248b21d581 input=90ae7a242cfcf025]*/ +/*[clinic end generated code: output=33655b248b21d581 input=3b5b7a9d7611c73a]*/ { PyObject *result = start; PyObject *temp, *item, *iter; @@ -2322,8 +2322,8 @@ /*[clinic input] isinstance as builtin_isinstance - obj: 'O' - class_or_tuple: 'O' + obj: object + class_or_tuple: object / Return whether an object is an instance of a class or of a subclass thereof. @@ -2336,7 +2336,7 @@ static PyObject * builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple) -/*[clinic end generated code: output=f960b7c12dbbeda0 input=cf9eb0ad6bb9bad6]*/ +/*[clinic end generated code: output=f960b7c12dbbeda0 input=ffa743db1daf7549]*/ { int retval; @@ -2350,8 +2350,8 @@ /*[clinic input] issubclass as builtin_issubclass - cls: 'O' - class_or_tuple: 'O' + cls: object + class_or_tuple: object / Return whether 'cls' is a derived from another class or is the same class. @@ -2364,7 +2364,7 @@ static PyObject * builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple) -/*[clinic end generated code: output=8b012a151940bbf2 input=923d03fa41fc352a]*/ +/*[clinic end generated code: output=8b012a151940bbf2 input=af5f35e9ceaddaf6]*/ { int retval; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 10:33:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 08:33:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Specify_default_values_of_semantic_booleans_in_Argument_?= =?utf-8?q?Clinic_generated?= Message-ID: <20150530083343.111598.8493@psf.io> https://hg.python.org/cpython/rev/2acc30d24edc changeset: 96372:2acc30d24edc parent: 96370:7654696dbc5a parent: 96371:f0487d3db275 user: Serhiy Storchaka date: Sat May 30 11:32:58 2015 +0300 summary: Specify default values of semantic booleans in Argument Clinic generated signatures as booleans. files: Modules/cjkcodecs/clinic/multibytecodec.c.h | 6 ++-- Modules/cjkcodecs/multibytecodec.c | 8 +++--- Modules/clinic/pyexpat.c.h | 12 +++++----- Modules/pyexpat.c | 8 +++--- Objects/bytearrayobject.c | 4 +- Objects/bytesobject.c | 4 +- Python/bltinmodule.c | 8 +++--- Python/clinic/bltinmodule.c.h | 10 ++++---- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -79,7 +79,7 @@ } PyDoc_STRVAR(_multibytecodec_MultibyteIncrementalEncoder_encode__doc__, -"encode($self, /, input, final=0)\n" +"encode($self, /, input, final=False)\n" "--\n" "\n"); @@ -126,7 +126,7 @@ } PyDoc_STRVAR(_multibytecodec_MultibyteIncrementalDecoder_decode__doc__, -"decode($self, /, input, final=0)\n" +"decode($self, /, input, final=False)\n" "--\n" "\n"); @@ -317,4 +317,4 @@ #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=c104f5fd548c1ac5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eebb21e18c3043d1 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -884,14 +884,14 @@ _multibytecodec.MultibyteIncrementalEncoder.encode input: object - final: int = 0 + final: int(c_default="0") = False [clinic start generated code]*/ static PyObject * _multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, PyObject *input, int final) -/*[clinic end generated code: output=123361b6c505e2c1 input=456b76d73e464661]*/ +/*[clinic end generated code: output=123361b6c505e2c1 input=a345c688fa664f92]*/ { return encoder_encode_stateful(STATEFUL_ECTX(self), input, final); } @@ -1041,14 +1041,14 @@ _multibytecodec.MultibyteIncrementalDecoder.decode input: Py_buffer - final: int = 0 + final: int(c_default="0") = False [clinic start generated code]*/ static PyObject * _multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, Py_buffer *input, int final) -/*[clinic end generated code: output=b9b9090e8a9ce2ba input=eb18c2f6e83589e1]*/ +/*[clinic end generated code: output=b9b9090e8a9ce2ba input=576631c61906d39d]*/ { MultibyteDecodeBuffer buf; char *data, *wdata = NULL; diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -3,7 +3,7 @@ [clinic start generated code]*/ PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, -"Parse($self, data, isFinal=0, /)\n" +"Parse($self, data, isfinal=False, /)\n" "--\n" "\n" "Parse XML data.\n" @@ -15,19 +15,19 @@ static PyObject * pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isFinal); + int isfinal); static PyObject * pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *args) { PyObject *return_value = NULL; PyObject *data; - int isFinal = 0; + int isfinal = 0; if (!PyArg_ParseTuple(args, "O|i:Parse", - &data, &isFinal)) + &data, &isfinal)) goto exit; - return_value = pyexpat_xmlparser_Parse_impl(self, data, isFinal); + return_value = pyexpat_xmlparser_Parse_impl(self, data, isfinal); exit: return return_value; @@ -281,4 +281,4 @@ #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=958c0faa1b855fc7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bf4d99c9702d8a6c input=a9049054013a1b77]*/ diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -707,7 +707,7 @@ pyexpat.xmlparser.Parse data: object - isFinal: int = 0 + isfinal: int(c_default="0") = False / Parse XML data. @@ -717,8 +717,8 @@ static PyObject * pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isFinal) -/*[clinic end generated code: output=37e105d55645b0f2 input=e37b81b8948ca7e0]*/ + int isfinal) +/*[clinic end generated code: output=f4db843dd1f4ed4b input=199d9e8e92ebbb4b]*/ { const char *s; Py_ssize_t slen; @@ -748,7 +748,7 @@ slen -= MAX_CHUNK_SIZE; } assert(MAX_CHUNK_SIZE < INT_MAX && slen < INT_MAX); - rc = XML_Parse(self->itself, s, (int)slen, isFinal); + rc = XML_Parse(self->itself, s, (int)slen, isfinal); done: if (view.buf != NULL) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2773,7 +2773,7 @@ /*[clinic input] bytearray.splitlines - keepends: int(py_default="False") = 0 + keepends: int(c_default="0") = False Return a list of the lines in the bytearray, breaking at line boundaries. @@ -2783,7 +2783,7 @@ static PyObject * bytearray_splitlines_impl(PyByteArrayObject *self, int keepends) -/*[clinic end generated code: output=4223c94b895f6ad9 input=36f0b25bc792f6c0]*/ +/*[clinic end generated code: output=4223c94b895f6ad9 input=8ccade941e5ea0bd]*/ { return stringlib_splitlines( (PyObject*) self, PyByteArray_AS_STRING(self), diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2942,7 +2942,7 @@ /*[clinic input] bytes.splitlines - keepends: int(py_default="False") = 0 + keepends: int(c_default="0") = False Return a list of the lines in the bytes, breaking at line boundaries. @@ -2952,7 +2952,7 @@ static PyObject * bytes_splitlines_impl(PyBytesObject*self, int keepends) -/*[clinic end generated code: output=995c3598f7833cad input=ddb93e3351080c8c]*/ +/*[clinic end generated code: output=995c3598f7833cad input=7f4aac67144f9944]*/ { return stringlib_splitlines( (PyObject*) self, PyBytes_AS_STRING(self), diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -637,7 +637,7 @@ filename: object(converter="PyUnicode_FSDecoder") mode: str flags: int = 0 - dont_inherit: int = 0 + dont_inherit: int(c_default="0") = False optimize: int = -1 Compile source into a code object that can be executed by exec() or eval(). @@ -648,9 +648,9 @@ single (interactive) statement, or 'eval' to compile an expression. The flags argument, if present, controls which future statements influence the compilation of the code. -The dont_inherit argument, if non-zero, stops the compilation inheriting +The dont_inherit argument, if true, stops the compilation inheriting the effects of any future statements in effect in the code calling -compile; if absent or zero these statements do influence the compilation, +compile; if absent or false these statements do influence the compilation, in addition to any features explicitly specified. [clinic start generated code]*/ @@ -658,7 +658,7 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=31881762c1bb90c4 input=7faa105f669fefcf]*/ +/*[clinic end generated code: output=31881762c1bb90c4 input=9d53e8cfb3c86414]*/ { Py_buffer view = {NULL, NULL}; const char *str; diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -129,8 +129,8 @@ } PyDoc_STRVAR(builtin_compile__doc__, -"compile($module, /, source, filename, mode, flags=0, dont_inherit=0,\n" -" optimize=-1)\n" +"compile($module, /, source, filename, mode, flags=0,\n" +" dont_inherit=False, optimize=-1)\n" "--\n" "\n" "Compile source into a code object that can be executed by exec() or eval().\n" @@ -141,9 +141,9 @@ "single (interactive) statement, or \'eval\' to compile an expression.\n" "The flags argument, if present, controls which future statements influence\n" "the compilation of the code.\n" -"The dont_inherit argument, if non-zero, stops the compilation inheriting\n" +"The dont_inherit argument, if true, stops the compilation inheriting\n" "the effects of any future statements in effect in the code calling\n" -"compile; if absent or zero these statements do influence the compilation,\n" +"compile; if absent or false these statements do influence the compilation,\n" "in addition to any features explicitly specified."); #define BUILTIN_COMPILE_METHODDEF \ @@ -660,4 +660,4 @@ exit: return return_value; } -/*[clinic end generated code: output=9b34d1ca57effad8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bec3399c0aee98d7 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 10:48:36 2015 From: python-checkins at python.org (larry.hastings) Date: Sat, 30 May 2015 08:48:36 +0000 Subject: [Python-checkins] =?utf-8?q?release=3A_add-to-pydotorg=2Epy_now_d?= =?utf-8?q?etects_if_two_files_have_the_same_slug=2C_and_if_so?= Message-ID: <20150530084835.83479.85302@psf.io> https://hg.python.org/release/rev/e928125072aa changeset: 98:e928125072aa user: Larry Hastings date: Sat May 30 01:48:32 2015 -0700 summary: add-to-pydotorg.py now detects if two files have the same slug, and if so reports an error without changing anything (including deleting the previous downloadable files). files: add-to-pydotorg.py | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/add-to-pydotorg.py b/add-to-pydotorg.py --- a/add-to-pydotorg.py +++ b/add-to-pydotorg.py @@ -191,14 +191,20 @@ rel_pk = query_object('release', name='Python+' + rel) print 'Found Release object: id =', rel_pk n = 0 + file_dicts = {} + for rfile, file_desc, os_pk, add_desc in list_files(rel): + print 'Creating ReleaseFile object for', rfile + file_dict = build_file_dict(rel, rfile, rel_pk, file_desc, os_pk, add_desc) + key = file_dict['slug'] + if key in file_dicts: + raise RuntimeError('duplicate slug generated: %s' % key) + file_dicts[key] = file_dict print 'Deleting previous release files' resp = requests.delete(base_url + 'downloads/release_file/?release=%s' % rel_pk, headers=headers) if resp.status_code != 204: raise RuntimeError('deleting previous releases failed: %s' % resp.status_code) - for rfile, file_desc, os_pk, add_desc in list_files(rel): - print 'Creating ReleaseFile object for', rfile - file_dict = build_file_dict(rel, rfile, rel_pk, file_desc, os_pk, add_desc) + for file_dict in file_dicts.values(): file_pk = post_object('release_file', file_dict) if file_pk >= 0: print 'Created as id =', file_pk -- Repository URL: https://hg.python.org/release From solipsis at pitrou.net Sat May 30 10:50:13 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 30 May 2015 08:50:13 +0000 Subject: [Python-checkins] Daily reference leaks (4a8bee4fe050): sum=226 Message-ID: <20150530085013.25413.59640@psf.io> results for 4a8bee4fe050 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghkCphI', '--timeout', '7200'] From python-checkins at python.org Sat May 30 14:51:53 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 12:51:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Use_test=2Esupport=2Estart=5Fthreads=28=29_in_threaded_l?= =?utf-8?q?ru=5Fcache_tests=2E?= Message-ID: <20150530125153.83497.33699@psf.io> https://hg.python.org/cpython/rev/ab5aaeaee5ac changeset: 96374:ab5aaeaee5ac parent: 96372:2acc30d24edc parent: 96373:6cce19c280df user: Serhiy Storchaka date: Sat May 30 15:49:42 2015 +0300 summary: Use test.support.start_threads() in threaded lru_cache tests. files: Lib/test/test_functools.py | 27 ++++++++----------------- 1 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1120,14 +1120,10 @@ sys.setswitchinterval(1e-6) try: # create 5 threads in order to fill cache - threads = [] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() + threads = [threading.Thread(target=full, args=[f, k, k]) + for k in range(5)] + with support.start_threads(threads): + pass hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(hits, 45) @@ -1135,16 +1131,11 @@ self.assertEqual(currsize, 5) # create 5 threads in order to fill cache and 1 to clear it - cleaner = threading.Thread(target=clear, args=[f]) - cleaner.start() - threads = [cleaner] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() + threads = [threading.Thread(target=clear, args=[f])] + threads += [threading.Thread(target=full, args=[f, k, k]) + for k in range(5)] + with support.start_threads(threads): + pass finally: sys.setswitchinterval(orig_si) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 14:51:52 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 12:51:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogVXNlIHRlc3Quc3Vw?= =?utf-8?q?port=2Estart=5Fthreads=28=29_in_threaded_lru=5Fcache_tests=2E?= Message-ID: <20150530125152.27666.8063@psf.io> https://hg.python.org/cpython/rev/6cce19c280df changeset: 96373:6cce19c280df branch: 3.5 parent: 96371:f0487d3db275 user: Serhiy Storchaka date: Sat May 30 15:49:17 2015 +0300 summary: Use test.support.start_threads() in threaded lru_cache tests. files: Lib/test/test_functools.py | 27 ++++++++----------------- 1 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1120,14 +1120,10 @@ sys.setswitchinterval(1e-6) try: # create 5 threads in order to fill cache - threads = [] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() + threads = [threading.Thread(target=full, args=[f, k, k]) + for k in range(5)] + with support.start_threads(threads): + pass hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(hits, 45) @@ -1135,16 +1131,11 @@ self.assertEqual(currsize, 5) # create 5 threads in order to fill cache and 1 to clear it - cleaner = threading.Thread(target=clear, args=[f]) - cleaner.start() - threads = [cleaner] - for k in range(5): - t = threading.Thread(target=full, args=[f, k, k]) - t.start() - threads.append(t) - - for t in threads: - t.join() + threads = [threading.Thread(target=clear, args=[f])] + threads += [threading.Thread(target=full, args=[f, k, k]) + for k in range(5)] + with support.start_threads(threads): + pass finally: sys.setswitchinterval(orig_si) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:49:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 14:49:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MTE1?= =?utf-8?q?=3A_Update_uses_of_PyObject=5FIsTrue=28=29=2C_PyObject=5FNot=28?= =?utf-8?b?KSw=?= Message-ID: <20150530144926.89791.59556@psf.io> https://hg.python.org/cpython/rev/82490d05f3b0 changeset: 96375:82490d05f3b0 branch: 2.7 parent: 96355:418ab34fd1ce user: Serhiy Storchaka date: Sat May 30 17:45:12 2015 +0300 summary: Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. files: Misc/NEWS | 4 ++ Modules/_json.c | 35 ++++++++++++++++----- Modules/threadmodule.c | 18 +++++++--- Objects/bytearrayobject.c | 10 ++++- Objects/setobject.c | 17 ++++++++-- Python/pythonrun.c | 43 +++++++++++++------------- 6 files changed, 83 insertions(+), 44 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), + PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() + to check for and handle errors correctly. + - Issue #4753: On compilers where it is supported, use "computed gotos" for bytecode dispatch in the interpreter. This improves interpretation performance. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -874,6 +874,9 @@ int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + pairs = PyList_New(0); if (pairs == NULL) return NULL; @@ -997,6 +1000,9 @@ int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + pairs = PyList_New(0); if (pairs == NULL) return NULL; @@ -1466,6 +1472,7 @@ Returns a new PyObject representation of the term. */ PyObject *res; + int strict; char *str = PyString_AS_STRING(pystr); Py_ssize_t length = PyString_GET_SIZE(pystr); if (idx < 0) { @@ -1479,10 +1486,11 @@ switch (str[idx]) { case '"': /* string */ + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; return scanstring_str(pystr, idx + 1, - PyString_AS_STRING(s->encoding), - PyObject_IsTrue(s->strict), - next_idx_ptr); + PyString_AS_STRING(s->encoding), strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1557,6 +1565,7 @@ Returns a new PyObject representation of the term. */ PyObject *res; + int strict; Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); Py_ssize_t length = PyUnicode_GET_SIZE(pystr); if (idx < 0) { @@ -1570,9 +1579,10 @@ switch (str[idx]) { case '"': /* string */ - return scanstring_unicode(pystr, idx + 1, - PyObject_IsTrue(s->strict), - next_idx_ptr); + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; + return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1825,14 +1835,19 @@ PyEncoderObject *s; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan; + PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj; + int allow_nan; assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, - &sort_keys, &skipkeys, &allow_nan)) + &sort_keys, &skipkeys, &allow_nan_obj)) + return -1; + + allow_nan = PyObject_IsTrue(allow_nan_obj); + if (allow_nan < 0) return -1; s->markers = markers; @@ -1844,7 +1859,7 @@ s->sort_keys = sort_keys; s->skipkeys = skipkeys; s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); - s->allow_nan = PyObject_IsTrue(allow_nan); + s->allow_nan = allow_nan; Py_INCREF(s->markers); Py_INCREF(s->defaultfn); @@ -2110,6 +2125,8 @@ if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); + if (skipkeys < 0) + goto bail; idx = 0; while ((key = PyIter_Next(it)) != NULL) { PyObject *encoded; diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c --- a/Modules/threadmodule.c +++ b/Modules/threadmodule.c @@ -333,12 +333,18 @@ "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; + if (type->tp_init == PyBaseObject_Type.tp_init) { + int rc = 0; + if (args != NULL) + rc = PyObject_IsTrue(args); + if (rc == 0 && kw != NULL) + rc = PyObject_IsTrue(kw); + if (rc != 0) { + if (rc > 0) + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } } self = (localobject *)type->tp_alloc(type, 0); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1021,14 +1021,18 @@ Py_buffer self_bytes, other_bytes; PyObject *res; Py_ssize_t minsize; - int cmp; + int cmp, rc; /* Bytes can be compared to anything that supports the (binary) buffer API. Except that a comparison with Unicode is always an error, even if the comparison is for equality. */ #ifdef Py_USING_UNICODE - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (Py_BytesWarningFlag && op == Py_EQ) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1548,9 +1548,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { setentry entrycopy; + int rv; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { + rv = _PyDict_Contains(other, entry->key, entry->hash); + if (rv < 0) { + Py_DECREF(result); + return NULL; + } + if (!rv) { if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { Py_DECREF(result); return NULL; @@ -1793,7 +1799,8 @@ static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; + PyObject *r1; + int r2; if(!PyAnySet_Check(w)) { Py_INCREF(Py_NotImplemented); @@ -1812,9 +1819,11 @@ r1 = set_richcompare(v, w, Py_EQ); if (r1 == NULL) return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); + r2 = PyObject_IsTrue(r1); Py_DECREF(r1); - return r2; + if (r2 < 0) + return NULL; + return PyBool_FromLong(!r2); case Py_LE: return set_issubset(v, w); case Py_GE: diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -137,6 +137,20 @@ return flag; } +static int +isatty_no_error(PyObject *sys_stream) +{ + PyObject *sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); + if (sys_isatty) { + int isatty = PyObject_IsTrue(sys_isatty); + Py_DECREF(sys_isatty); + if (isatty >= 0) + return isatty; + } + PyErr_Clear(); + return 0; +} + void Py_InitializeEx(int install_sigs) { @@ -150,7 +164,7 @@ char *errors = NULL; int free_codeset = 0; int overridden = 0; - PyObject *sys_stream, *sys_isatty; + PyObject *sys_stream; #if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET) char *saved_locale, *loc_codeset; #endif @@ -336,40 +350,25 @@ if (codeset) { sys_stream = PySys_GetObject("stdin"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if ((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, icodeset, errors)) Py_FatalError("Cannot set codeset of stdin"); } - Py_XDECREF(sys_isatty); sys_stream = PySys_GetObject("stdout"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if ((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors)) Py_FatalError("Cannot set codeset of stdout"); } - Py_XDECREF(sys_isatty); sys_stream = PySys_GetObject("stderr"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors)) Py_FatalError("Cannot set codeset of stderr"); } - Py_XDECREF(sys_isatty); if (free_codeset) free(codeset); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:49:26 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 14:49:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTE1?= =?utf-8?q?=3A_Update_uses_of_PyObject=5FIsTrue=28=29=2C_PyObject=5FNot=28?= =?utf-8?b?KSw=?= Message-ID: <20150530144926.18670.17474@psf.io> https://hg.python.org/cpython/rev/8167df7d4cd0 changeset: 96376:8167df7d4cd0 branch: 3.4 parent: 96354:800a55c20b56 user: Serhiy Storchaka date: Sat May 30 17:45:22 2015 +0300 summary: Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. files: Misc/NEWS | 4 ++++ Modules/_json.c | 24 +++++++++++++++++------- Modules/_threadmodule.c | 18 ++++++++++++------ Modules/faulthandler.c | 4 ++-- Objects/bytearrayobject.c | 10 +++++++--- Objects/bytesobject.c | 20 +++++++++++++------- Objects/rangeobject.c | 5 ++++- Objects/setobject.c | 17 +++++++++++++---- Python/codecs.c | 11 ++++++----- Python/import.c | 6 +++++- 10 files changed, 83 insertions(+), 36 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), + PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() + to check for and handle errors correctly. + - Issue #24257: Fixed system error in the comparison of faked types.SimpleNamespace. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -595,6 +595,9 @@ int has_pairs_hook = (s->object_pairs_hook != Py_None); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + if (PyUnicode_READY(pystr) == -1) return NULL; @@ -940,6 +943,7 @@ void *str; int kind; Py_ssize_t length; + int strict; if (PyUnicode_READY(pystr) == -1) return NULL; @@ -960,9 +964,10 @@ switch (PyUnicode_READ(kind, str, idx)) { case '"': /* string */ - return scanstring_unicode(pystr, idx + 1, - PyObject_IsTrue(s->strict), - next_idx_ptr); + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; + return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1212,12 +1217,13 @@ PyEncoderObject *s; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan; + PyObject *item_separator, *sort_keys, *skipkeys; + int allow_nan; assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; @@ -1231,7 +1237,7 @@ s->sort_keys = sort_keys; s->skipkeys = skipkeys; s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); - s->allow_nan = PyObject_IsTrue(allow_nan); + s->allow_nan = allow_nan; Py_INCREF(s->markers); Py_INCREF(s->defaultfn); @@ -1500,6 +1506,7 @@ PyObject *items; PyObject *item = NULL; int skipkeys; + int sortkeys; Py_ssize_t idx; if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { @@ -1544,13 +1551,16 @@ items = PyMapping_Items(dct); if (items == NULL) goto bail; - if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + sortkeys = PyObject_IsTrue(s->sort_keys); + if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0)) goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); + if (skipkeys < 0) + goto bail; idx = 0; while ((item = PyIter_Next(it)) != NULL) { PyObject *encoded, *key, *value; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -718,12 +718,18 @@ "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; + if (type->tp_init == PyBaseObject_Type.tp_init) { + int rc = 0; + if (args != NULL) + rc = PyObject_IsTrue(args); + if (rc == 0 && kw != NULL) + rc = PyObject_IsTrue(kw); + if (rc != 0) { + if (rc > 0) + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } } self = (localobject *)type->tp_alloc(type, 0); diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1087,8 +1087,8 @@ has_key = PyDict_Contains(xoptions, key); Py_DECREF(key); - if (!has_key) - return 0; + if (has_key <= 0) + return has_key; } module = PyImport_ImportModule("faulthandler"); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -974,13 +974,17 @@ Py_buffer self_bytes, other_bytes; PyObject *res; Py_ssize_t minsize; - int cmp; + int cmp, rc; /* Bytes can be compared to anything that supports the (binary) buffer API. Except that a comparison with Unicode is always an error, even if the comparison is for equality. */ - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -816,17 +816,23 @@ Py_ssize_t len_a, len_b; Py_ssize_t min_len; PyObject *result; + int rc; /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { - if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE) && - (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyUnicode_Type))) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and string", 1)) + if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { + rc = PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyUnicode_Type); + if (rc < 0) return NULL; + if (rc) { + if (PyErr_WarnEx(PyExc_BytesWarning, + "Comparison between bytes and string", 1)) + return NULL; + } } result = Py_NotImplemented; } diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -194,8 +194,11 @@ } /* if (lo >= hi), return length of 0. */ - if (PyObject_RichCompareBool(lo, hi, Py_GE) == 1) { + cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE); + if (cmp_result != 0) { Py_XDECREF(step); + if (cmp_result < 0) + return NULL; return PyLong_FromLong(0); } diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1569,9 +1569,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { setentry entrycopy; + int rv; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { + rv = _PyDict_Contains(other, entry->key, entry->hash); + if (rv < 0) { + Py_DECREF(result); + return NULL; + } + if (!rv) { if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { Py_DECREF(result); return NULL; @@ -1807,7 +1813,8 @@ static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; + PyObject *r1; + int r2; if(!PyAnySet_Check(w)) Py_RETURN_NOTIMPLEMENTED; @@ -1825,9 +1832,11 @@ r1 = set_richcompare(v, w, Py_EQ); if (r1 == NULL) return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); + r2 = PyObject_IsTrue(r1); Py_DECREF(r1); - return r2; + if (r2 < 0) + return NULL; + return PyBool_FromLong(!r2); case Py_LE: return set_issubset(v, w); case Py_GE: diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -549,12 +549,13 @@ } else { is_text_codec = PyObject_IsTrue(attr); Py_DECREF(attr); - if (!is_text_codec) { + if (is_text_codec <= 0) { Py_DECREF(codec); - PyErr_Format(PyExc_LookupError, - "'%.400s' is not a text encoding; " - "use %s to handle arbitrary codecs", - encoding, alternate_command); + if (!is_text_codec) + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding; " + "use %s to handle arbitrary codecs", + encoding, alternate_command); return NULL; } } diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1416,6 +1416,7 @@ PyObject *globals = NULL; PyObject *fromlist = NULL; PyInterpreterState *interp = PyThreadState_GET()->interp; + int has_from; /* Make sure to use default values so as to not have PyObject_CallMethodObjArgs() truncate the parameter list because of a @@ -1646,7 +1647,10 @@ } /* From now on we don't hold the import lock anymore. */ - if (PyObject_Not(fromlist)) { + has_from = PyObject_IsTrue(fromlist); + if (has_from < 0) + goto error; + if (!has_from) { if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { PyObject *front = NULL; PyObject *partition = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:49:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 14:49:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324115=3A_Update_uses_of_PyObject=5FIsTrue=28=29=2C_Py?= =?utf-8?b?T2JqZWN0X05vdCgpLA==?= Message-ID: <20150530144926.83477.41384@psf.io> https://hg.python.org/cpython/rev/7d1b81224c3b changeset: 96377:7d1b81224c3b branch: 3.5 parent: 96373:6cce19c280df parent: 96376:8167df7d4cd0 user: Serhiy Storchaka date: Sat May 30 17:48:19 2015 +0300 summary: Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. files: Misc/NEWS | 4 +++ Modules/_json.c | 24 +++++++++++++----- Modules/_threadmodule.c | 18 +++++++++---- Modules/faulthandler.c | 4 +- Objects/bytearrayobject.c | 10 +++++-- Objects/bytesobject.c | 33 ++++++++++++++++++--------- Objects/rangeobject.c | 5 +++- Objects/setobject.c | 17 ++++++++++--- Python/codecs.c | 11 ++++---- Python/import.c | 6 ++++- 10 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), + PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() + to check for and handle errors correctly. + - Issue #24328: Fix importing one character extension modules. - Issue #11205: In dictionary displays, evaluate the key before the value. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -710,6 +710,9 @@ int has_pairs_hook = (s->object_pairs_hook != Py_None); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + if (PyUnicode_READY(pystr) == -1) return NULL; @@ -1055,6 +1058,7 @@ void *str; int kind; Py_ssize_t length; + int strict; if (PyUnicode_READY(pystr) == -1) return NULL; @@ -1075,9 +1079,10 @@ switch (PyUnicode_READ(kind, str, idx)) { case '"': /* string */ - return scanstring_unicode(pystr, idx + 1, - PyObject_IsTrue(s->strict), - next_idx_ptr); + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; + return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1327,12 +1332,13 @@ PyEncoderObject *s; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan; + PyObject *item_separator, *sort_keys, *skipkeys; + int allow_nan; assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; @@ -1353,7 +1359,7 @@ s->fast_encode = f; } } - s->allow_nan = PyObject_IsTrue(allow_nan); + s->allow_nan = allow_nan; Py_INCREF(s->markers); Py_INCREF(s->defaultfn); @@ -1622,6 +1628,7 @@ PyObject *items; PyObject *item = NULL; int skipkeys; + int sortkeys; Py_ssize_t idx; if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { @@ -1666,13 +1673,16 @@ items = PyMapping_Items(dct); if (items == NULL) goto bail; - if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + sortkeys = PyObject_IsTrue(s->sort_keys); + if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0)) goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); + if (skipkeys < 0) + goto bail; idx = 0; while ((item = PyIter_Next(it)) != NULL) { PyObject *encoded, *key, *value; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -711,12 +711,18 @@ "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; + if (type->tp_init == PyBaseObject_Type.tp_init) { + int rc = 0; + if (args != NULL) + rc = PyObject_IsTrue(args); + if (rc == 0 && kw != NULL) + rc = PyObject_IsTrue(kw); + if (rc != 0) { + if (rc > 0) + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } } self = (localobject *)type->tp_alloc(type, 0); diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1115,8 +1115,8 @@ has_key = PyDict_Contains(xoptions, key); Py_DECREF(key); - if (!has_key) - return 0; + if (has_key <= 0) + return has_key; } module = PyImport_ImportModule("faulthandler"); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1011,13 +1011,17 @@ Py_buffer self_bytes, other_bytes; PyObject *res; Py_ssize_t minsize; - int cmp; + int cmp, rc; /* Bytes can be compared to anything that supports the (binary) buffer API. Except that a comparison with Unicode is always an error, even if the comparison is for equality. */ - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1419,25 +1419,36 @@ Py_ssize_t len_a, len_b; Py_ssize_t min_len; PyObject *result; + int rc; /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { - if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and string", 1)) + "Comparison between bytes and string", 1)) return NULL; } - else if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyLong_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyLong_Type)) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and int", 1)) + else { + rc = PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyLong_Type); + if (!rc) + rc = PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyLong_Type); + if (rc < 0) return NULL; + if (rc) { + if (PyErr_WarnEx(PyExc_BytesWarning, + "Comparison between bytes and int", 1)) + return NULL; + } } } result = Py_NotImplemented; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -194,8 +194,11 @@ } /* if (lo >= hi), return length of 0. */ - if (PyObject_RichCompareBool(lo, hi, Py_GE) == 1) { + cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE); + if (cmp_result != 0) { Py_XDECREF(step); + if (cmp_result < 0) + return NULL; return PyLong_FromLong(0); } diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1519,9 +1519,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { setentry entrycopy; + int rv; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { + rv = _PyDict_Contains(other, entry->key, entry->hash); + if (rv < 0) { + Py_DECREF(result); + return NULL; + } + if (!rv) { if (set_add_entry((PySetObject *)result, &entrycopy)) { Py_DECREF(result); return NULL; @@ -1757,7 +1763,8 @@ static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; + PyObject *r1; + int r2; if(!PyAnySet_Check(w)) Py_RETURN_NOTIMPLEMENTED; @@ -1775,9 +1782,11 @@ r1 = set_richcompare(v, w, Py_EQ); if (r1 == NULL) return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); + r2 = PyObject_IsTrue(r1); Py_DECREF(r1); - return r2; + if (r2 < 0) + return NULL; + return PyBool_FromLong(!r2); case Py_LE: return set_issubset(v, w); case Py_GE: diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -550,12 +550,13 @@ } else { is_text_codec = PyObject_IsTrue(attr); Py_DECREF(attr); - if (!is_text_codec) { + if (is_text_codec <= 0) { Py_DECREF(codec); - PyErr_Format(PyExc_LookupError, - "'%.400s' is not a text encoding; " - "use %s to handle arbitrary codecs", - encoding, alternate_command); + if (!is_text_codec) + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding; " + "use %s to handle arbitrary codecs", + encoding, alternate_command); return NULL; } } diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1366,6 +1366,7 @@ PyObject *globals = NULL; PyObject *fromlist = NULL; PyInterpreterState *interp = PyThreadState_GET()->interp; + int has_from; /* Make sure to use default values so as to not have PyObject_CallMethodObjArgs() truncate the parameter list because of a @@ -1596,7 +1597,10 @@ } /* From now on we don't hold the import lock anymore. */ - if (PyObject_Not(fromlist)) { + has_from = PyObject_IsTrue(fromlist); + if (has_from < 0) + goto error; + if (!has_from) { if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { PyObject *front = NULL; PyObject *partition = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:49:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 14:49:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324115=3A_Update_uses_of_PyObject=5FIsTrue=28=29?= =?utf-8?b?LCBQeU9iamVjdF9Ob3QoKSw=?= Message-ID: <20150530144927.91779.44425@psf.io> https://hg.python.org/cpython/rev/f5d1bb0c4192 changeset: 96378:f5d1bb0c4192 parent: 96374:ab5aaeaee5ac parent: 96377:7d1b81224c3b user: Serhiy Storchaka date: Sat May 30 17:48:54 2015 +0300 summary: Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. files: Misc/NEWS | 4 +++ Modules/_json.c | 24 +++++++++++++----- Modules/_threadmodule.c | 18 +++++++++---- Modules/faulthandler.c | 4 +- Objects/bytearrayobject.c | 10 +++++-- Objects/bytesobject.c | 33 ++++++++++++++++++--------- Objects/rangeobject.c | 5 +++- Objects/setobject.c | 17 ++++++++++--- Python/codecs.c | 11 ++++---- Python/import.c | 6 ++++- 10 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,10 @@ Core and Builtins ----------------- +- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), + PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() + to check for and handle errors correctly. + - Issue #24328: Fix importing one character extension modules. - Issue #11205: In dictionary displays, evaluate the key before the value. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -710,6 +710,9 @@ int has_pairs_hook = (s->object_pairs_hook != Py_None); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + if (PyUnicode_READY(pystr) == -1) return NULL; @@ -1055,6 +1058,7 @@ void *str; int kind; Py_ssize_t length; + int strict; if (PyUnicode_READY(pystr) == -1) return NULL; @@ -1075,9 +1079,10 @@ switch (PyUnicode_READ(kind, str, idx)) { case '"': /* string */ - return scanstring_unicode(pystr, idx + 1, - PyObject_IsTrue(s->strict), - next_idx_ptr); + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; + return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1327,12 +1332,13 @@ PyEncoderObject *s; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan; + PyObject *item_separator, *sort_keys, *skipkeys; + int allow_nan; assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOp:make_encoder", kwlist, &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, &sort_keys, &skipkeys, &allow_nan)) return -1; @@ -1353,7 +1359,7 @@ s->fast_encode = f; } } - s->allow_nan = PyObject_IsTrue(allow_nan); + s->allow_nan = allow_nan; Py_INCREF(s->markers); Py_INCREF(s->defaultfn); @@ -1622,6 +1628,7 @@ PyObject *items; PyObject *item = NULL; int skipkeys; + int sortkeys; Py_ssize_t idx; if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { @@ -1666,13 +1673,16 @@ items = PyMapping_Items(dct); if (items == NULL) goto bail; - if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0) + sortkeys = PyObject_IsTrue(s->sort_keys); + if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0)) goto bail; it = PyObject_GetIter(items); Py_DECREF(items); if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); + if (skipkeys < 0) + goto bail; idx = 0; while ((item = PyIter_Next(it)) != NULL) { PyObject *encoded, *key, *value; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -711,12 +711,18 @@ "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; + if (type->tp_init == PyBaseObject_Type.tp_init) { + int rc = 0; + if (args != NULL) + rc = PyObject_IsTrue(args); + if (rc == 0 && kw != NULL) + rc = PyObject_IsTrue(kw); + if (rc != 0) { + if (rc > 0) + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } } self = (localobject *)type->tp_alloc(type, 0); diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1115,8 +1115,8 @@ has_key = PyDict_Contains(xoptions, key); Py_DECREF(key); - if (!has_key) - return 0; + if (has_key <= 0) + return has_key; } module = PyImport_ImportModule("faulthandler"); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1011,13 +1011,17 @@ Py_buffer self_bytes, other_bytes; PyObject *res; Py_ssize_t minsize; - int cmp; + int cmp, rc; /* Bytes can be compared to anything that supports the (binary) buffer API. Except that a comparison with Unicode is always an error, even if the comparison is for equality. */ - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1419,25 +1419,36 @@ Py_ssize_t len_a, len_b; Py_ssize_t min_len; PyObject *result; + int rc; /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { - if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and string", 1)) + "Comparison between bytes and string", 1)) return NULL; } - else if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyLong_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyLong_Type)) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and int", 1)) + else { + rc = PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyLong_Type); + if (!rc) + rc = PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyLong_Type); + if (rc < 0) return NULL; + if (rc) { + if (PyErr_WarnEx(PyExc_BytesWarning, + "Comparison between bytes and int", 1)) + return NULL; + } } } result = Py_NotImplemented; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -194,8 +194,11 @@ } /* if (lo >= hi), return length of 0. */ - if (PyObject_RichCompareBool(lo, hi, Py_GE) == 1) { + cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE); + if (cmp_result != 0) { Py_XDECREF(step); + if (cmp_result < 0) + return NULL; return PyLong_FromLong(0); } diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1582,9 +1582,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { setentry entrycopy; + int rv; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { + rv = _PyDict_Contains(other, entry->key, entry->hash); + if (rv < 0) { + Py_DECREF(result); + return NULL; + } + if (!rv) { if (set_add_entry((PySetObject *)result, &entrycopy)) { Py_DECREF(result); return NULL; @@ -1820,7 +1826,8 @@ static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; + PyObject *r1; + int r2; if(!PyAnySet_Check(w)) Py_RETURN_NOTIMPLEMENTED; @@ -1838,9 +1845,11 @@ r1 = set_richcompare(v, w, Py_EQ); if (r1 == NULL) return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); + r2 = PyObject_IsTrue(r1); Py_DECREF(r1); - return r2; + if (r2 < 0) + return NULL; + return PyBool_FromLong(!r2); case Py_LE: return set_issubset(v, w); case Py_GE: diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -550,12 +550,13 @@ } else { is_text_codec = PyObject_IsTrue(attr); Py_DECREF(attr); - if (!is_text_codec) { + if (is_text_codec <= 0) { Py_DECREF(codec); - PyErr_Format(PyExc_LookupError, - "'%.400s' is not a text encoding; " - "use %s to handle arbitrary codecs", - encoding, alternate_command); + if (!is_text_codec) + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding; " + "use %s to handle arbitrary codecs", + encoding, alternate_command); return NULL; } } diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1366,6 +1366,7 @@ PyObject *globals = NULL; PyObject *fromlist = NULL; PyInterpreterState *interp = PyThreadState_GET()->interp; + int has_from; /* Make sure to use default values so as to not have PyObject_CallMethodObjArgs() truncate the parameter list because of a @@ -1596,7 +1597,10 @@ } /* From now on we don't hold the import lock anymore. */ - if (PyObject_Not(fromlist)) { + has_from = PyObject_IsTrue(fromlist); + if (has_from < 0) + goto error; + if (!has_from) { if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { PyObject *front = NULL; PyObject *partition = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:54:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 14:54:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_docs/whatsnew?= =?utf-8?q?=3A_Mention_OrderedDict_C_implementation?= Message-ID: <20150530145405.18159.55591@psf.io> https://hg.python.org/cpython/rev/5c818c93b998 changeset: 96379:5c818c93b998 branch: 3.5 parent: 96377:7d1b81224c3b user: Yury Selivanov date: Sat May 30 10:49:09 2015 -0400 summary: docs/whatsnew: Mention OrderedDict C implementation files: Doc/whatsnew/3.5.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -97,6 +97,10 @@ Significantly Improved Library Modules: +* :class:`collections.OrderedDict` is now implemented in C, which improves + its performance between 4x to 100x times. Contributed by Eric Snow in + :issue:`16991`. + * You may now pass bytes to the :mod:`tempfile` module's APIs and it will return the temporary pathname as bytes instead of str. It also accepts a value of ``None`` on parameters where only str was accepted in the past to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:54:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 14:54:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_3=2E5?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150530145405.27666.55597@psf.io> https://hg.python.org/cpython/rev/d0a97a87b1d1 changeset: 96380:d0a97a87b1d1 branch: 3.5 parent: 96379:5c818c93b998 parent: 96378:f5d1bb0c4192 user: Yury Selivanov date: Sat May 30 10:49:27 2015 -0400 summary: Merge 3.5 files: Doc/tutorial/interpreter.rst | 14 +- Doc/tutorial/stdlib.rst | 2 +- Doc/tutorial/stdlib2.rst | 2 +- Doc/whatsnew/3.6.rst | 166 ++ Doc/whatsnew/index.rst | 1 + Include/patchlevel.h | 8 +- Lib/string.py | 9 +- Lib/test/test_collections.py | 7 + Lib/test/test_dictviews.py | 22 + Lib/test/test_symbol.py | 45 + Misc/NEWS | 15 + Objects/setobject.c | 145 +- PC/example_nt/example.vcproj | 4 +- PC/pyconfig.h | 4 +- PC/python3.def | 1402 +++++++++++----------- PCbuild/prepare_ssl.bat | 4 +- README | 16 +- configure | 20 +- configure.ac | 2 +- 19 files changed, 1101 insertions(+), 787 deletions(-) diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -1,4 +1,4 @@ -.. _tut-using: +3.6.. _tut-using: **************************** Using the Python Interpreter @@ -10,13 +10,13 @@ Invoking the Interpreter ======================== -The Python interpreter is usually installed as :file:`/usr/local/bin/python3.5` +The Python interpreter is usually installed as :file:`/usr/local/bin/python3.6` on those machines where it is available; putting :file:`/usr/local/bin` in your Unix shell's search path makes it possible to start it by typing the command: .. code-block:: text - python3.5 + python3.6 to the shell. [#]_ Since the choice of the directory where the interpreter lives is an installation option, other places are possible; check with your local @@ -24,11 +24,11 @@ popular alternative location.) On Windows machines, the Python installation is usually placed in -:file:`C:\\Python35`, though you can change this when you're running the +:file:`C:\\Python36`, though you can change this when you're running the installer. To add this directory to your path, you can type the following command into the command prompt in a DOS box:: - set path=%path%;C:\python35 + set path=%path%;C:\python36 Typing an end-of-file character (:kbd:`Control-D` on Unix, :kbd:`Control-Z` on Windows) at the primary prompt causes the interpreter to exit with a zero exit @@ -96,8 +96,8 @@ prints a welcome message stating its version number and a copyright notice before printing the first prompt:: - $ python3.5 - Python 3.5 (default, Sep 16 2015, 09:25:04) + $ python3.6 + Python 3.6 (default, Sep 16 2015, 09:25:04) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -15,7 +15,7 @@ >>> import os >>> os.getcwd() # Return the current working directory - 'C:\\Python35' + 'C:\\Python36' >>> os.chdir('/server/accesslogs') # Change current working directory >>> os.system('mkdir today') # Run the command mkdir in the system shell 0 diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst --- a/Doc/tutorial/stdlib2.rst +++ b/Doc/tutorial/stdlib2.rst @@ -277,7 +277,7 @@ Traceback (most recent call last): File "", line 1, in d['primary'] # entry was automatically removed - File "C:/python35/lib/weakref.py", line 46, in __getitem__ + File "C:/python36/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst new file mode 100644 --- /dev/null +++ b/Doc/whatsnew/3.6.rst @@ -0,0 +1,166 @@ +**************************** + What's New In Python 3.6 +**************************** + +:Release: |release| +:Date: |today| + +.. Rules for maintenance: + + * Anyone can add text to this document. Do not spend very much time + on the wording of your changes, because your text will probably + get rewritten to some degree. + + * The maintainer will go through Misc/NEWS periodically and add + changes; it's therefore more important to add your changes to + Misc/NEWS than to this file. + + * This is not a complete list of every single change; completeness + is the purpose of Misc/NEWS. Some changes I consider too small + or esoteric to include. If such a change is added to the text, + I'll just remove it. (This is another reason you shouldn't spend + too much time on writing your addition.) + + * If you want to draw your new text to the attention of the + maintainer, add 'XXX' to the beginning of the paragraph or + section. + + * It's OK to just add a fragmentary note about a change. For + example: "XXX Describe the transmogrify() function added to the + socket module." The maintainer will research the change and + write the necessary text. + + * You can comment out your additions if you like, but it's not + necessary (especially when a final release is some months away). + + * Credit the author of a patch or bugfix. Just the name is + sufficient; the e-mail address isn't necessary. + + * It's helpful to add the bug/patch number as a comment: + + XXX Describe the transmogrify() function added to the socket + module. + (Contributed by P.Y. Developer in :issue:`12345`.) + + This saves the maintainer the effort of going through the Mercurial log + when researching a change. + +This article explains the new features in Python 3.6, compared to 3.5. + +For full details, see the :source:`Misc/NEWS` file. + +.. note:: + + Prerelease users should be aware that this document is currently in draft + form. It will be updated substantially as Python 3.6 moves towards release, + so it's worth checking back even after reading earlier versions. + + +Summary -- Release highlights +============================= + +.. This section singles out the most important changes in Python 3.6. + Brevity is key. + +* None yet. + +.. PEP-sized items next. + +.. _pep-4XX: + +.. PEP 4XX: Virtual Environments +.. ============================= + + +.. (Implemented by Foo Bar.) + +.. .. seealso:: + + :pep:`4XX` - Python Virtual Environments + PEP written by Carl Meyer + + +Other Language Changes +====================== + +* None yet. + + +New Modules +=========== + +* None yet. + + +Improved Modules +================ + +* None yet. + + +Optimizations +============= + +* None yet. + + +Build and C API Changes +======================= + +* None yet. + + +Deprecated +========== + +New Keywords +------------ + +``async`` and ``await`` are not recommended to be used as variable, class or +function names. Introduced by :pep:`492` in Python 3.5, they will become +proper keywords in Python 3.7. + + +Deprecated Python modules, functions and methods +------------------------------------------------ + +* None yet. + + +Deprecated functions and types of the C API +------------------------------------------- + +* None yet. + + +Deprecated features +------------------- + +* None yet. + + +Removed +======= + +API and Feature Removals +------------------------ + +* None yet. + + +Porting to Python 3.6 +===================== + +This section lists previously described changes and other bugfixes +that may require changes to your code. + +Changes in the Python API +------------------------- + +* None yet. + + +Changes in the C API +-------------------- + +* None yet. diff --git a/Doc/whatsnew/index.rst b/Doc/whatsnew/index.rst --- a/Doc/whatsnew/index.rst +++ b/Doc/whatsnew/index.rst @@ -11,6 +11,7 @@ .. toctree:: :maxdepth: 2 + 3.6.rst 3.5.rst 3.4.rst 3.3.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -17,13 +17,13 @@ /* Version parsed out into numeric values */ /*--start constants--*/ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 5 +#define PY_MINOR_VERSION 6 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.5.0b1+" +#define PY_VERSION "3.6.0a0" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/string.py b/Lib/string.py --- a/Lib/string.py +++ b/Lib/string.py @@ -112,10 +112,7 @@ # Check the most common path first. named = mo.group('named') or mo.group('braced') if named is not None: - val = mapping[named] - # We use this idiom instead of str() because the latter will - # fail if val is a Unicode containing non-ASCII characters. - return '%s' % (val,) + return str(mapping[named]) if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: @@ -142,9 +139,7 @@ named = mo.group('named') or mo.group('braced') if named is not None: try: - # We use this idiom instead of str() because the latter - # will fail if val is a Unicode containing non-ASCII - return '%s' % (mapping[named],) + return str(mapping[named]) except KeyError: return mo.group() if mo.group('escaped') is not None: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1965,7 +1965,14 @@ od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) + def test_views(self): OrderedDict = self.module.OrderedDict + # See http://bugs.python.org/issue24286 + s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() + od = OrderedDict.fromkeys(s) + self.assertEqual(od.keys(), dict(od).keys()) + self.assertEqual(od.items(), dict(od).items()) + def test_override_update(self): OrderedDict = self.module.OrderedDict # Verify that subclasses can override update() without breaking __init__() diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,3 +1,4 @@ +import collections import unittest class DictSetTest(unittest.TestCase): @@ -197,6 +198,27 @@ d[42] = d.values() self.assertRaises(RuntimeError, repr, d) + def test_abc_registry(self): + d = dict(a=1) + + self.assertIsInstance(d.keys(), collections.KeysView) + self.assertIsInstance(d.keys(), collections.MappingView) + self.assertIsInstance(d.keys(), collections.Set) + self.assertIsInstance(d.keys(), collections.Sized) + self.assertIsInstance(d.keys(), collections.Iterable) + self.assertIsInstance(d.keys(), collections.Container) + + self.assertIsInstance(d.values(), collections.ValuesView) + self.assertIsInstance(d.values(), collections.MappingView) + self.assertIsInstance(d.values(), collections.Sized) + + self.assertIsInstance(d.items(), collections.ItemsView) + self.assertIsInstance(d.items(), collections.MappingView) + self.assertIsInstance(d.items(), collections.Set) + self.assertIsInstance(d.items(), collections.Sized) + self.assertIsInstance(d.items(), collections.Iterable) + self.assertIsInstance(d.items(), collections.Container) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_symbol.py b/Lib/test/test_symbol.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_symbol.py @@ -0,0 +1,45 @@ +import unittest +from test import support +import filecmp +import os +import sys +import subprocess + + +SYMBOL_FILE = support.findfile('symbol.py') +GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), + '..', '..', 'Include', 'graminit.h') +TEST_PY_FILE = 'symbol_test.py' + + +class TestSymbolGeneration(unittest.TestCase): + + def _copy_file_without_generated_symbols(self, source_file, dest_file): + with open(source_file, 'rb') as fp: + lines = fp.readlines() + nl = lines[0][len(lines[0].rstrip()):] + with open(dest_file, 'wb') as fp: + fp.writelines(lines[:lines.index(b"#--start constants--" + nl) + 1]) + fp.writelines(lines[lines.index(b"#--end constants--" + nl):]) + + def _generate_symbols(self, grammar_file, target_symbol_py_file): + proc = subprocess.Popen([sys.executable, + SYMBOL_FILE, + grammar_file, + target_symbol_py_file], stderr=subprocess.PIPE) + stderr = proc.communicate()[1] + return proc.returncode, stderr + + @unittest.skipIf(not os.path.exists(GRAMMAR_FILE), + 'test only works from source build directory') + def test_real_grammar_and_symbol_file(self): + self._copy_file_without_generated_symbols(SYMBOL_FILE, TEST_PY_FILE) + self.addCleanup(support.unlink, TEST_PY_FILE) + self.assertFalse(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) + self.assertEqual((0, b''), self._generate_symbols(GRAMMAR_FILE, + TEST_PY_FILE)) + self.assertTrue(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.6.0 alpha 1? +=================================== + +Release date: XXXX-XX-XX + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 beta 2? ================================== @@ -43,6 +55,9 @@ - Issue #24268: PEP 489: Multi-phase extension module initialization. Patch by Petr Viktorin. +- Issue #23359: Optimize set object internals by specializing the + hash table search into a lookup function and an insert function. + - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -52,7 +52,6 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; - setentry *freeslot = NULL; setentry *entry; size_t perturb = hash; size_t mask = so->mask; @@ -86,14 +85,12 @@ return entry; mask = so->mask; /* help avoid a register spill */ } - if (entry->hash == -1 && freeslot == NULL) - freeslot = entry; if (i + LINEAR_PROBES <= mask) { for (j = 0 ; j < LINEAR_PROBES ; j++) { entry++; - if (entry->key == NULL) - goto found_null; + if (entry->hash == 0 && entry->key == NULL) + return entry; if (entry->hash == hash) { PyObject *startkey = entry->key; assert(startkey != dummy); @@ -114,6 +111,89 @@ return entry; mask = so->mask; } + } + } + + perturb >>= PERTURB_SHIFT; + i = (i * 5 + 1 + perturb) & mask; + + entry = &table[i]; + if (entry->hash == 0 && entry->key == NULL) + return entry; + } +} + +/* +Internal routine to insert a new key into the table. +Used by the public insert routine. +Eats a reference to key. +*/ +static int +set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) +{ + setentry *table = so->table; + setentry *freeslot = NULL; + setentry *entry; + size_t perturb = hash; + size_t mask = so->mask; + size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */ + size_t j; + int cmp; + + entry = &table[i]; + if (entry->key == NULL) + goto found_null; + + while (1) { + if (entry->hash == hash) { + PyObject *startkey = entry->key; + /* startkey cannot be a dummy because the dummy hash field is -1 */ + assert(startkey != dummy); + if (startkey == key) + goto found_active; + if (PyUnicode_CheckExact(startkey) + && PyUnicode_CheckExact(key) + && unicode_eq(startkey, key)) + goto found_active; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) /* unlikely */ + return -1; + if (table != so->table || entry->key != startkey) /* unlikely */ + return set_insert_key(so, key, hash); + if (cmp > 0) /* likely */ + goto found_active; + mask = so->mask; /* help avoid a register spill */ + } + if (entry->hash == -1 && freeslot == NULL) + freeslot = entry; + + if (i + LINEAR_PROBES <= mask) { + for (j = 0 ; j < LINEAR_PROBES ; j++) { + entry++; + if (entry->hash == 0 && entry->key == NULL) + goto found_null; + if (entry->hash == hash) { + PyObject *startkey = entry->key; + assert(startkey != dummy); + if (startkey == key) + goto found_active; + if (PyUnicode_CheckExact(startkey) + && PyUnicode_CheckExact(key) + && unicode_eq(startkey, key)) + goto found_active; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) + return -1; + if (table != so->table || entry->key != startkey) + return set_insert_key(so, key, hash); + if (cmp > 0) + goto found_active; + mask = so->mask; + } if (entry->hash == -1 && freeslot == NULL) freeslot = entry; } @@ -123,11 +203,26 @@ i = (i * 5 + 1 + perturb) & mask; entry = &table[i]; - if (entry->key == NULL) + if (entry->hash == 0 && entry->key == NULL) goto found_null; } + found_null: - return freeslot == NULL ? entry : freeslot; + if (freeslot == NULL) { + /* UNUSED */ + so->fill++; + } else { + /* DUMMY */ + entry = freeslot; + } + so->used++; + entry->key = key; + entry->hash = hash; + return 0; + + found_active: + Py_DECREF(key); + return 0; } /* @@ -172,38 +267,6 @@ /* ======== End logic for probing the hash table ========================== */ /* ======================================================================== */ - -/* -Internal routine to insert a new key into the table. -Used by the public insert routine. -Eats a reference to key. -*/ -static int -set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) -{ - setentry *entry; - - entry = set_lookkey(so, key, hash); - if (entry == NULL) - return -1; - if (entry->key == NULL) { - /* UNUSED */ - entry->key = key; - entry->hash = hash; - so->fill++; - so->used++; - } else if (entry->key == dummy) { - /* DUMMY */ - entry->key = key; - entry->hash = hash; - so->used++; - } else { - /* ACTIVE */ - Py_DECREF(key); - } - return 0; -} - /* Restructure the table by allocating a new table and reinserting all keys again. When entries have been deleted, the new table may @@ -345,7 +408,7 @@ entry = set_lookkey(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; - if (entry->key == NULL || entry->key == dummy) + if (entry->key == NULL) return DISCARD_NOTFOUND; old_key = entry->key; entry->key = dummy; @@ -623,7 +686,7 @@ if (lu_entry == NULL) return -1; key = lu_entry->key; - return key != NULL && key != dummy; + return key != NULL; } static int diff --git a/PC/example_nt/example.vcproj b/PC/example_nt/example.vcproj --- a/PC/example_nt/example.vcproj +++ b/PC/example_nt/example.vcproj @@ -39,7 +39,7 @@ . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='python' PACKAGE_TARNAME='python' -PACKAGE_VERSION='3.5' -PACKAGE_STRING='python 3.5' +PACKAGE_VERSION='3.6' +PACKAGE_STRING='python 3.6' PACKAGE_BUGREPORT='http://bugs.python.org/' PACKAGE_URL='' @@ -1378,7 +1378,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures python 3.5 to adapt to many kinds of systems. +\`configure' configures python 3.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1443,7 +1443,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of python 3.5:";; + short | recursive ) echo "Configuration of python 3.6:";; esac cat <<\_ACEOF @@ -1597,7 +1597,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -python configure 3.5 +python configure 3.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2436,7 +2436,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by python $as_me 3.5, which was +It was created by python $as_me 3.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3009,7 +3009,7 @@ mv confdefs.h.new confdefs.h -VERSION=3.5 +VERSION=3.6 # Version number of Python's own shared library file. @@ -16540,7 +16540,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by python $as_me 3.5, which was +This file was extended by python $as_me 3.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16602,7 +16602,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -python config.status 3.5 +python config.status 3.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *********************************************** # Set VERSION so we only need to edit in one place (i.e., here) -m4_define(PYTHON_VERSION, 3.5) +m4_define(PYTHON_VERSION, 3.6) AC_PREREQ(2.65) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:59:15 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 14:59:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150530145915.83479.36519@psf.io> https://hg.python.org/cpython/rev/596458a04782 changeset: 96382:596458a04782 parent: 96378:f5d1bb0c4192 parent: 96381:1c11e0de934a user: Yury Selivanov date: Sat May 30 10:59:09 2015 -0400 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 16:59:15 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 14:59:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Reverting_my_p?= =?utf-8?q?revious_commit=2E?= Message-ID: <20150530145915.83473.93677@psf.io> https://hg.python.org/cpython/rev/1c11e0de934a changeset: 96381:1c11e0de934a branch: 3.5 user: Yury Selivanov date: Sat May 30 10:57:56 2015 -0400 summary: Reverting my previous commit. Something went horribly wrong when I was doing `hg rebase`. files: Doc/tutorial/interpreter.rst | 14 +- Doc/tutorial/stdlib.rst | 2 +- Doc/tutorial/stdlib2.rst | 2 +- Doc/whatsnew/3.6.rst | 166 -- Doc/whatsnew/index.rst | 1 - Include/patchlevel.h | 8 +- Lib/string.py | 9 +- Lib/test/test_collections.py | 7 - Lib/test/test_dictviews.py | 22 - Lib/test/test_symbol.py | 45 - Misc/NEWS | 15 - Objects/setobject.c | 145 +- PC/example_nt/example.vcproj | 4 +- PC/pyconfig.h | 4 +- PC/python3.def | 1402 +++++++++++----------- PCbuild/prepare_ssl.bat | 4 +- README | 16 +- configure | 20 +- configure.ac | 2 +- 19 files changed, 787 insertions(+), 1101 deletions(-) diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -1,4 +1,4 @@ -3.6.. _tut-using: +.. _tut-using: **************************** Using the Python Interpreter @@ -10,13 +10,13 @@ Invoking the Interpreter ======================== -The Python interpreter is usually installed as :file:`/usr/local/bin/python3.6` +The Python interpreter is usually installed as :file:`/usr/local/bin/python3.5` on those machines where it is available; putting :file:`/usr/local/bin` in your Unix shell's search path makes it possible to start it by typing the command: .. code-block:: text - python3.6 + python3.5 to the shell. [#]_ Since the choice of the directory where the interpreter lives is an installation option, other places are possible; check with your local @@ -24,11 +24,11 @@ popular alternative location.) On Windows machines, the Python installation is usually placed in -:file:`C:\\Python36`, though you can change this when you're running the +:file:`C:\\Python35`, though you can change this when you're running the installer. To add this directory to your path, you can type the following command into the command prompt in a DOS box:: - set path=%path%;C:\python36 + set path=%path%;C:\python35 Typing an end-of-file character (:kbd:`Control-D` on Unix, :kbd:`Control-Z` on Windows) at the primary prompt causes the interpreter to exit with a zero exit @@ -96,8 +96,8 @@ prints a welcome message stating its version number and a copyright notice before printing the first prompt:: - $ python3.6 - Python 3.6 (default, Sep 16 2015, 09:25:04) + $ python3.5 + Python 3.5 (default, Sep 16 2015, 09:25:04) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -15,7 +15,7 @@ >>> import os >>> os.getcwd() # Return the current working directory - 'C:\\Python36' + 'C:\\Python35' >>> os.chdir('/server/accesslogs') # Change current working directory >>> os.system('mkdir today') # Run the command mkdir in the system shell 0 diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst --- a/Doc/tutorial/stdlib2.rst +++ b/Doc/tutorial/stdlib2.rst @@ -277,7 +277,7 @@ Traceback (most recent call last): File "", line 1, in d['primary'] # entry was automatically removed - File "C:/python36/lib/weakref.py", line 46, in __getitem__ + File "C:/python35/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary' diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst deleted file mode 100644 --- a/Doc/whatsnew/3.6.rst +++ /dev/null @@ -1,166 +0,0 @@ -**************************** - What's New In Python 3.6 -**************************** - -:Release: |release| -:Date: |today| - -.. Rules for maintenance: - - * Anyone can add text to this document. Do not spend very much time - on the wording of your changes, because your text will probably - get rewritten to some degree. - - * The maintainer will go through Misc/NEWS periodically and add - changes; it's therefore more important to add your changes to - Misc/NEWS than to this file. - - * This is not a complete list of every single change; completeness - is the purpose of Misc/NEWS. Some changes I consider too small - or esoteric to include. If such a change is added to the text, - I'll just remove it. (This is another reason you shouldn't spend - too much time on writing your addition.) - - * If you want to draw your new text to the attention of the - maintainer, add 'XXX' to the beginning of the paragraph or - section. - - * It's OK to just add a fragmentary note about a change. For - example: "XXX Describe the transmogrify() function added to the - socket module." The maintainer will research the change and - write the necessary text. - - * You can comment out your additions if you like, but it's not - necessary (especially when a final release is some months away). - - * Credit the author of a patch or bugfix. Just the name is - sufficient; the e-mail address isn't necessary. - - * It's helpful to add the bug/patch number as a comment: - - XXX Describe the transmogrify() function added to the socket - module. - (Contributed by P.Y. Developer in :issue:`12345`.) - - This saves the maintainer the effort of going through the Mercurial log - when researching a change. - -This article explains the new features in Python 3.6, compared to 3.5. - -For full details, see the :source:`Misc/NEWS` file. - -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.6 moves towards release, - so it's worth checking back even after reading earlier versions. - - -Summary -- Release highlights -============================= - -.. This section singles out the most important changes in Python 3.6. - Brevity is key. - -* None yet. - -.. PEP-sized items next. - -.. _pep-4XX: - -.. PEP 4XX: Virtual Environments -.. ============================= - - -.. (Implemented by Foo Bar.) - -.. .. seealso:: - - :pep:`4XX` - Python Virtual Environments - PEP written by Carl Meyer - - -Other Language Changes -====================== - -* None yet. - - -New Modules -=========== - -* None yet. - - -Improved Modules -================ - -* None yet. - - -Optimizations -============= - -* None yet. - - -Build and C API Changes -======================= - -* None yet. - - -Deprecated -========== - -New Keywords ------------- - -``async`` and ``await`` are not recommended to be used as variable, class or -function names. Introduced by :pep:`492` in Python 3.5, they will become -proper keywords in Python 3.7. - - -Deprecated Python modules, functions and methods ------------------------------------------------- - -* None yet. - - -Deprecated functions and types of the C API -------------------------------------------- - -* None yet. - - -Deprecated features -------------------- - -* None yet. - - -Removed -======= - -API and Feature Removals ------------------------- - -* None yet. - - -Porting to Python 3.6 -===================== - -This section lists previously described changes and other bugfixes -that may require changes to your code. - -Changes in the Python API -------------------------- - -* None yet. - - -Changes in the C API --------------------- - -* None yet. diff --git a/Doc/whatsnew/index.rst b/Doc/whatsnew/index.rst --- a/Doc/whatsnew/index.rst +++ b/Doc/whatsnew/index.rst @@ -11,7 +11,6 @@ .. toctree:: :maxdepth: 2 - 3.6.rst 3.5.rst 3.4.rst 3.3.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -17,13 +17,13 @@ /* Version parsed out into numeric values */ /*--start constants--*/ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 6 +#define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 0 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.6.0a0" +#define PY_VERSION "3.5.0b1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/string.py b/Lib/string.py --- a/Lib/string.py +++ b/Lib/string.py @@ -112,7 +112,10 @@ # Check the most common path first. named = mo.group('named') or mo.group('braced') if named is not None: - return str(mapping[named]) + val = mapping[named] + # We use this idiom instead of str() because the latter will + # fail if val is a Unicode containing non-ASCII characters. + return '%s' % (val,) if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: @@ -139,7 +142,9 @@ named = mo.group('named') or mo.group('braced') if named is not None: try: - return str(mapping[named]) + # We use this idiom instead of str() because the latter + # will fail if val is a Unicode containing non-ASCII + return '%s' % (mapping[named],) except KeyError: return mo.group() if mo.group('escaped') is not None: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1965,14 +1965,7 @@ od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) - def test_views(self): OrderedDict = self.module.OrderedDict - # See http://bugs.python.org/issue24286 - s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() - od = OrderedDict.fromkeys(s) - self.assertEqual(od.keys(), dict(od).keys()) - self.assertEqual(od.items(), dict(od).items()) - def test_override_update(self): OrderedDict = self.module.OrderedDict # Verify that subclasses can override update() without breaking __init__() diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,4 +1,3 @@ -import collections import unittest class DictSetTest(unittest.TestCase): @@ -198,27 +197,6 @@ d[42] = d.values() self.assertRaises(RuntimeError, repr, d) - def test_abc_registry(self): - d = dict(a=1) - - self.assertIsInstance(d.keys(), collections.KeysView) - self.assertIsInstance(d.keys(), collections.MappingView) - self.assertIsInstance(d.keys(), collections.Set) - self.assertIsInstance(d.keys(), collections.Sized) - self.assertIsInstance(d.keys(), collections.Iterable) - self.assertIsInstance(d.keys(), collections.Container) - - self.assertIsInstance(d.values(), collections.ValuesView) - self.assertIsInstance(d.values(), collections.MappingView) - self.assertIsInstance(d.values(), collections.Sized) - - self.assertIsInstance(d.items(), collections.ItemsView) - self.assertIsInstance(d.items(), collections.MappingView) - self.assertIsInstance(d.items(), collections.Set) - self.assertIsInstance(d.items(), collections.Sized) - self.assertIsInstance(d.items(), collections.Iterable) - self.assertIsInstance(d.items(), collections.Container) - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_symbol.py b/Lib/test/test_symbol.py deleted file mode 100644 --- a/Lib/test/test_symbol.py +++ /dev/null @@ -1,45 +0,0 @@ -import unittest -from test import support -import filecmp -import os -import sys -import subprocess - - -SYMBOL_FILE = support.findfile('symbol.py') -GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), - '..', '..', 'Include', 'graminit.h') -TEST_PY_FILE = 'symbol_test.py' - - -class TestSymbolGeneration(unittest.TestCase): - - def _copy_file_without_generated_symbols(self, source_file, dest_file): - with open(source_file, 'rb') as fp: - lines = fp.readlines() - nl = lines[0][len(lines[0].rstrip()):] - with open(dest_file, 'wb') as fp: - fp.writelines(lines[:lines.index(b"#--start constants--" + nl) + 1]) - fp.writelines(lines[lines.index(b"#--end constants--" + nl):]) - - def _generate_symbols(self, grammar_file, target_symbol_py_file): - proc = subprocess.Popen([sys.executable, - SYMBOL_FILE, - grammar_file, - target_symbol_py_file], stderr=subprocess.PIPE) - stderr = proc.communicate()[1] - return proc.returncode, stderr - - @unittest.skipIf(not os.path.exists(GRAMMAR_FILE), - 'test only works from source build directory') - def test_real_grammar_and_symbol_file(self): - self._copy_file_without_generated_symbols(SYMBOL_FILE, TEST_PY_FILE) - self.addCleanup(support.unlink, TEST_PY_FILE) - self.assertFalse(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) - self.assertEqual((0, b''), self._generate_symbols(GRAMMAR_FILE, - TEST_PY_FILE)) - self.assertTrue(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) - - -if __name__ == "__main__": - unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,18 +2,6 @@ Python News +++++++++++ -What's New in Python 3.6.0 alpha 1? -=================================== - -Release date: XXXX-XX-XX - -Core and Builtins ------------------ - -Library -------- - - What's New in Python 3.5.0 beta 2? ================================== @@ -55,9 +43,6 @@ - Issue #24268: PEP 489: Multi-phase extension module initialization. Patch by Petr Viktorin. -- Issue #23359: Optimize set object internals by specializing the - hash table search into a lookup function and an insert function. - - Issue #23955: Add pyvenv.cfg option to suppress registry/environment lookup for generating sys.path on Windows. diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -52,6 +52,7 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; + setentry *freeslot = NULL; setentry *entry; size_t perturb = hash; size_t mask = so->mask; @@ -85,12 +86,14 @@ return entry; mask = so->mask; /* help avoid a register spill */ } + if (entry->hash == -1 && freeslot == NULL) + freeslot = entry; if (i + LINEAR_PROBES <= mask) { for (j = 0 ; j < LINEAR_PROBES ; j++) { entry++; - if (entry->hash == 0 && entry->key == NULL) - return entry; + if (entry->key == NULL) + goto found_null; if (entry->hash == hash) { PyObject *startkey = entry->key; assert(startkey != dummy); @@ -111,89 +114,6 @@ return entry; mask = so->mask; } - } - } - - perturb >>= PERTURB_SHIFT; - i = (i * 5 + 1 + perturb) & mask; - - entry = &table[i]; - if (entry->hash == 0 && entry->key == NULL) - return entry; - } -} - -/* -Internal routine to insert a new key into the table. -Used by the public insert routine. -Eats a reference to key. -*/ -static int -set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) -{ - setentry *table = so->table; - setentry *freeslot = NULL; - setentry *entry; - size_t perturb = hash; - size_t mask = so->mask; - size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */ - size_t j; - int cmp; - - entry = &table[i]; - if (entry->key == NULL) - goto found_null; - - while (1) { - if (entry->hash == hash) { - PyObject *startkey = entry->key; - /* startkey cannot be a dummy because the dummy hash field is -1 */ - assert(startkey != dummy); - if (startkey == key) - goto found_active; - if (PyUnicode_CheckExact(startkey) - && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) - goto found_active; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); - if (cmp < 0) /* unlikely */ - return -1; - if (table != so->table || entry->key != startkey) /* unlikely */ - return set_insert_key(so, key, hash); - if (cmp > 0) /* likely */ - goto found_active; - mask = so->mask; /* help avoid a register spill */ - } - if (entry->hash == -1 && freeslot == NULL) - freeslot = entry; - - if (i + LINEAR_PROBES <= mask) { - for (j = 0 ; j < LINEAR_PROBES ; j++) { - entry++; - if (entry->hash == 0 && entry->key == NULL) - goto found_null; - if (entry->hash == hash) { - PyObject *startkey = entry->key; - assert(startkey != dummy); - if (startkey == key) - goto found_active; - if (PyUnicode_CheckExact(startkey) - && PyUnicode_CheckExact(key) - && unicode_eq(startkey, key)) - goto found_active; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); - if (cmp < 0) - return -1; - if (table != so->table || entry->key != startkey) - return set_insert_key(so, key, hash); - if (cmp > 0) - goto found_active; - mask = so->mask; - } if (entry->hash == -1 && freeslot == NULL) freeslot = entry; } @@ -203,26 +123,11 @@ i = (i * 5 + 1 + perturb) & mask; entry = &table[i]; - if (entry->hash == 0 && entry->key == NULL) + if (entry->key == NULL) goto found_null; } - found_null: - if (freeslot == NULL) { - /* UNUSED */ - so->fill++; - } else { - /* DUMMY */ - entry = freeslot; - } - so->used++; - entry->key = key; - entry->hash = hash; - return 0; - - found_active: - Py_DECREF(key); - return 0; + return freeslot == NULL ? entry : freeslot; } /* @@ -267,6 +172,38 @@ /* ======== End logic for probing the hash table ========================== */ /* ======================================================================== */ + +/* +Internal routine to insert a new key into the table. +Used by the public insert routine. +Eats a reference to key. +*/ +static int +set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash) +{ + setentry *entry; + + entry = set_lookkey(so, key, hash); + if (entry == NULL) + return -1; + if (entry->key == NULL) { + /* UNUSED */ + entry->key = key; + entry->hash = hash; + so->fill++; + so->used++; + } else if (entry->key == dummy) { + /* DUMMY */ + entry->key = key; + entry->hash = hash; + so->used++; + } else { + /* ACTIVE */ + Py_DECREF(key); + } + return 0; +} + /* Restructure the table by allocating a new table and reinserting all keys again. When entries have been deleted, the new table may @@ -408,7 +345,7 @@ entry = set_lookkey(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; - if (entry->key == NULL) + if (entry->key == NULL || entry->key == dummy) return DISCARD_NOTFOUND; old_key = entry->key; entry->key = dummy; @@ -686,7 +623,7 @@ if (lu_entry == NULL) return -1; key = lu_entry->key; - return key != NULL; + return key != NULL && key != dummy; } static int diff --git a/PC/example_nt/example.vcproj b/PC/example_nt/example.vcproj --- a/PC/example_nt/example.vcproj +++ b/PC/example_nt/example.vcproj @@ -39,7 +39,7 @@ . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='python' PACKAGE_TARNAME='python' -PACKAGE_VERSION='3.6' -PACKAGE_STRING='python 3.6' +PACKAGE_VERSION='3.5' +PACKAGE_STRING='python 3.5' PACKAGE_BUGREPORT='http://bugs.python.org/' PACKAGE_URL='' @@ -1378,7 +1378,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures python 3.6 to adapt to many kinds of systems. +\`configure' configures python 3.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1443,7 +1443,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of python 3.6:";; + short | recursive ) echo "Configuration of python 3.5:";; esac cat <<\_ACEOF @@ -1597,7 +1597,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -python configure 3.6 +python configure 3.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2436,7 +2436,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by python $as_me 3.6, which was +It was created by python $as_me 3.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3009,7 +3009,7 @@ mv confdefs.h.new confdefs.h -VERSION=3.6 +VERSION=3.5 # Version number of Python's own shared library file. @@ -16540,7 +16540,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by python $as_me 3.6, which was +This file was extended by python $as_me 3.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16602,7 +16602,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -python config.status 3.6 +python config.status 3.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *********************************************** # Set VERSION so we only need to edit in one place (i.e., here) -m4_define(PYTHON_VERSION, 3.6) +m4_define(PYTHON_VERSION, 3.5) AC_PREREQ(2.65) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 17:36:04 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 15:36:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Use_PyObject=5FTypeCheck_instead_of_PyObject=5FIsInstance?= =?utf-8?q?=2E?= Message-ID: <20150530153604.24087.28454@psf.io> https://hg.python.org/cpython/rev/0a7380984e37 changeset: 96383:0a7380984e37 branch: 3.5 parent: 96381:1c11e0de934a user: Eric Snow date: Sat May 30 09:29:53 2015 -0600 summary: Issue #16991: Use PyObject_TypeCheck instead of PyObject_IsInstance. files: Include/dictobject.h | 6 +++--- Include/odictobject.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -45,9 +45,9 @@ #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) -#define PyDictKeys_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictKeys_Type)) -#define PyDictItems_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictItems_Type)) -#define PyDictValues_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictValues_Type)) +#define PyDictKeys_Check(op) PyObject_TypeCheck(op, &PyDictKeys_Type) +#define PyDictItems_Check(op) PyObject_TypeCheck(op, &PyDictItems_Type) +#define PyDictValues_Check(op) PyObject_TypeCheck(op, &PyDictValues_Type) /* This excludes Values, since they are not sets. */ # define PyDictViewSet_Check(op) \ (PyDictKeys_Check(op) || PyDictItems_Check(op)) diff --git a/Include/odictobject.h b/Include/odictobject.h --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -19,7 +19,7 @@ #endif /* Py_LIMITED_API */ -#define PyODict_Check(op) PyObject_IsInstance(op, (PyObject *)&PyODict_Type) +#define PyODict_Check(op) PyObject_TypeCheck(op, &PyODict_Type) #define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) #define PyODict_SIZE(op) ((PyDictObject *)op)->ma_used #define PyODict_HasKey(od, key) (PyMapping_HasKey(PyObject *)od, key) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 17:36:05 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 15:36:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530153605.91791.53765@psf.io> https://hg.python.org/cpython/rev/10eabadba316 changeset: 96384:10eabadba316 parent: 96382:596458a04782 parent: 96383:0a7380984e37 user: Eric Snow date: Sat May 30 09:34:28 2015 -0600 summary: Merge from 3.5. files: Include/dictobject.h | 6 +++--- Include/odictobject.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/dictobject.h b/Include/dictobject.h --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -45,9 +45,9 @@ #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) -#define PyDictKeys_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictKeys_Type)) -#define PyDictItems_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictItems_Type)) -#define PyDictValues_Check(op) (PyObject_IsInstance(op, (PyObject *)&PyDictValues_Type)) +#define PyDictKeys_Check(op) PyObject_TypeCheck(op, &PyDictKeys_Type) +#define PyDictItems_Check(op) PyObject_TypeCheck(op, &PyDictItems_Type) +#define PyDictValues_Check(op) PyObject_TypeCheck(op, &PyDictValues_Type) /* This excludes Values, since they are not sets. */ # define PyDictViewSet_Check(op) \ (PyDictKeys_Check(op) || PyDictItems_Check(op)) diff --git a/Include/odictobject.h b/Include/odictobject.h --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -19,7 +19,7 @@ #endif /* Py_LIMITED_API */ -#define PyODict_Check(op) PyObject_IsInstance(op, (PyObject *)&PyODict_Type) +#define PyODict_Check(op) PyObject_TypeCheck(op, &PyODict_Type) #define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) #define PyODict_SIZE(op) ((PyDictObject *)op)->ma_used #define PyODict_HasKey(od, key) (PyMapping_HasKey(PyObject *)od, key) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 18:46:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 16:46:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzU2MzM6?= =?utf-8?q?_Fixed_timeit_when_the_statement_is_a_string_and_the_setup_is_n?= =?utf-8?b?b3Qu?= Message-ID: <20150530164603.24083.76616@psf.io> https://hg.python.org/cpython/rev/89de73c0d848 changeset: 96386:89de73c0d848 branch: 3.4 parent: 96376:8167df7d4cd0 user: Serhiy Storchaka date: Sat May 30 19:38:26 2015 +0300 summary: Issue #5633: Fixed timeit when the statement is a string and the setup is not. files: Lib/test/test_timeit.py | 7 +++++++ Lib/timeit.py | 7 ++++--- Misc/NEWS | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -124,6 +124,9 @@ def test_timeit_callable_stmt(self): self.timeit(self.fake_callable_stmt, self.fake_setup, number=3) + def test_timeit_callable_setup(self): + self.timeit(self.fake_stmt, self.fake_callable_setup, number=3) + def test_timeit_callable_stmt_and_setup(self): self.timeit(self.fake_callable_stmt, self.fake_callable_setup, number=3) @@ -173,6 +176,10 @@ self.repeat(self.fake_callable_stmt, self.fake_setup, repeat=3, number=5) + def test_repeat_callable_setup(self): + self.repeat(self.fake_stmt, self.fake_callable_setup, + repeat=3, number=5) + def test_repeat_callable_stmt_and_setup(self): self.repeat(self.fake_callable_stmt, self.fake_callable_setup, repeat=3, number=5) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -65,7 +65,7 @@ # in Timer.__init__() depend on setup being indented 4 spaces and stmt # being indented 8 spaces. template = """ -def inner(_it, _timer): +def inner(_it, _timer{init}): {setup} _t0 = _timer() for _i in _it: @@ -119,9 +119,10 @@ stmt = reindent(stmt, 8) if isinstance(setup, str): setup = reindent(setup, 4) - src = template.format(stmt=stmt, setup=setup) + src = template.format(stmt=stmt, setup=setup, init='') elif callable(setup): - src = template.format(stmt=stmt, setup='_setup()') + src = template.format(stmt=stmt, setup='_setup()', + init=', _setup=_setup') ns['_setup'] = setup else: raise ValueError("setup is neither a string nor callable") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,8 @@ Library ------- +- Issue #5633: Fixed timeit when the statement is a string and the setup is not. + - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 18:46:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 16:46:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzU2MzM6?= =?utf-8?q?_Fixed_timeit_when_the_statement_is_a_string_and_the_setup_is_n?= =?utf-8?b?b3Qu?= Message-ID: <20150530164603.91785.49951@psf.io> https://hg.python.org/cpython/rev/14d1018940cb changeset: 96385:14d1018940cb branch: 2.7 parent: 96375:82490d05f3b0 user: Serhiy Storchaka date: Sat May 30 19:37:19 2015 +0300 summary: Issue #5633: Fixed timeit when the statement is a string and the setup is not. files: Lib/test/test_timeit.py | 7 +++++++ Lib/timeit.py | 7 ++++--- Misc/NEWS | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -120,6 +120,9 @@ def test_timeit_callable_stmt(self): self.timeit(self.fake_callable_stmt, self.fake_setup, number=3) + def test_timeit_callable_setup(self): + self.timeit(self.fake_stmt, self.fake_callable_setup, number=3) + def test_timeit_callable_stmt_and_setup(self): self.timeit(self.fake_callable_stmt, self.fake_callable_setup, number=3) @@ -169,6 +172,10 @@ self.repeat(self.fake_callable_stmt, self.fake_setup, repeat=3, number=5) + def test_repeat_callable_setup(self): + self.repeat(self.fake_stmt, self.fake_callable_setup, + repeat=3, number=5) + def test_repeat_callable_stmt_and_setup(self): self.repeat(self.fake_callable_stmt, self.fake_callable_setup, repeat=3, number=5) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -78,7 +78,7 @@ # in Timer.__init__() depend on setup being indented 4 spaces and stmt # being indented 8 spaces. template = """ -def inner(_it, _timer): +def inner(_it, _timer%(init)s): %(setup)s _t0 = _timer() for _i in _it: @@ -132,9 +132,10 @@ stmt = reindent(stmt, 8) if isinstance(setup, basestring): setup = reindent(setup, 4) - src = template % {'stmt': stmt, 'setup': setup} + src = template % {'stmt': stmt, 'setup': setup, 'init': ''} elif hasattr(setup, '__call__'): - src = template % {'stmt': stmt, 'setup': '_setup()'} + src = template % {'stmt': stmt, 'setup': '_setup()', + 'init': ', _setup=_setup'} ns['_setup'] = setup else: raise ValueError("setup is neither a string nor callable") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,8 @@ Library ------- +- Issue #5633: Fixed timeit when the statement is a string and the setup is not. + - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 18:46:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 16:46:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=235633=3A_Fixed_timeit_when_the_statement_is_a_st?= =?utf-8?q?ring_and_the_setup_is_not=2E?= Message-ID: <20150530164604.27668.54412@psf.io> https://hg.python.org/cpython/rev/fd01cbe4336e changeset: 96388:fd01cbe4336e parent: 96384:10eabadba316 parent: 96387:faea7c8bcb13 user: Serhiy Storchaka date: Sat May 30 19:45:36 2015 +0300 summary: Issue #5633: Fixed timeit when the statement is a string and the setup is not. Refactored timeit.__init__ for unified handling of stmt and setup parameters. files: Lib/test/test_timeit.py | 7 +++ Lib/timeit.py | 53 ++++++++++------------------ Misc/NEWS | 2 + 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -124,6 +124,9 @@ def test_timeit_callable_stmt(self): self.timeit(self.fake_callable_stmt, self.fake_setup, number=3) + def test_timeit_callable_setup(self): + self.timeit(self.fake_stmt, self.fake_callable_setup, number=3) + def test_timeit_callable_stmt_and_setup(self): self.timeit(self.fake_callable_stmt, self.fake_callable_setup, number=3) @@ -184,6 +187,10 @@ self.repeat(self.fake_callable_stmt, self.fake_setup, repeat=3, number=5) + def test_repeat_callable_setup(self): + self.repeat(self.fake_stmt, self.fake_callable_setup, + repeat=3, number=5) + def test_repeat_callable_stmt_and_setup(self): self.repeat(self.fake_callable_stmt, self.fake_callable_setup, repeat=3, number=5) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -68,7 +68,7 @@ # in Timer.__init__() depend on setup being indented 4 spaces and stmt # being indented 8 spaces. template = """ -def inner(_it, _timer): +def inner(_it, _timer{init}): {setup} _t0 = _timer() for _i in _it: @@ -81,17 +81,6 @@ """Helper to reindent a multi-line statement.""" return src.replace("\n", "\n" + " "*indent) -def _template_func(setup, func): - """Create a timer function. Used if the "statement" is a callable.""" - def inner(_it, _timer, _func=func): - setup() - _t0 = _timer() - for _i in _it: - _func() - _t1 = _timer() - return _t1 - _t0 - return inner - class Timer: """Class for timing execution speed of small code snippets. @@ -116,37 +105,35 @@ self.timer = timer local_ns = {} global_ns = _globals() if globals is None else globals + init = '' + if isinstance(setup, str): + # Check that the code can be compiled outside a function + compile(setup, dummy_src_name, "exec") + setup = reindent(setup, 4) + elif callable(setup): + local_ns['_setup'] = setup + init += ', _setup=_setup' + setup = '_setup()' + else: + raise ValueError("setup is neither a string nor callable") if isinstance(stmt, str): # Check that the code can be compiled outside a function if isinstance(setup, str): - compile(setup, dummy_src_name, "exec") compile(setup + '\n' + stmt, dummy_src_name, "exec") else: compile(stmt, dummy_src_name, "exec") stmt = reindent(stmt, 8) - if isinstance(setup, str): - setup = reindent(setup, 4) - src = template.format(stmt=stmt, setup=setup) - elif callable(setup): - src = template.format(stmt=stmt, setup='_setup()') - local_ns['_setup'] = setup - else: - raise ValueError("setup is neither a string nor callable") - self.src = src # Save for traceback display - code = compile(src, dummy_src_name, "exec") - exec(code, global_ns, local_ns) - self.inner = local_ns["inner"] elif callable(stmt): - self.src = None - if isinstance(setup, str): - _setup = setup - def setup(): - exec(_setup, global_ns, local_ns) - elif not callable(setup): - raise ValueError("setup is neither a string nor callable") - self.inner = _template_func(setup, stmt) + local_ns['_stmt'] = stmt + init += ', _stmt=_stmt' + stmt = '_stmt()' else: raise ValueError("stmt is neither a string nor callable") + src = template.format(stmt=stmt, setup=setup, init=init) + self.src = src # Save for traceback display + code = compile(src, dummy_src_name, "exec") + exec(code, global_ns, local_ns) + self.inner = local_ns["inner"] def print_exc(self, file=None): """Helper to print a traceback from the timed code. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,8 @@ Library ------- +- Issue #5633: Fixed timeit when the statement is a string and the setup is not. + - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 18:46:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 30 May 2015 16:46:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=235633=3A_Fixed_timeit_when_the_statement_is_a_string_a?= =?utf-8?q?nd_the_setup_is_not=2E?= Message-ID: <20150530164604.18668.21417@psf.io> https://hg.python.org/cpython/rev/faea7c8bcb13 changeset: 96387:faea7c8bcb13 branch: 3.5 parent: 96383:0a7380984e37 parent: 96386:89de73c0d848 user: Serhiy Storchaka date: Sat May 30 19:44:55 2015 +0300 summary: Issue #5633: Fixed timeit when the statement is a string and the setup is not. Refactored timeit.__init__ for unified handling of stmt and setup parameters. files: Lib/test/test_timeit.py | 7 +++ Lib/timeit.py | 53 ++++++++++------------------ Misc/NEWS | 2 + 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -124,6 +124,9 @@ def test_timeit_callable_stmt(self): self.timeit(self.fake_callable_stmt, self.fake_setup, number=3) + def test_timeit_callable_setup(self): + self.timeit(self.fake_stmt, self.fake_callable_setup, number=3) + def test_timeit_callable_stmt_and_setup(self): self.timeit(self.fake_callable_stmt, self.fake_callable_setup, number=3) @@ -184,6 +187,10 @@ self.repeat(self.fake_callable_stmt, self.fake_setup, repeat=3, number=5) + def test_repeat_callable_setup(self): + self.repeat(self.fake_stmt, self.fake_callable_setup, + repeat=3, number=5) + def test_repeat_callable_stmt_and_setup(self): self.repeat(self.fake_callable_stmt, self.fake_callable_setup, repeat=3, number=5) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -68,7 +68,7 @@ # in Timer.__init__() depend on setup being indented 4 spaces and stmt # being indented 8 spaces. template = """ -def inner(_it, _timer): +def inner(_it, _timer{init}): {setup} _t0 = _timer() for _i in _it: @@ -81,17 +81,6 @@ """Helper to reindent a multi-line statement.""" return src.replace("\n", "\n" + " "*indent) -def _template_func(setup, func): - """Create a timer function. Used if the "statement" is a callable.""" - def inner(_it, _timer, _func=func): - setup() - _t0 = _timer() - for _i in _it: - _func() - _t1 = _timer() - return _t1 - _t0 - return inner - class Timer: """Class for timing execution speed of small code snippets. @@ -116,37 +105,35 @@ self.timer = timer local_ns = {} global_ns = _globals() if globals is None else globals + init = '' + if isinstance(setup, str): + # Check that the code can be compiled outside a function + compile(setup, dummy_src_name, "exec") + setup = reindent(setup, 4) + elif callable(setup): + local_ns['_setup'] = setup + init += ', _setup=_setup' + setup = '_setup()' + else: + raise ValueError("setup is neither a string nor callable") if isinstance(stmt, str): # Check that the code can be compiled outside a function if isinstance(setup, str): - compile(setup, dummy_src_name, "exec") compile(setup + '\n' + stmt, dummy_src_name, "exec") else: compile(stmt, dummy_src_name, "exec") stmt = reindent(stmt, 8) - if isinstance(setup, str): - setup = reindent(setup, 4) - src = template.format(stmt=stmt, setup=setup) - elif callable(setup): - src = template.format(stmt=stmt, setup='_setup()') - local_ns['_setup'] = setup - else: - raise ValueError("setup is neither a string nor callable") - self.src = src # Save for traceback display - code = compile(src, dummy_src_name, "exec") - exec(code, global_ns, local_ns) - self.inner = local_ns["inner"] elif callable(stmt): - self.src = None - if isinstance(setup, str): - _setup = setup - def setup(): - exec(_setup, global_ns, local_ns) - elif not callable(setup): - raise ValueError("setup is neither a string nor callable") - self.inner = _template_func(setup, stmt) + local_ns['_stmt'] = stmt + init += ', _stmt=_stmt' + stmt = '_stmt()' else: raise ValueError("stmt is neither a string nor callable") + src = template.format(stmt=stmt, setup=setup, init=init) + self.src = src # Save for traceback display + code = compile(src, dummy_src_name, "exec") + exec(code, global_ns, local_ns) + self.inner = local_ns["inner"] def print_exc(self, file=None): """Helper to print a traceback from the timed code. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,8 @@ Library ------- +- Issue #5633: Fixed timeit when the statement is a string and the setup is not. + - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. Original patch by David Moore. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 19:48:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 17:48:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_docs=3A_Sync_whatsnew/3=2E?= =?utf-8?q?5=2Erst_with_3=2E6?= Message-ID: <20150530174803.27658.50427@psf.io> https://hg.python.org/cpython/rev/d810cce6473f changeset: 96389:d810cce6473f user: Yury Selivanov date: Sat May 30 13:47:57 2015 -0400 summary: docs: Sync whatsnew/3.5.rst with 3.6 files: Doc/whatsnew/3.5.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -97,6 +97,10 @@ Significantly Improved Library Modules: +* :class:`collections.OrderedDict` is now implemented in C, which improves + its performance between 4x to 100x times. Contributed by Eric Snow in + :issue:`16991`. + * You may now pass bytes to the :mod:`tempfile` module's APIs and it will return the temporary pathname as bytes instead of str. It also accepts a value of ``None`` on parameters where only str was accepted in the past to -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 19:54:59 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 17:54:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_22357=3A_Merge_from_3=2E4?= Message-ID: <20150530175459.24081.38339@psf.io> https://hg.python.org/cpython/rev/1d9131bc0ea4 changeset: 96391:1d9131bc0ea4 branch: 3.5 parent: 96387:faea7c8bcb13 parent: 96390:943fa0e8b6a4 user: Yury Selivanov date: Sat May 30 13:54:36 2015 -0400 summary: Issue 22357: Merge from 3.4 files: Doc/library/inspect.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -43,6 +43,11 @@ +-----------+-----------------+---------------------------+ | class | __doc__ | documentation string | +-----------+-----------------+---------------------------+ +| | __name__ | name with which this | +| | | class was defined | ++-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __module__ | name of module in which | | | | this class was defined | +-----------+-----------------+---------------------------+ @@ -51,6 +56,8 @@ | | __name__ | name with which this | | | | method was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __func__ | function object | | | | containing implementation | | | | of method | @@ -64,6 +71,8 @@ | | __name__ | name with which this | | | | function was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __code__ | code object containing | | | | compiled function | | | | :term:`bytecode` | @@ -174,6 +183,8 @@ | | __name__ | original name of this | | | | function or method | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __self__ | instance to which a | | | | method is bound, or | | | | ``None`` | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 19:54:59 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 17:54:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjIzNTc6?= =?utf-8?q?_Document_=5F=5Fqualname=5F=5F_in_inspect=2Erst?= Message-ID: <20150530175459.4340.20343@psf.io> https://hg.python.org/cpython/rev/943fa0e8b6a4 changeset: 96390:943fa0e8b6a4 branch: 3.4 parent: 96386:89de73c0d848 user: Yury Selivanov date: Sat May 30 13:53:49 2015 -0400 summary: Issue 22357: Document __qualname__ in inspect.rst files: Doc/library/inspect.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -43,6 +43,11 @@ +-----------+-----------------+---------------------------+ | class | __doc__ | documentation string | +-----------+-----------------+---------------------------+ +| | __name__ | name with which this | +| | | class was defined | ++-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __module__ | name of module in which | | | | this class was defined | +-----------+-----------------+---------------------------+ @@ -51,6 +56,8 @@ | | __name__ | name with which this | | | | method was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __func__ | function object | | | | containing implementation | | | | of method | @@ -64,6 +71,8 @@ | | __name__ | name with which this | | | | function was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __code__ | code object containing | | | | compiled function | | | | :term:`bytecode` | @@ -164,6 +173,8 @@ | | __name__ | original name of this | | | | function or method | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __self__ | instance to which a | | | | method is bound, or | | | | ``None`` | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 19:55:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 17:55:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_22357=3A_Merge_from_3=2E5?= Message-ID: <20150530175500.111602.33787@psf.io> https://hg.python.org/cpython/rev/5621e9a21cc3 changeset: 96392:5621e9a21cc3 parent: 96389:d810cce6473f parent: 96391:1d9131bc0ea4 user: Yury Selivanov date: Sat May 30 13:54:52 2015 -0400 summary: Issue 22357: Merge from 3.5 files: Doc/library/inspect.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -43,6 +43,11 @@ +-----------+-----------------+---------------------------+ | class | __doc__ | documentation string | +-----------+-----------------+---------------------------+ +| | __name__ | name with which this | +| | | class was defined | ++-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __module__ | name of module in which | | | | this class was defined | +-----------+-----------------+---------------------------+ @@ -51,6 +56,8 @@ | | __name__ | name with which this | | | | method was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __func__ | function object | | | | containing implementation | | | | of method | @@ -64,6 +71,8 @@ | | __name__ | name with which this | | | | function was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __code__ | code object containing | | | | compiled function | | | | :term:`bytecode` | @@ -174,6 +183,8 @@ | | __name__ | original name of this | | | | function or method | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __self__ | instance to which a | | | | method is bound, or | | | | ``None`` | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:04:23 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:04:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Do_not_return_None_from_OrderedDict=2E=5F=5Freversed=5F=5F?= =?utf-8?q?=2E?= Message-ID: <20150530180423.83477.27315@psf.io> https://hg.python.org/cpython/rev/951a3ef82180 changeset: 96394:951a3ef82180 branch: 3.5 user: Eric Snow date: Sat May 30 11:43:36 2015 -0600 summary: Issue #16991: Do not return None from OrderedDict.__reversed__. files: Lib/test/test_collections.py | 14 +++++++++++++- Objects/odictobject.c | 3 --- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1773,6 +1773,19 @@ self.assertEqual(sorted(reversed(od)), sorted([t[0] for t in reversed(pairs)])) + def test_iterators_empty(self): + OrderedDict = self.module.OrderedDict + od = OrderedDict() + empty = [] + self.assertEqual(list(od), empty) + self.assertEqual(list(od.keys()), empty) + self.assertEqual(list(od.values()), empty) + self.assertEqual(list(od.items()), empty) + self.assertEqual(list(reversed(od)), empty) + self.assertEqual(list(reversed(od.keys())), empty) + self.assertEqual(list(reversed(od.values())), empty) + self.assertEqual(list(reversed(od.items())), empty) + def test_popitem(self): OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1965,7 +1978,6 @@ od = OrderedDict(**d) self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) - OrderedDict = self.module.OrderedDict def test_override_update(self): OrderedDict = self.module.OrderedDict # Verify that subclasses can override update() without breaking __init__() diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1357,9 +1357,6 @@ static PyObject * odict_reversed(PyODictObject *od) { - if (_odict_EMPTY(od)) { - Py_RETURN_NONE; - } return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:04:22 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:04:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Properly_handle_return_values_in_several_places=2E?= Message-ID: <20150530180422.91785.8510@psf.io> https://hg.python.org/cpython/rev/c9404fba02ba changeset: 96393:c9404fba02ba branch: 3.5 parent: 96387:faea7c8bcb13 user: Eric Snow date: Sat May 30 11:28:56 2015 -0600 summary: Issue #16991: Properly handle return values in several places. files: Objects/odictobject.c | 59 ++++++++++++++++++++++-------- 1 files changed, 43 insertions(+), 16 deletions(-) diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -948,7 +948,7 @@ odict_sizeof(PyODictObject *od) { PyObject *pylong; - Py_ssize_t res; + Py_ssize_t res, temp; pylong = _PyDict_SizeOf((PyDictObject *)od); if (pylong == NULL) @@ -964,10 +964,11 @@ pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict); if (pylong == NULL) return NULL; - res += PyLong_AsSsize_t(pylong); + temp = PyLong_AsSsize_t(pylong); Py_DECREF(pylong); - if (res == -1 && PyErr_Occurred()) + if (temp == -1 && PyErr_Occurred()) return NULL; + res += temp; res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ if (!_odict_EMPTY(od)) { @@ -990,8 +991,11 @@ /* capture any instance state */ vars = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__); - if (vars != NULL) { + if (vars == NULL) + goto Done; + else { PyObject *empty, *od_vars, *iterator, *key; + int ns_len; /* od.__dict__ isn't necessarily a dict... */ ns = PyObject_CallMethod((PyObject *)vars, "copy", NULL); @@ -1021,7 +1025,10 @@ if (PyErr_Occurred()) goto Done; - if (!PyObject_Length(ns)) { + ns_len = PyObject_Length(ns); + if (ns_len == -1) + goto Done; + if (!ns_len) { /* nothing novel to pickle in od.__dict__ */ Py_DECREF(ns); ns = NULL; @@ -1382,14 +1389,21 @@ return NULL; } if (last != NULL) { + int is_true; Py_INCREF(last); - pos = PyObject_IsTrue(last) ? -1 : 0; + is_true = PyObject_IsTrue(last); Py_DECREF(last); + if (is_true == -1) + return NULL; + pos = is_true ? -1 : 0; } if (pos == 0) { /* Only move if not already the first one. */ PyObject *first_key = _odictnode_KEY(_odict_FIRST(od)); - if (PyObject_RichCompareBool(key, first_key, Py_NE)) { + int not_equal = PyObject_RichCompareBool(key, first_key, Py_NE); + if (not_equal == -1) + return NULL; + if (not_equal) { _ODictNode *node = _odict_pop_node(od, NULL, key); if (node != NULL) { _odict_add_head(od, node); @@ -1405,7 +1419,10 @@ else if (pos == -1) { /* Only move if not already the last one. */ PyObject *last_key = _odictnode_KEY(_odict_LAST(od)); - if (PyObject_RichCompareBool(key, last_key, Py_NE)) { + int not_equal = PyObject_RichCompareBool(key, last_key, Py_NE); + if (not_equal == -1) + return NULL; + if (not_equal) { _ODictNode *node = _odict_pop_node(od, NULL, key); if (node != NULL) { _odict_add_tail(od, node); @@ -1771,6 +1788,7 @@ int res = PyDict_SetItem(od, key, value); if (res == 0) { res = _odict_add_new_node((PyODictObject *)od, key); + /* XXX Revert setting the value on the dict? */ } return res; }; @@ -1869,6 +1887,8 @@ PyObject *result = di->di_result; value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ + if (value == NULL) + return NULL; if (result->ob_refcnt == 1) { /* not in use so we can reuse it @@ -1905,7 +1925,7 @@ static PyObject * odictiter_reduce(odictiterobject *di) { - PyObject *list; + PyObject *list, *iter; list = PyList_New(0); if (!list) @@ -1931,7 +1951,12 @@ Py_DECREF(list); return NULL; } - return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); + iter = _PyObject_GetBuiltin("iter"); + if (iter == NULL) { + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", iter, list); } static PyMethodDef odictiter_methods[] = { @@ -2262,8 +2287,10 @@ while ((pair = PyIter_Next(iterator)) != NULL) { /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */ - PyObject * key, *value = NULL; + PyObject *key = NULL, *value = NULL; PyObject *pair_iterator = PyObject_GetIter(pair); + if (pair_iterator == NULL) + goto Done; key = PyIter_Next(pair_iterator); if (key == NULL) { @@ -2295,7 +2322,7 @@ Done: Py_DECREF(pair); - Py_DECREF(pair_iterator); + Py_XDECREF(pair_iterator); Py_XDECREF(key); Py_XDECREF(value); if (PyErr_Occurred()) @@ -2316,7 +2343,7 @@ Py_ssize_t len = (args != NULL) ? PyObject_Size(args) : 0; /* first handle args, if any */ - if (len < 0) + if (len < 0) /* PyObject_Size raised an exception. */ return NULL; else if (len > 1) { char *msg = "update() takes at most 1 positional argument (%d given)"; @@ -2328,7 +2355,7 @@ if (other == NULL) return NULL; Py_INCREF(other); - if (PyObject_HasAttrString(other, "items")) { + if (PyObject_HasAttrString(other, "items")) { /* never fails */ PyObject *items = PyMapping_Items(other); Py_DECREF(other); if (items == NULL) @@ -2338,7 +2365,7 @@ if (res == -1) return NULL; } - else if (PyObject_HasAttrString(other, "keys")) { + else if (PyObject_HasAttrString(other, "keys")) { /* never fails */ PyObject *keys, *iterator, *key; keys = PyObject_CallMethod(other, "keys", NULL); Py_DECREF(other); @@ -2373,7 +2400,7 @@ /* now handle kwargs */ len = (kwargs != NULL) ? PyObject_Size(kwargs) : 0; - if (len < 0) + if (len < 0) /* PyObject_Size raised an exception. */ return NULL; else if (len > 0) { PyObject *items; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:04:23 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:04:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_merge?= Message-ID: <20150530180423.27652.21739@psf.io> https://hg.python.org/cpython/rev/9d779c04b009 changeset: 96395:9d779c04b009 branch: 3.5 parent: 96394:951a3ef82180 parent: 96391:1d9131bc0ea4 user: Eric Snow date: Sat May 30 11:59:17 2015 -0600 summary: merge files: Doc/library/inspect.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -43,6 +43,11 @@ +-----------+-----------------+---------------------------+ | class | __doc__ | documentation string | +-----------+-----------------+---------------------------+ +| | __name__ | name with which this | +| | | class was defined | ++-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __module__ | name of module in which | | | | this class was defined | +-----------+-----------------+---------------------------+ @@ -51,6 +56,8 @@ | | __name__ | name with which this | | | | method was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __func__ | function object | | | | containing implementation | | | | of method | @@ -64,6 +71,8 @@ | | __name__ | name with which this | | | | function was defined | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __code__ | code object containing | | | | compiled function | | | | :term:`bytecode` | @@ -174,6 +183,8 @@ | | __name__ | original name of this | | | | function or method | +-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ | | __self__ | instance to which a | | | | method is bound, or | | | | ``None`` | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:04:23 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:04:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530180423.18175.26959@psf.io> https://hg.python.org/cpython/rev/958f1233e28c changeset: 96396:958f1233e28c parent: 96392:5621e9a21cc3 parent: 96395:9d779c04b009 user: Eric Snow date: Sat May 30 12:00:05 2015 -0600 summary: Merge from 3.5. files: Lib/test/test_collections.py | 14 +++++- Objects/odictobject.c | 62 ++++++++++++++++------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1773,6 +1773,19 @@ self.assertEqual(sorted(reversed(od)), sorted([t[0] for t in reversed(pairs)])) + def test_iterators_empty(self): + OrderedDict = self.module.OrderedDict + od = OrderedDict() + empty = [] + self.assertEqual(list(od), empty) + self.assertEqual(list(od.keys()), empty) + self.assertEqual(list(od.values()), empty) + self.assertEqual(list(od.items()), empty) + self.assertEqual(list(reversed(od)), empty) + self.assertEqual(list(reversed(od.keys())), empty) + self.assertEqual(list(reversed(od.values())), empty) + self.assertEqual(list(reversed(od.items())), empty) + def test_popitem(self): OrderedDict = self.module.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] @@ -1966,7 +1979,6 @@ self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) def test_views(self): - OrderedDict = self.module.OrderedDict # See http://bugs.python.org/issue24286 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() od = OrderedDict.fromkeys(s) diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -948,7 +948,7 @@ odict_sizeof(PyODictObject *od) { PyObject *pylong; - Py_ssize_t res; + Py_ssize_t res, temp; pylong = _PyDict_SizeOf((PyDictObject *)od); if (pylong == NULL) @@ -964,10 +964,11 @@ pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict); if (pylong == NULL) return NULL; - res += PyLong_AsSsize_t(pylong); + temp = PyLong_AsSsize_t(pylong); Py_DECREF(pylong); - if (res == -1 && PyErr_Occurred()) + if (temp == -1 && PyErr_Occurred()) return NULL; + res += temp; res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ if (!_odict_EMPTY(od)) { @@ -990,8 +991,11 @@ /* capture any instance state */ vars = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__); - if (vars != NULL) { + if (vars == NULL) + goto Done; + else { PyObject *empty, *od_vars, *iterator, *key; + int ns_len; /* od.__dict__ isn't necessarily a dict... */ ns = PyObject_CallMethod((PyObject *)vars, "copy", NULL); @@ -1021,7 +1025,10 @@ if (PyErr_Occurred()) goto Done; - if (!PyObject_Length(ns)) { + ns_len = PyObject_Length(ns); + if (ns_len == -1) + goto Done; + if (!ns_len) { /* nothing novel to pickle in od.__dict__ */ Py_DECREF(ns); ns = NULL; @@ -1350,9 +1357,6 @@ static PyObject * odict_reversed(PyODictObject *od) { - if (_odict_EMPTY(od)) { - Py_RETURN_NONE; - } return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED); } @@ -1382,14 +1386,21 @@ return NULL; } if (last != NULL) { + int is_true; Py_INCREF(last); - pos = PyObject_IsTrue(last) ? -1 : 0; + is_true = PyObject_IsTrue(last); Py_DECREF(last); + if (is_true == -1) + return NULL; + pos = is_true ? -1 : 0; } if (pos == 0) { /* Only move if not already the first one. */ PyObject *first_key = _odictnode_KEY(_odict_FIRST(od)); - if (PyObject_RichCompareBool(key, first_key, Py_NE)) { + int not_equal = PyObject_RichCompareBool(key, first_key, Py_NE); + if (not_equal == -1) + return NULL; + if (not_equal) { _ODictNode *node = _odict_pop_node(od, NULL, key); if (node != NULL) { _odict_add_head(od, node); @@ -1405,7 +1416,10 @@ else if (pos == -1) { /* Only move if not already the last one. */ PyObject *last_key = _odictnode_KEY(_odict_LAST(od)); - if (PyObject_RichCompareBool(key, last_key, Py_NE)) { + int not_equal = PyObject_RichCompareBool(key, last_key, Py_NE); + if (not_equal == -1) + return NULL; + if (not_equal) { _ODictNode *node = _odict_pop_node(od, NULL, key); if (node != NULL) { _odict_add_tail(od, node); @@ -1771,6 +1785,7 @@ int res = PyDict_SetItem(od, key, value); if (res == 0) { res = _odict_add_new_node((PyODictObject *)od, key); + /* XXX Revert setting the value on the dict? */ } return res; }; @@ -1869,6 +1884,8 @@ PyObject *result = di->di_result; value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ + if (value == NULL) + return NULL; if (result->ob_refcnt == 1) { /* not in use so we can reuse it @@ -1905,7 +1922,7 @@ static PyObject * odictiter_reduce(odictiterobject *di) { - PyObject *list; + PyObject *list, *iter; list = PyList_New(0); if (!list) @@ -1931,7 +1948,12 @@ Py_DECREF(list); return NULL; } - return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list); + iter = _PyObject_GetBuiltin("iter"); + if (iter == NULL) { + Py_DECREF(list); + return NULL; + } + return Py_BuildValue("N(N)", iter, list); } static PyMethodDef odictiter_methods[] = { @@ -2262,8 +2284,10 @@ while ((pair = PyIter_Next(iterator)) != NULL) { /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */ - PyObject * key, *value = NULL; + PyObject *key = NULL, *value = NULL; PyObject *pair_iterator = PyObject_GetIter(pair); + if (pair_iterator == NULL) + goto Done; key = PyIter_Next(pair_iterator); if (key == NULL) { @@ -2295,7 +2319,7 @@ Done: Py_DECREF(pair); - Py_DECREF(pair_iterator); + Py_XDECREF(pair_iterator); Py_XDECREF(key); Py_XDECREF(value); if (PyErr_Occurred()) @@ -2316,7 +2340,7 @@ Py_ssize_t len = (args != NULL) ? PyObject_Size(args) : 0; /* first handle args, if any */ - if (len < 0) + if (len < 0) /* PyObject_Size raised an exception. */ return NULL; else if (len > 1) { char *msg = "update() takes at most 1 positional argument (%d given)"; @@ -2328,7 +2352,7 @@ if (other == NULL) return NULL; Py_INCREF(other); - if (PyObject_HasAttrString(other, "items")) { + if (PyObject_HasAttrString(other, "items")) { /* never fails */ PyObject *items = PyMapping_Items(other); Py_DECREF(other); if (items == NULL) @@ -2338,7 +2362,7 @@ if (res == -1) return NULL; } - else if (PyObject_HasAttrString(other, "keys")) { + else if (PyObject_HasAttrString(other, "keys")) { /* never fails */ PyObject *keys, *iterator, *key; keys = PyObject_CallMethod(other, "keys", NULL); Py_DECREF(other); @@ -2373,7 +2397,7 @@ /* now handle kwargs */ len = (kwargs != NULL) ? PyObject_Size(kwargs) : 0; - if (len < 0) + if (len < 0) /* PyObject_Size raised an exception. */ return NULL; else if (len > 0) { PyObject *items; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:08:16 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:08:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Drop_Py=5FODict=5FGetItemId=2E?= Message-ID: <20150530180816.4336.73658@psf.io> https://hg.python.org/cpython/rev/7117e9b0f595 changeset: 96397:7117e9b0f595 branch: 3.5 parent: 96395:9d779c04b009 user: Eric Snow date: Sat May 30 12:06:03 2015 -0600 summary: Issue #16991: Drop Py_ODict_GetItemId. files: Include/odictobject.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Include/odictobject.h b/Include/odictobject.h --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -34,7 +34,6 @@ #define PyODict_Size(od) PyDict_Size((PyObject *)od) #define PyODict_GetItemString(od, key) \ PyDict_GetItemString((PyObject *)od, key) -#define Py_ODict_GetItemId(od, key) _PyDict_GetItemId((PyObject *)od, key) #ifdef __cplusplus } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:08:16 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:08:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530180816.25405.94159@psf.io> https://hg.python.org/cpython/rev/6f99cd255237 changeset: 96398:6f99cd255237 parent: 96396:958f1233e28c parent: 96397:7117e9b0f595 user: Eric Snow date: Sat May 30 12:06:26 2015 -0600 summary: Merge from 3.5. files: Include/odictobject.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Include/odictobject.h b/Include/odictobject.h --- a/Include/odictobject.h +++ b/Include/odictobject.h @@ -34,7 +34,6 @@ #define PyODict_Size(od) PyDict_Size((PyObject *)od) #define PyODict_GetItemString(od, key) \ PyDict_GetItemString((PyObject *)od, key) -#define Py_ODict_GetItemId(od, key) _PyDict_GetItemId((PyObject *)od, key) #ifdef __cplusplus } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:55:44 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:55:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Fix_a_few_leaks_and_other_memory-related_concerns_in_Ordere?= =?utf-8?q?dDict=2E?= Message-ID: <20150530185544.4340.82141@psf.io> https://hg.python.org/cpython/rev/030205f1e716 changeset: 96399:030205f1e716 branch: 3.5 parent: 96397:7117e9b0f595 user: Eric Snow date: Sat May 30 12:51:15 2015 -0600 summary: Issue #16991: Fix a few leaks and other memory-related concerns in OrderedDict. files: Objects/odictobject.c | 26 ++++++++++++++------------ 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1030,8 +1030,7 @@ goto Done; if (!ns_len) { /* nothing novel to pickle in od.__dict__ */ - Py_DECREF(ns); - ns = NULL; + Py_CLEAR(ns); } } @@ -1184,8 +1183,7 @@ value = PyObject_GetItem(od, key); if (value != NULL) { if (PyObject_DelItem(od, key) == -1) { - Py_DECREF(value); - value = NULL; + Py_CLEAR(value); } } } @@ -1718,10 +1716,10 @@ { PyObject *od = PyDict_Type.tp_new(type, args, kwds); if (od != NULL) { + if (_odict_initialize((PyODictObject *)od) < 0) + return NULL; ((PyODictObject *)od)->od_inst_dict = PyDict_New(); ((PyODictObject *)od)->od_weakreflist = NULL; - if (_odict_initialize((PyODictObject *)od) < 0) - return NULL; } return od; } @@ -1845,8 +1843,7 @@ node = _odict_find_node(di->di_odict, di->di_current); if (node == NULL) { /* Must have been deleted. */ - Py_DECREF(di->di_current); - di->di_current = NULL; + Py_CLEAR(di->di_current); return NULL; } key = di->di_current; @@ -1884,8 +1881,11 @@ PyObject *result = di->di_result; value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ - if (value == NULL) + if (value == NULL) { + Py_DECREF(key); return NULL; + } + Py_INCREF(value); if (result->ob_refcnt == 1) { /* not in use so we can reuse it @@ -1896,11 +1896,13 @@ } else { result = PyTuple_New(2); - if (result == NULL) + if (result == NULL) { + Py_DECREF(key); + Py_DECREF(value); return NULL; + } } - Py_INCREF(value); PyTuple_SET_ITEM(result, 0, key); /* steals reference */ PyTuple_SET_ITEM(result, 1, value); /* steals reference */ @@ -2365,7 +2367,6 @@ else if (PyObject_HasAttrString(other, "keys")) { /* never fails */ PyObject *keys, *iterator, *key; keys = PyObject_CallMethod(other, "keys", NULL); - Py_DECREF(other); if (keys == NULL) return NULL; iterator = PyObject_GetIter(keys); @@ -2383,6 +2384,7 @@ } Py_DECREF(key); } + Py_DECREF(other); Py_DECREF(iterator); if (res != 0 || PyErr_Occurred()) return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 20:55:44 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 18:55:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530185544.4324.62649@psf.io> https://hg.python.org/cpython/rev/39acefd27d8d changeset: 96400:39acefd27d8d parent: 96398:6f99cd255237 parent: 96399:030205f1e716 user: Eric Snow date: Sat May 30 12:55:22 2015 -0600 summary: Merge from 3.5. files: Objects/odictobject.c | 26 ++++++++++++++------------ 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1030,8 +1030,7 @@ goto Done; if (!ns_len) { /* nothing novel to pickle in od.__dict__ */ - Py_DECREF(ns); - ns = NULL; + Py_CLEAR(ns); } } @@ -1184,8 +1183,7 @@ value = PyObject_GetItem(od, key); if (value != NULL) { if (PyObject_DelItem(od, key) == -1) { - Py_DECREF(value); - value = NULL; + Py_CLEAR(value); } } } @@ -1718,10 +1716,10 @@ { PyObject *od = PyDict_Type.tp_new(type, args, kwds); if (od != NULL) { + if (_odict_initialize((PyODictObject *)od) < 0) + return NULL; ((PyODictObject *)od)->od_inst_dict = PyDict_New(); ((PyODictObject *)od)->od_weakreflist = NULL; - if (_odict_initialize((PyODictObject *)od) < 0) - return NULL; } return od; } @@ -1845,8 +1843,7 @@ node = _odict_find_node(di->di_odict, di->di_current); if (node == NULL) { /* Must have been deleted. */ - Py_DECREF(di->di_current); - di->di_current = NULL; + Py_CLEAR(di->di_current); return NULL; } key = di->di_current; @@ -1884,8 +1881,11 @@ PyObject *result = di->di_result; value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */ - if (value == NULL) + if (value == NULL) { + Py_DECREF(key); return NULL; + } + Py_INCREF(value); if (result->ob_refcnt == 1) { /* not in use so we can reuse it @@ -1896,11 +1896,13 @@ } else { result = PyTuple_New(2); - if (result == NULL) + if (result == NULL) { + Py_DECREF(key); + Py_DECREF(value); return NULL; + } } - Py_INCREF(value); PyTuple_SET_ITEM(result, 0, key); /* steals reference */ PyTuple_SET_ITEM(result, 1, value); /* steals reference */ @@ -2365,7 +2367,6 @@ else if (PyObject_HasAttrString(other, "keys")) { /* never fails */ PyObject *keys, *iterator, *key; keys = PyObject_CallMethod(other, "keys", NULL); - Py_DECREF(other); if (keys == NULL) return NULL; iterator = PyObject_GetIter(keys); @@ -2383,6 +2384,7 @@ } Py_DECREF(key); } + Py_DECREF(other); Py_DECREF(iterator); if (res != 0 || PyErr_Occurred()) return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 21:25:20 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 19:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316991=3A_Ensure_t?= =?utf-8?q?hat_the_proper_OrderedDict_is_used_in_tests=2E?= Message-ID: <20150530192520.25403.28330@psf.io> https://hg.python.org/cpython/rev/fbe74badb0c6 changeset: 96401:fbe74badb0c6 user: Eric Snow date: Sat May 30 13:24:54 2015 -0600 summary: Issue #16991: Ensure that the proper OrderedDict is used in tests. files: Lib/test/test_collections.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1979,6 +1979,7 @@ self.assertGreater(sys.getsizeof(od), sys.getsizeof(d)) def test_views(self): + OrderedDict = self.module.OrderedDict # See http://bugs.python.org/issue24286 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() od = OrderedDict.fromkeys(s) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 22:27:08 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 20:27:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Add_PyODict*_to_Windows_builds=2E?= Message-ID: <20150530202707.83471.4262@psf.io> https://hg.python.org/cpython/rev/1d851112922f changeset: 96402:1d851112922f branch: 3.5 parent: 96399:030205f1e716 user: Eric Snow date: Sat May 30 14:19:27 2015 -0600 summary: Issue #16991: Add PyODict* to Windows builds. files: PC/python3.def | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -434,6 +434,14 @@ PyObject_Size=python35.PyObject_Size PyObject_Str=python35.PyObject_Str PyObject_Type=python35.PyObject_Type DATA + PyODict_DelItem=python35.PyODict_DelItem + PyODict_New=python35.PyODict_New + PyODict_SetItem=python35.PyODict_SetItem + PyODict_Type=python35.PyODict_Type DATA + PyODictItems_Type=python35.PyODictItems_Type DATA + PyODictIter_Type=python35.PyODictIter_Type DATA + PyODictKeys_Type=python35.PyODictKeys_Type DATA + PyODictValues_Type=python35.PyODictValues_Type DATA PyParser_SimpleParseFileFlags=python35.PyParser_SimpleParseFileFlags PyParser_SimpleParseStringFlags=python35.PyParser_SimpleParseStringFlags PyProperty_Type=python35.PyProperty_Type DATA -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 22:27:08 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 20:27:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530202708.4354.19559@psf.io> https://hg.python.org/cpython/rev/cf8f8d07a4fd changeset: 96403:cf8f8d07a4fd parent: 96401:fbe74badb0c6 parent: 96402:1d851112922f user: Eric Snow date: Sat May 30 14:26:40 2015 -0600 summary: Merge from 3.5. files: PC/python3.def | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -434,6 +434,14 @@ PyObject_Size=python36.PyObject_Size PyObject_Str=python36.PyObject_Str PyObject_Type=python36.PyObject_Type DATA + PyODict_DelItem=python35.PyODict_DelItem + PyODict_New=python35.PyODict_New + PyODict_SetItem=python35.PyODict_SetItem + PyODict_Type=python35.PyODict_Type DATA + PyODictItems_Type=python35.PyODictItems_Type DATA + PyODictIter_Type=python35.PyODictIter_Type DATA + PyODictKeys_Type=python35.PyODictKeys_Type DATA + PyODictValues_Type=python35.PyODictValues_Type DATA PyParser_SimpleParseFileFlags=python36.PyParser_SimpleParseFileFlags PyParser_SimpleParseStringFlags=python36.PyParser_SimpleParseStringFlags PyProperty_Type=python36.PyProperty_Type DATA -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 22:35:23 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 20:35:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316991=3A_Use_the_?= =?utf-8?q?correct_version_for_master=2E?= Message-ID: <20150530203523.24083.66004@psf.io> https://hg.python.org/cpython/rev/3ba1fa925f17 changeset: 96404:3ba1fa925f17 user: Eric Snow date: Sat May 30 14:34:10 2015 -0600 summary: Issue #16991: Use the correct version for master. files: PC/python3.def | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -434,14 +434,14 @@ PyObject_Size=python36.PyObject_Size PyObject_Str=python36.PyObject_Str PyObject_Type=python36.PyObject_Type DATA - PyODict_DelItem=python35.PyODict_DelItem - PyODict_New=python35.PyODict_New - PyODict_SetItem=python35.PyODict_SetItem - PyODict_Type=python35.PyODict_Type DATA - PyODictItems_Type=python35.PyODictItems_Type DATA - PyODictIter_Type=python35.PyODictIter_Type DATA - PyODictKeys_Type=python35.PyODictKeys_Type DATA - PyODictValues_Type=python35.PyODictValues_Type DATA + PyODict_DelItem=python36.PyODict_DelItem + PyODict_New=python36.PyODict_New + PyODict_SetItem=python36.PyODict_SetItem + PyODict_Type=python36.PyODict_Type DATA + PyODictItems_Type=python36.PyODictItems_Type DATA + PyODictIter_Type=python36.PyODictIter_Type DATA + PyODictKeys_Type=python36.PyODictKeys_Type DATA + PyODictValues_Type=python36.PyODictValues_Type DATA PyParser_SimpleParseFileFlags=python36.PyParser_SimpleParseFileFlags PyParser_SimpleParseStringFlags=python36.PyParser_SimpleParseStringFlags PyProperty_Type=python36.PyProperty_Type DATA -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 22:56:35 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 20:56:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUu?= Message-ID: <20150530205635.27668.3988@psf.io> https://hg.python.org/cpython/rev/4a6d49e69a3a changeset: 96406:4a6d49e69a3a parent: 96404:3ba1fa925f17 parent: 96405:aea27164d207 user: Eric Snow date: Sat May 30 14:56:30 2015 -0600 summary: Merge from 3.5. files: PCbuild/pythoncore.vcxproj | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -122,6 +122,7 @@ + @@ -313,6 +314,7 @@ + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 22:56:35 2015 From: python-checkins at python.org (eric.snow) Date: Sat, 30 May 2015 20:56:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE2OTkx?= =?utf-8?q?=3A_Add_odictobject=2Eh_on_Windows=2E?= Message-ID: <20150530205635.89771.24996@psf.io> https://hg.python.org/cpython/rev/aea27164d207 changeset: 96405:aea27164d207 branch: 3.5 parent: 96402:1d851112922f user: Eric Snow date: Sat May 30 14:56:04 2015 -0600 summary: Issue #16991: Add odictobject.h on Windows. files: PCbuild/pythoncore.vcxproj | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -122,6 +122,7 @@ + @@ -313,6 +314,7 @@ + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 23:09:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 21:09:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzOTM0?= =?utf-8?q?=3A_Fix_inspect=2Esignature_to_fail_correctly_for_builtin_types?= =?utf-8?q?=2E?= Message-ID: <20150530210930.111600.90997@psf.io> https://hg.python.org/cpython/rev/e59966bb6de5 changeset: 96407:e59966bb6de5 branch: 3.5 parent: 96405:aea27164d207 user: Yury Selivanov date: Sat May 30 17:08:36 2015 -0400 summary: Issue #23934: Fix inspect.signature to fail correctly for builtin types. Initial patch by James Powell. files: Lib/inspect.py | 6 +++++- Lib/test/test_inspect.py | 7 ++++++- Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2255,9 +2255,13 @@ if type not in obj.__mro__: # We have a class (not metaclass), but no user-defined # __init__ or __new__ for it - if obj.__init__ is object.__init__: + if (obj.__init__ is object.__init__ and + obj.__new__ is object.__new__): # Return a signature of 'object' builtin. return signature(object) + else: + raise ValueError( + 'no signature found for builtin type {!r}'.format(obj)) elif not isinstance(obj, _NonUserDefinedCallables): # An object with __call__ diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1980,9 +1980,14 @@ @cpython_only def test_signature_on_builtins_no_signature(self): import _testcapi - with self.assertRaisesRegex(ValueError, 'no signature found for builtin'): + with self.assertRaisesRegex(ValueError, + 'no signature found for builtin'): inspect.signature(_testcapi.docstring_no_signature) + with self.assertRaisesRegex(ValueError, + 'no signature found for builtin'): + inspect.signature(str) + def test_signature_on_non_function(self): with self.assertRaisesRegex(TypeError, 'is not a callable object'): inspect.signature(42) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -31,6 +31,9 @@ - Issue #16991: Add a C implementation of OrderedDict. +- Issue #23934: Fix inspect.signature to fail correctly for builtin types + lacking signature information. Initial patch by James Powell. + What's New in Python 3.5.0 beta 1? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 23:09:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 30 May 2015 21:09:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323934=3A_Fix_inspect=2Esignature_to_fail_correc?= =?utf-8?q?tly_for_builtin_types=2E?= Message-ID: <20150530210930.18151.82698@psf.io> https://hg.python.org/cpython/rev/19e0ffdd1daa changeset: 96408:19e0ffdd1daa parent: 96406:4a6d49e69a3a parent: 96407:e59966bb6de5 user: Yury Selivanov date: Sat May 30 17:09:15 2015 -0400 summary: Issue #23934: Fix inspect.signature to fail correctly for builtin types. Initial patch by James Powell. (Merge 3.5) files: Lib/inspect.py | 6 +++++- Lib/test/test_inspect.py | 7 ++++++- Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2255,9 +2255,13 @@ if type not in obj.__mro__: # We have a class (not metaclass), but no user-defined # __init__ or __new__ for it - if obj.__init__ is object.__init__: + if (obj.__init__ is object.__init__ and + obj.__new__ is object.__new__): # Return a signature of 'object' builtin. return signature(object) + else: + raise ValueError( + 'no signature found for builtin type {!r}'.format(obj)) elif not isinstance(obj, _NonUserDefinedCallables): # An object with __call__ diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1980,9 +1980,14 @@ @cpython_only def test_signature_on_builtins_no_signature(self): import _testcapi - with self.assertRaisesRegex(ValueError, 'no signature found for builtin'): + with self.assertRaisesRegex(ValueError, + 'no signature found for builtin'): inspect.signature(_testcapi.docstring_no_signature) + with self.assertRaisesRegex(ValueError, + 'no signature found for builtin'): + inspect.signature(str) + def test_signature_on_non_function(self): with self.assertRaisesRegex(TypeError, 'is not a callable object'): inspect.signature(42) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,9 @@ - Issue #16991: Add a C implementation of OrderedDict. +- Issue #23934: Fix inspect.signature to fail correctly for builtin types + lacking signature information. Initial patch by James Powell. + What's New in Python 3.5.0 beta 1? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat May 30 23:13:06 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 30 May 2015 21:13:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_placeholder_PEP_494=2C_Py?= =?utf-8?q?thon_3=2E6_Release_Schedule?= Message-ID: <20150530211306.18666.51873@psf.io> https://hg.python.org/peps/rev/eff8d4584f91 changeset: 5882:eff8d4584f91 user: Ned Deily date: Sat May 30 14:11:48 2015 -0700 summary: Add placeholder PEP 494, Python 3.6 Release Schedule files: pep-0494.txt | 68 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 68 insertions(+), 0 deletions(-) diff --git a/pep-0494.txt b/pep-0494.txt new file mode 100644 --- /dev/null +++ b/pep-0494.txt @@ -0,0 +1,68 @@ +PEP: 494 +Title: Python 3.6 Release Schedule +Version: $Revision$ +Last-Modified: $Date$ +Author: Ned Deily +Status: Active +Type: Informational +Content-Type: text/x-rst +Created: 30-May-2015 +Python-Version: 3.6 + + +Abstract +======== + +This document describes the development and release schedule for +Python 3.6. The schedule primarily concerns itself with PEP-sized +items. + +.. Small features may be added up to the first beta + release. Bugs may be fixed until the final release, + which is planned for September 2015. + + +Release Manager and Crew +======================== + +- 3.6 Release Manager: Ned Deily +- Windows installers: Steve Dower +- Mac installers: Ned Deily +- Documentation: Georg Brandl + + +Release Schedule +================ + +The releases: + +- 3.6.0 alpha 1: TBD +- 3.6.0 beta 1: TBD +- 3.6.0 candidate 1: TBD +- 3.6.0 final: TBD (late 2016?) + +(Beta 1 is also "feature freeze"--no new features beyond this point.) + + +Features for 3.6 +================ + +Proposed changes for 3.6: + +* TBD + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 31 01:56:34 2015 From: python-checkins at python.org (larry.hastings) Date: Sat, 30 May 2015 23:56:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Tweak_the_release_process--wh?= =?utf-8?q?y_not_check_for_errors_*before*_regenerating?= Message-ID: <20150530235633.18163.43467@psf.io> https://hg.python.org/peps/rev/941e73d5d758 changeset: 5883:941e73d5d758 user: Larry Hastings date: Sat May 30 16:56:30 2015 -0700 summary: Tweak the release process--why not check for errors *before* regenerating the topic index! files: pep-0101.txt | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -160,17 +160,18 @@ ___ Make sure the current branch of your release clone is the branch you want to release from. + ___ Check the docs for markup errors. + + cd to the Doc directory and run ``make suspicious``. If any markup + errors are found, fix them. + ___ Regenerate Lib/pydoc-topics.py. - cd to the Doc directory and type ``make pydoc-topics``. Then copy + While still in the Doc directory, run ``make pydoc-topics``. Then copy ``build/pydoc-topics/topics.py`` to ``../Lib/pydoc_data/topics.py``. - ___ Check the docs for markup errors. - - In the Doc directory, type ``make suspicious``. If any markup errors - are found, fix them. - - ___ Commit any changes to pydoc_topics.py and the doc sources. + ___ Commit your changes to pydoc_topics.py + (and any fixes you made in the docs). ___ Make sure the SOURCE_URI in ``Doc/tools/pyspecific.py`` points to the right branch in the hg repository (or ``default`` for -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 31 02:29:00 2015 From: python-checkins at python.org (larry.hastings) Date: Sun, 31 May 2015 00:29:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Change_SOURCE=5FURI_for_py?= =?utf-8?q?doc_source_URLs_to_point_back_to_correct_branch_for_3=2E6=2E?= Message-ID: <20150531002900.4342.85757@psf.io> https://hg.python.org/cpython/rev/673dc0b8a402 changeset: 96409:673dc0b8a402 user: Larry Hastings date: Sat May 30 17:28:56 2015 -0700 summary: Change SOURCE_URI for pydoc source URLs to point back to correct branch for 3.6. files: Doc/tools/extensions/pyspecific.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -34,7 +34,7 @@ ISSUE_URI = 'https://bugs.python.org/issue%s' -SOURCE_URI = 'https://hg.python.org/cpython/file/3.5/%s' +SOURCE_URI = 'https://hg.python.org/cpython/file/default/%s' # monkey-patch reST parser to disable alphabetic and roman enumerated lists from docutils.parsers.rst.states import Body -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 03:02:57 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 01:02:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24004=3A_Support_Awaitables_=28pep_492=29_in_=40as?= =?utf-8?q?yncio=2Ecoroutine_decorator?= Message-ID: <20150531010257.91795.64360@psf.io> https://hg.python.org/cpython/rev/6c53591d589b changeset: 96412:6c53591d589b parent: 96409:673dc0b8a402 parent: 96411:d1959cafc68c user: Yury Selivanov date: Sat May 30 21:02:49 2015 -0400 summary: Issue 24004: Support Awaitables (pep 492) in @asyncio.coroutine decorator (Merge 3.5) files: Lib/asyncio/coroutines.py | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -54,9 +54,10 @@ inspect.CO_COROUTINE) try: - from collections.abc import Coroutine as CoroutineABC + from collections.abc import Coroutine as CoroutineABC, \ + Awaitable as AwaitableABC except ImportError: - CoroutineABC = None + CoroutineABC = AwaitableABC = None # Check for CPython issue #21209 @@ -192,6 +193,16 @@ res = func(*args, **kw) if isinstance(res, futures.Future) or inspect.isgenerator(res): res = yield from res + elif AwaitableABC is not None: + # If 'func' returns an Awaitable (new in 3.5) we + # want to run it. + try: + await_meth = res.__await__ + except AttributeError: + pass + else: + if isinstance(res, AwaitableABC): + res = yield from await_meth() return res if not _DEBUG: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 03:02:57 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 01:02:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQwMDQ6?= =?utf-8?q?_Support_Awaitables_=28pep_492=29_in_=40asyncio=2Ecoroutine_dec?= =?utf-8?q?orator?= Message-ID: <20150531010256.111604.45471@psf.io> https://hg.python.org/cpython/rev/b7b73029c825 changeset: 96410:b7b73029c825 branch: 3.4 parent: 96390:943fa0e8b6a4 user: Yury Selivanov date: Sat May 30 21:02:12 2015 -0400 summary: Issue 24004: Support Awaitables (pep 492) in @asyncio.coroutine decorator files: Lib/asyncio/coroutines.py | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -54,9 +54,10 @@ inspect.CO_COROUTINE) try: - from collections.abc import Coroutine as CoroutineABC + from collections.abc import Coroutine as CoroutineABC, \ + Awaitable as AwaitableABC except ImportError: - CoroutineABC = None + CoroutineABC = AwaitableABC = None # Check for CPython issue #21209 @@ -192,6 +193,16 @@ res = func(*args, **kw) if isinstance(res, futures.Future) or inspect.isgenerator(res): res = yield from res + elif AwaitableABC is not None: + # If 'func' returns an Awaitable (new in 3.5) we + # want to run it. + try: + await_meth = res.__await__ + except AttributeError: + pass + else: + if isinstance(res, AwaitableABC): + res = yield from await_meth() return res if not _DEBUG: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 03:02:57 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 01:02:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_24004=3A_Support_Awaitables_=28pep_492=29_in_=40asyncio?= =?utf-8?q?=2Ecoroutine_decorator?= Message-ID: <20150531010257.83491.59458@psf.io> https://hg.python.org/cpython/rev/d1959cafc68c changeset: 96411:d1959cafc68c branch: 3.5 parent: 96407:e59966bb6de5 parent: 96410:b7b73029c825 user: Yury Selivanov date: Sat May 30 21:02:34 2015 -0400 summary: Issue 24004: Support Awaitables (pep 492) in @asyncio.coroutine decorator (Merge 3.4) files: Lib/asyncio/coroutines.py | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -54,9 +54,10 @@ inspect.CO_COROUTINE) try: - from collections.abc import Coroutine as CoroutineABC + from collections.abc import Coroutine as CoroutineABC, \ + Awaitable as AwaitableABC except ImportError: - CoroutineABC = None + CoroutineABC = AwaitableABC = None # Check for CPython issue #21209 @@ -192,6 +193,16 @@ res = func(*args, **kw) if isinstance(res, futures.Future) or inspect.isgenerator(res): res = yield from res + elif AwaitableABC is not None: + # If 'func' returns an Awaitable (new in 3.5) we + # want to run it. + try: + await_meth = res.__await__ + except AttributeError: + pass + else: + if isinstance(res, AwaitableABC): + res = yield from await_meth() return res if not _DEBUG: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 03:05:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 01:05:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQwMDQ6?= =?utf-8?q?_Add_a_unittest_for_=40asyncio=2Ecoroutine_supporting_Awaitable?= =?utf-8?q?s?= Message-ID: <20150531010509.18672.11727@psf.io> https://hg.python.org/cpython/rev/5f1e24f083c7 changeset: 96413:5f1e24f083c7 branch: 3.5 parent: 96411:d1959cafc68c user: Yury Selivanov date: Sat May 30 21:04:37 2015 -0400 summary: Issue 24004: Add a unittest for @asyncio.coroutine supporting Awaitables files: Lib/test/test_asyncio/test_pep492.py | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -106,6 +106,19 @@ self.assertTrue(asyncio.iscoroutine(FakeCoro())) + def test_function_returning_awaitable(self): + class Awaitable: + def __await__(self): + return ('spam',) + + @asyncio.coroutine + def func(): + return Awaitable() + + coro = func() + self.assertEquals(coro.send(None), 'spam') + coro.close() + if __name__ == '__main__': unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 03:05:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 01:05:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24004=3A_Add_a_unittest_for_=40asyncio=2Ecoroutine?= =?utf-8?q?_supporting_Awaitables?= Message-ID: <20150531010509.89791.81207@psf.io> https://hg.python.org/cpython/rev/9d261141eb0c changeset: 96414:9d261141eb0c parent: 96412:6c53591d589b parent: 96413:5f1e24f083c7 user: Yury Selivanov date: Sat May 30 21:04:58 2015 -0400 summary: Issue 24004: Add a unittest for @asyncio.coroutine supporting Awaitables (Merge 3.5) files: Lib/test/test_asyncio/test_pep492.py | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -106,6 +106,19 @@ self.assertTrue(asyncio.iscoroutine(FakeCoro())) + def test_function_returning_awaitable(self): + class Awaitable: + def __await__(self): + return ('spam',) + + @asyncio.coroutine + def func(): + return Awaitable() + + coro = func() + self.assertEquals(coro.send(None), 'spam') + coro.close() + if __name__ == '__main__': unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 07:02:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 05:02:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxODUz?= =?utf-8?q?=3A_Fixed_the_inspect_module_in_unicode_disabled_build=2E?= Message-ID: <20150531050215.91787.24954@psf.io> https://hg.python.org/cpython/rev/44590c1b264e changeset: 96415:44590c1b264e branch: 2.7 parent: 96385:14d1018940cb user: Serhiy Storchaka date: Sun May 31 08:01:00 2015 +0300 summary: Issue #21853: Fixed the inspect module in unicode disabled build. files: Lib/inspect.py | 9 +++++++-- Lib/test/test_inspect.py | 10 +++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -969,8 +969,13 @@ assign(varkw, named) elif named: unexpected = next(iter(named)) - if isinstance(unexpected, unicode): - unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') + try: + unicode + except NameError: + pass + else: + if isinstance(unexpected, unicode): + unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') raise TypeError("%s() got an unexpected keyword argument '%s'" % (f_name, unexpected)) unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -8,7 +8,7 @@ from UserList import UserList from UserDict import UserDict -from test.test_support import run_unittest, check_py3k_warnings +from test.test_support import run_unittest, check_py3k_warnings, have_unicode with check_py3k_warnings( ("tuple parameter unpacking has been removed", SyntaxWarning), @@ -17,7 +17,10 @@ from test import inspect_fodder2 as mod2 # C module for test_findsource_binary -import unicodedata +try: + import unicodedata +except ImportError: + unicodedata = None # Functions tested in this suite: # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, @@ -798,7 +801,8 @@ self.assertEqualException(f, '2, c=3') self.assertEqualException(f, '2, 3, c=4') self.assertEqualException(f, '2, c=4, b=3') - self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}') + if have_unicode: + self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}') # f got multiple values for keyword argument self.assertEqualException(f, '1, a=2') self.assertEqualException(f, '1, **{"a":2}') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 07:22:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 31 May 2015 05:22:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_improve_sectio?= =?utf-8?q?n_title?= Message-ID: <20150531052254.91777.38470@psf.io> https://hg.python.org/cpython/rev/a09cc60d89db changeset: 96416:a09cc60d89db branch: 3.5 parent: 96413:5f1e24f083c7 user: Benjamin Peterson date: Sun May 31 00:22:42 2015 -0500 summary: improve section title files: Doc/whatsnew/3.5.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -151,8 +151,8 @@ :pep:`492` -- Coroutines with async and await syntax -PEP 461 - Adding formatting to bytes and bytearray --------------------------------------------------- +PEP 461 - Formatting support for bytes and bytearray +---------------------------------------------------- This PEP proposes adding % formatting operations similar to Python 2's ``str`` type to :class:`bytes` and :class:`bytearray`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 07:22:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 31 May 2015 05:22:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41?= Message-ID: <20150531052254.25409.501@psf.io> https://hg.python.org/cpython/rev/85c22fe713a3 changeset: 96417:85c22fe713a3 parent: 96414:9d261141eb0c parent: 96416:a09cc60d89db user: Benjamin Peterson date: Sun May 31 00:22:49 2015 -0500 summary: merge 3.5 files: Doc/whatsnew/3.5.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -151,8 +151,8 @@ :pep:`492` -- Coroutines with async and await syntax -PEP 461 - Adding formatting to bytes and bytearray --------------------------------------------------- +PEP 461 - Formatting support for bytes and bytearray +---------------------------------------------------- This PEP proposes adding % formatting operations similar to Python 2's ``str`` type to :class:`bytes` and :class:`bytearray`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 08:06:15 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 06:06:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MjY0?= =?utf-8?q?=3A_Fixed_buffer_overflow_in_the_imageop_module=2E?= Message-ID: <20150531060615.91783.66182@psf.io> https://hg.python.org/cpython/rev/de0ccaaf2e64 changeset: 96418:de0ccaaf2e64 branch: 2.7 parent: 96415:44590c1b264e user: Serhiy Storchaka date: Sun May 31 09:05:10 2015 +0300 summary: Issue #24264: Fixed buffer overflow in the imageop module. files: Lib/test/test_imageop.py | 4 +++- Misc/NEWS | 2 ++ Modules/imageop.c | 7 +++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_imageop.py b/Lib/test/test_imageop.py --- a/Lib/test/test_imageop.py +++ b/Lib/test/test_imageop.py @@ -61,7 +61,9 @@ self.check("rgb82rgb") self.check("rgb2grey") self.check("grey2rgb") - + # Issue #24264: Buffer overflow + with self.assertRaises(imageop.error): + imageop.grey2rgb('A'*256, 1, 129) def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,8 @@ Library ------- +- Issue #24264: Fixed buffer overflow in the imageop module. + - Issue #5633: Fixed timeit when the statement is a string and the setup is not. - Issue #24326: Fixed audioop.ratecv() with non-default weightB argument. diff --git a/Modules/imageop.c b/Modules/imageop.c --- a/Modules/imageop.c +++ b/Modules/imageop.c @@ -50,8 +50,11 @@ return 0; if ( !check_coordonnate(y, yname) ) return 0; - if ( size == (product / y) / x ) - return 1; + if ( product % y == 0 ) { + product /= y; + if ( product % x == 0 && size == product / x ) + return 1; + } PyErr_SetString(ImageopError, "String has incorrect length"); return 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 08:17:02 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 06:17:02 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjg0?= =?utf-8?q?=3A_The_startswith_and_endswith_methods_of_the_str_class_no_lon?= =?utf-8?q?ger?= Message-ID: <20150531061702.91787.83531@psf.io> https://hg.python.org/cpython/rev/a82498f424fe changeset: 96419:a82498f424fe branch: 3.5 parent: 96416:a09cc60d89db user: Serhiy Storchaka date: Sun May 31 09:15:51 2015 +0300 summary: Issue #24284: The startswith and endswith methods of the str class no longer return True when finding the empty string and the indexes are completely out of range. files: Doc/whatsnew/3.5.rst | 4 ++++ Lib/test/string_tests.py | 6 ++++++ Misc/NEWS | 4 ++++ Objects/unicodeobject.c | 6 +++--- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1049,6 +1049,10 @@ program depends on patching the module level variable to capture the debug output, you will need to update it to capture sys.stderr instead. +* The :meth:`str.startswith` and :meth:`str.endswith` methods no longer return + ``True`` when finding the empty string and the indexes are completely out of + range. See :issue:`24284`. + Changes in the C API -------------------- diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -976,6 +976,9 @@ self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3) self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3, 7) self.checkequal(False, 'helloworld', 'startswith', 'lowo', 3, 6) + self.checkequal(True, '', 'startswith', '', 0, 1) + self.checkequal(True, '', 'startswith', '', 0, 0) + self.checkequal(False, '', 'startswith', '', 1, 0) # test negative indices self.checkequal(True, 'hello', 'startswith', 'he', 0, -1) @@ -1022,6 +1025,9 @@ self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, 8) self.checkequal(False, 'ab', 'endswith', 'ab', 0, 1) self.checkequal(False, 'ab', 'endswith', 'ab', 0, 0) + self.checkequal(True, '', 'endswith', '', 0, 1) + self.checkequal(True, '', 'endswith', '', 0, 0) + self.checkequal(False, '', 'endswith', '', 1, 0) # test negative indices self.checkequal(True, 'hello', 'endswith', 'lo', -2) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24284: The startswith and endswith methods of the str class no longer + return True when finding the empty string and the indexes are completely out + of range. + - Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9280,14 +9280,14 @@ PyUnicode_READY(substring) == -1) return -1; - if (PyUnicode_GET_LENGTH(substring) == 0) - return 1; - ADJUST_INDICES(start, end, PyUnicode_GET_LENGTH(self)); end -= PyUnicode_GET_LENGTH(substring); if (end < start) return 0; + if (PyUnicode_GET_LENGTH(substring) == 0) + return 1; + kind_self = PyUnicode_KIND(self); data_self = PyUnicode_DATA(self); kind_sub = PyUnicode_KIND(substring); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 08:17:02 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 06:17:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324284=3A_The_startswith_and_endswith_methods_of?= =?utf-8?q?_the_str_class_no_longer?= Message-ID: <20150531061702.25407.46060@psf.io> https://hg.python.org/cpython/rev/04162e06323f changeset: 96420:04162e06323f parent: 96417:85c22fe713a3 parent: 96419:a82498f424fe user: Serhiy Storchaka date: Sun May 31 09:16:13 2015 +0300 summary: Issue #24284: The startswith and endswith methods of the str class no longer return True when finding the empty string and the indexes are completely out of range. files: Doc/whatsnew/3.5.rst | 4 ++++ Lib/test/string_tests.py | 6 ++++++ Misc/NEWS | 4 ++++ Objects/unicodeobject.c | 6 +++--- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1049,6 +1049,10 @@ program depends on patching the module level variable to capture the debug output, you will need to update it to capture sys.stderr instead. +* The :meth:`str.startswith` and :meth:`str.endswith` methods no longer return + ``True`` when finding the empty string and the indexes are completely out of + range. See :issue:`24284`. + Changes in the C API -------------------- diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -976,6 +976,9 @@ self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3) self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3, 7) self.checkequal(False, 'helloworld', 'startswith', 'lowo', 3, 6) + self.checkequal(True, '', 'startswith', '', 0, 1) + self.checkequal(True, '', 'startswith', '', 0, 0) + self.checkequal(False, '', 'startswith', '', 1, 0) # test negative indices self.checkequal(True, 'hello', 'startswith', 'he', 0, -1) @@ -1022,6 +1025,9 @@ self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, 8) self.checkequal(False, 'ab', 'endswith', 'ab', 0, 1) self.checkequal(False, 'ab', 'endswith', 'ab', 0, 0) + self.checkequal(True, '', 'endswith', '', 0, 1) + self.checkequal(True, '', 'endswith', '', 0, 0) + self.checkequal(False, '', 'endswith', '', 1, 0) # test negative indices self.checkequal(True, 'hello', 'endswith', 'lo', -2) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,10 @@ Core and Builtins ----------------- +- Issue #24284: The startswith and endswith methods of the str class no longer + return True when finding the empty string and the indexes are completely out + of range. + - Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9280,14 +9280,14 @@ PyUnicode_READY(substring) == -1) return -1; - if (PyUnicode_GET_LENGTH(substring) == 0) - return 1; - ADJUST_INDICES(start, end, PyUnicode_GET_LENGTH(self)); end -= PyUnicode_GET_LENGTH(substring); if (end < start) return 0; + if (PyUnicode_GET_LENGTH(substring) == 0) + return 1; + kind_self = PyUnicode_KIND(self); data_self = PyUnicode_DATA(self); kind_sub = PyUnicode_KIND(substring); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 10:57:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 08:57:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_the_arra?= =?utf-8?q?y_module_in_unicode_disabled_build_=28regression_of_issue20014?= =?utf-8?b?KS4=?= Message-ID: <20150531085728.4354.4220@psf.io> https://hg.python.org/cpython/rev/6ee122fac1e8 changeset: 96421:6ee122fac1e8 branch: 2.7 parent: 96418:de0ccaaf2e64 user: Serhiy Storchaka date: Sun May 31 11:56:48 2015 +0300 summary: Fixed the array module in unicode disabled build (regression of issue20014). files: Lib/test/test_array.py | 5 ++++- Modules/arraymodule.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -18,7 +18,9 @@ array.array.__init__(self, typecode) tests = [] # list to accumulate all tests -typecodes = "cubBhHiIlLfd" +typecodes = "cbBhHiIlLfd" +if test_support.have_unicode: + typecodes += "u" class BadConstructorTest(unittest.TestCase): @@ -837,6 +839,7 @@ self.assertEqual(s.color, "red") self.assertEqual(s.__dict__.keys(), ["color"]) + @test_support.requires_unicode def test_nounicode(self): a = array.array(self.typecode, self.example) self.assertRaises(ValueError, a.fromunicode, unicode('')) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1940,8 +1940,10 @@ if (PyString_Check(typecode) && PyString_GET_SIZE(typecode) == 1) c = (unsigned char)*PyString_AS_STRING(typecode); +#ifdef Py_USING_UNICODE else if (PyUnicode_Check(typecode) && PyUnicode_GET_SIZE(typecode) == 1) c = *PyUnicode_AS_UNICODE(typecode); +#endif else { PyErr_Format(PyExc_TypeError, "array() argument 1 or typecode must be char (string or " -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 11:06:04 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 09:06:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRml4ZWQgdGVzdF9h?= =?utf-8?q?udioop_for_issue_=2324326=2E?= Message-ID: <20150531090604.4336.68788@psf.io> https://hg.python.org/cpython/rev/7d6a6028b104 changeset: 96422:7d6a6028b104 branch: 2.7 user: Serhiy Storchaka date: Sun May 31 12:05:40 2015 +0300 summary: Fixed test_audioop for issue #24326. 24-bit samples are not supported in 2.7. files: Lib/test/test_audioop.py | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -301,12 +301,10 @@ expected = { 1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14), 2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a), - 3: packs[3](0, 0x0da740, 0x377776, -0x262fca, - 0x56740c, -0x4a62fd, -0x1298c0), 4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962, 0x56740da6, -0x4a62fc96, -0x1298bf26), } - for w in 1, 2, 3, 4: + for w in 1, 2, 4: self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0], expected[w]) self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0], -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun May 31 11:23:32 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 31 May 2015 09:23:32 +0000 Subject: [Python-checkins] Daily reference leaks (85c22fe713a3): sum=709 Message-ID: <20150531092331.111612.57926@psf.io> results for 85c22fe713a3 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [122, 122, 122] references, sum=366 test_collections leaked [38, 38, 38] memory blocks, sum=114 test_functools leaked [0, 2, 2] memory blocks, sum=4 test_importlib leaked [50, 50, 50] references, sum=150 test_importlib leaked [24, 24, 24] memory blocks, sum=72 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghRW0HO', '--timeout', '7200'] From python-checkins at python.org Sun May 31 17:29:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 15:29:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24004=3A_Fix_DeprecationWarning_in_a_unittest?= Message-ID: <20150531152903.24097.66109@psf.io> https://hg.python.org/cpython/rev/60f5091cbfbf changeset: 96424:60f5091cbfbf parent: 96420:04162e06323f parent: 96423:8296f0119f20 user: Yury Selivanov date: Sun May 31 11:28:57 2015 -0400 summary: Issue 24004: Fix DeprecationWarning in a unittest (Merge from 3.5) files: Lib/test/test_asyncio/test_pep492.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -116,7 +116,7 @@ return Awaitable() coro = func() - self.assertEquals(coro.send(None), 'spam') + self.assertEqual(coro.send(None), 'spam') coro.close() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 17:29:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 15:29:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQwMDQ6?= =?utf-8?q?_Fix_DeprecationWarning_in_a_unittest?= Message-ID: <20150531152903.89785.63076@psf.io> https://hg.python.org/cpython/rev/8296f0119f20 changeset: 96423:8296f0119f20 branch: 3.5 parent: 96419:a82498f424fe user: Yury Selivanov date: Sun May 31 11:28:35 2015 -0400 summary: Issue 24004: Fix DeprecationWarning in a unittest files: Lib/test/test_asyncio/test_pep492.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -116,7 +116,7 @@ return Awaitable() coro = func() - self.assertEquals(coro.send(None), 'spam') + self.assertEqual(coro.send(None), 'spam') coro.close() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 19:21:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 31 May 2015 17:21:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5NTQz?= =?utf-8?q?=3A_Emit_deprecation_warning_for_known_non-text_encodings=2E?= Message-ID: <20150531172138.27668.94130@psf.io> https://hg.python.org/cpython/rev/cf6e782a7f94 changeset: 96425:cf6e782a7f94 branch: 2.7 parent: 96422:7d6a6028b104 user: Serhiy Storchaka date: Sun May 31 20:21:00 2015 +0300 summary: Issue #19543: Emit deprecation warning for known non-text encodings. Backported issues #19619: encode() and decode() methods and constructors of str, unicode and bytearray classes now emit deprecation warning for known non-text encodings when Python is ran with the -3 option. Backported issues #20404: io.TextIOWrapper (and hence io.open()) now uses the internal codec marking system added to emit deprecation warning for known non-text encodings at stream construction time when Python is ran with the -3 option. files: Include/codecs.h | 45 ++++ Lib/_pyio.py | 6 + Lib/codecs.py | 14 +- Lib/encodings/base64_codec.py | 1 + Lib/encodings/bz2_codec.py | 1 + Lib/encodings/hex_codec.py | 1 + Lib/encodings/quopri_codec.py | 1 + Lib/encodings/rot_13.py | 1 + Lib/encodings/uu_codec.py | 1 + Lib/encodings/zlib_codec.py | 1 + Lib/json/decoder.py | 6 +- Lib/test/string_tests.py | 12 +- Lib/test/test_calendar.py | 4 +- Lib/test/test_codecs.py | 48 ++++- Lib/test/test_fileinput.py | 7 +- Lib/test/test_io.py | 43 +++- Misc/NEWS | 8 + Modules/_io/textio.c | 34 ++- Objects/bytearrayobject.c | 6 +- Objects/stringobject.c | 4 +- Objects/unicodeobject.c | 8 +- Python/codecs.c | 213 +++++++++++++++++++-- 22 files changed, 393 insertions(+), 72 deletions(-) diff --git a/Include/codecs.h b/Include/codecs.h --- a/Include/codecs.h +++ b/Include/codecs.h @@ -81,6 +81,51 @@ const char *errors ); +/* Text codec specific encoding and decoding API. + + Checks the encoding against a list of codecs which do not + implement a unicode<->bytes encoding before attempting the + operation. + + Please note that these APIs are internal and should not + be used in Python C extensions. + + XXX (ncoghlan): should we make these, or something like them, public + in Python 3.5+? + + */ +PyAPI_FUNC(PyObject *) _PyCodec_LookupTextEncoding( + const char *encoding, + const char *alternate_command + ); + +PyAPI_FUNC(PyObject *) _PyCodec_EncodeText( + PyObject *object, + const char *encoding, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodec_DecodeText( + PyObject *object, + const char *encoding, + const char *errors + ); + +/* These two aren't actually text encoding specific, but _io.TextIOWrapper + * is the only current API consumer. + */ +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalDecoder( + PyObject *codec_info, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalEncoder( + PyObject *codec_info, + const char *errors + ); + + + /* --- Codec Lookup APIs -------------------------------------------------- All APIs return a codec object with incremented refcount and are diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -7,6 +7,7 @@ import os import abc import codecs +import sys import warnings import errno # Import thread instead of threading to reduce startup cost @@ -1497,6 +1498,11 @@ if not isinstance(encoding, basestring): raise ValueError("invalid encoding: %r" % encoding) + if sys.py3kwarning and not codecs.lookup(encoding)._is_text_encoding: + msg = ("%r is not a text encoding; " + "use codecs.open() to handle arbitrary codecs") + warnings.warnpy3k(msg % encoding, stacklevel=2) + if errors is None: errors = "strict" else: diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -79,9 +79,19 @@ ### Codec base classes (defining the API) class CodecInfo(tuple): + """Codec details when looking up the codec registry""" + + # Private API to allow Python to blacklist the known non-Unicode + # codecs in the standard library. A more general mechanism to + # reliably distinguish test encodings from other codecs will hopefully + # be defined for Python 3.5 + # + # See http://bugs.python.org/issue19619 + _is_text_encoding = True # Assume codecs are text encodings by default def __new__(cls, encode, decode, streamreader=None, streamwriter=None, - incrementalencoder=None, incrementaldecoder=None, name=None): + incrementalencoder=None, incrementaldecoder=None, name=None, + _is_text_encoding=None): self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter)) self.name = name self.encode = encode @@ -90,6 +100,8 @@ self.incrementaldecoder = incrementaldecoder self.streamwriter = streamwriter self.streamreader = streamreader + if _is_text_encoding is not None: + self._is_text_encoding = _is_text_encoding return self def __repr__(self): diff --git a/Lib/encodings/base64_codec.py b/Lib/encodings/base64_codec.py --- a/Lib/encodings/base64_codec.py +++ b/Lib/encodings/base64_codec.py @@ -76,4 +76,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/bz2_codec.py b/Lib/encodings/bz2_codec.py --- a/Lib/encodings/bz2_codec.py +++ b/Lib/encodings/bz2_codec.py @@ -99,4 +99,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/hex_codec.py b/Lib/encodings/hex_codec.py --- a/Lib/encodings/hex_codec.py +++ b/Lib/encodings/hex_codec.py @@ -76,4 +76,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/quopri_codec.py b/Lib/encodings/quopri_codec.py --- a/Lib/encodings/quopri_codec.py +++ b/Lib/encodings/quopri_codec.py @@ -72,4 +72,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/rot_13.py b/Lib/encodings/rot_13.py --- a/Lib/encodings/rot_13.py +++ b/Lib/encodings/rot_13.py @@ -44,6 +44,7 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) ### Decoding Map diff --git a/Lib/encodings/uu_codec.py b/Lib/encodings/uu_codec.py --- a/Lib/encodings/uu_codec.py +++ b/Lib/encodings/uu_codec.py @@ -126,4 +126,5 @@ incrementaldecoder=IncrementalDecoder, streamreader=StreamReader, streamwriter=StreamWriter, + _is_text_encoding=False, ) diff --git a/Lib/encodings/zlib_codec.py b/Lib/encodings/zlib_codec.py --- a/Lib/encodings/zlib_codec.py +++ b/Lib/encodings/zlib_codec.py @@ -99,4 +99,5 @@ incrementaldecoder=IncrementalDecoder, streamreader=StreamReader, streamwriter=StreamWriter, + _is_text_encoding=False, ) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -15,10 +15,8 @@ FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL def _floatconstants(): - _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') - if sys.byteorder != 'big': - _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] - nan, inf = struct.unpack('dd', _BYTES) + nan, = struct.unpack('>d', b'\x7f\xf8\x00\x00\x00\x00\x00\x00') + inf, = struct.unpack('>d', b'\x7f\xf0\x00\x00\x00\x00\x00\x00') return nan, inf, -inf NaN, PosInf, NegInf = _floatconstants() diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -1295,8 +1295,10 @@ ('hex', '68656c6c6f20776f726c64'), ('uu', 'begin 666 \n+:&5L;&\\@=V]R;&0 \n \nend\n')] for encoding, data in codecs: - self.checkequal(data, 'hello world', 'encode', encoding) - self.checkequal('hello world', data, 'decode', encoding) + with test_support.check_py3k_warnings(): + self.checkequal(data, 'hello world', 'encode', encoding) + with test_support.check_py3k_warnings(): + self.checkequal('hello world', data, 'decode', encoding) # zlib is optional, so we make the test optional too... try: import zlib @@ -1304,8 +1306,10 @@ pass else: data = 'x\x9c\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\x01\x00\x1a\x0b\x04]' - self.checkequal(data, 'hello world', 'encode', 'zlib') - self.checkequal('hello world', data, 'decode', 'zlib') + with test_support.check_py3k_warnings(): + self.checkequal(data, 'hello world', 'encode', 'zlib') + with test_support.check_py3k_warnings(): + self.checkequal('hello world', data, 'decode', 'zlib') self.checkraises(TypeError, 'xyz', 'decode', 42) self.checkraises(TypeError, 'xyz', 'encode', 42) diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -513,8 +513,8 @@ def test_option_encoding(self): self.assertFailure('-e') self.assertFailure('--encoding') - stdout = self.run_ok('--encoding', 'rot-13', '2004') - self.assertEqual(stdout.strip(), conv(result_2004_text.encode('rot-13')).strip()) + stdout = self.run_ok('--encoding', 'utf-16-le', '2004') + self.assertEqual(stdout.strip(), conv(result_2004_text.encode('utf-16-le')).strip()) def test_option_locale(self): self.assertFailure('-L') diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1395,14 +1395,14 @@ class Str2StrTest(unittest.TestCase): def test_read(self): - sin = "\x80".encode("base64_codec") + sin = codecs.encode("\x80", "base64_codec") reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) sout = reader.read() self.assertEqual(sout, "\x80") self.assertIsInstance(sout, str) def test_readline(self): - sin = "\x80".encode("base64_codec") + sin = codecs.encode("\x80", "base64_codec") reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) sout = reader.readline() self.assertEqual(sout, "\x80") @@ -1536,6 +1536,9 @@ ] broken_incremental_coders = broken_unicode_with_streams[:] +if sys.flags.py3k_warning: + broken_unicode_with_streams.append("rot_13") + # The following encodings only support "strict" mode only_strict_mode = [ "idna", @@ -2135,6 +2138,47 @@ # Missing "begin" line self.assertRaises(ValueError, codecs.decode, "", "uu-codec") + def test_text_to_binary_blacklists_binary_transforms(self): + # Check binary -> binary codecs give a good error for str input + bad_input = "bad input type" + for encoding in bytes_transform_encodings: + fmt = (r"{!r} is not a text encoding; " + r"use codecs.encode\(\) to handle arbitrary codecs") + msg = fmt.format(encoding) + with self.assertRaisesRegex(LookupError, msg) as failure: + bad_input.encode(encoding) + self.assertIsNone(failure.exception.__cause__) + + def test_text_to_binary_blacklists_text_transforms(self): + # Check str.encode gives a good error message for str -> str codecs + msg = (r"^'rot_13' is not a text encoding; " + r"use codecs.encode\(\) to handle arbitrary codecs") + with self.assertRaisesRegex(LookupError, msg): + "just an example message".encode("rot_13") + + def test_binary_to_text_blacklists_binary_transforms(self): + # Check bytes.decode and bytearray.decode give a good error + # message for binary -> binary codecs + data = b"encode first to ensure we meet any format restrictions" + for encoding in bytes_transform_encodings: + encoded_data = codecs.encode(data, encoding) + fmt = (r"{!r} is not a text encoding; " + r"use codecs.decode\(\) to handle arbitrary codecs") + msg = fmt.format(encoding) + with self.assertRaisesRegex(LookupError, msg): + encoded_data.decode(encoding) + with self.assertRaisesRegex(LookupError, msg): + bytearray(encoded_data).decode(encoding) + + def test_binary_to_text_blacklists_text_transforms(self): + # Check str -> str codec gives a good error for binary input + for bad_input in (b"immutable", bytearray(b"mutable")): + msg = (r"^'rot_13' is not a text encoding; " + r"use codecs.decode\(\) to handle arbitrary codecs") + with self.assertRaisesRegex(LookupError, msg) as failure: + bad_input.decode("rot_13") + self.assertIsNone(failure.exception.__cause__) + if __name__ == "__main__": test_main() diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -211,10 +211,11 @@ except ValueError: pass try: - t1 = writeTmp(1, ["A\nB"], mode="wb") - fi = FileInput(files=t1, openhook=hook_encoded("rot13")) + # UTF-7 is a convenient, seldom used encoding + t1 = writeTmp(1, ['+AEE-\n+AEI-'], mode="wb") + fi = FileInput(files=t1, openhook=hook_encoded("utf-7")) lines = list(fi) - self.assertEqual(lines, ["N\n", "O"]) + self.assertEqual(lines, [u'A\n', u'B']) finally: remove_tempfiles(t1) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2001,6 +2001,15 @@ t.__init__(self.MockRawIO()) self.assertEqual(t.read(0), u'') + def test_non_text_encoding_codecs_are_rejected(self): + # Ensure the constructor complains if passed a codec that isn't + # marked as a text encoding + # http://bugs.python.org/issue20404 + r = self.BytesIO() + b = self.BufferedWriter(r) + with support.check_py3k_warnings(): + self.TextIOWrapper(b, encoding="hex_codec") + def test_detach(self): r = self.BytesIO() b = self.BufferedWriter(r) @@ -2617,19 +2626,39 @@ def test_illegal_decoder(self): # Issue #17106 + # Bypass the early encoding check added in issue 20404 + def _make_illegal_wrapper(): + quopri = codecs.lookup("quopri_codec") + quopri._is_text_encoding = True + try: + t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), + newline='\n', encoding="quopri_codec") + finally: + quopri._is_text_encoding = False + return t # Crash when decoder returns non-string - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + with support.check_py3k_warnings(): + t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', + encoding='quopri_codec') with self.maybeRaises(TypeError): t.read(1) - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + with support.check_py3k_warnings(): + t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', + encoding='quopri_codec') with self.maybeRaises(TypeError): t.readline() - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + with support.check_py3k_warnings(): + t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', + encoding='quopri_codec') with self.maybeRaises(TypeError): t.read() + #else: + #t = _make_illegal_wrapper() + #self.assertRaises(TypeError, t.read, 1) + #t = _make_illegal_wrapper() + #self.assertRaises(TypeError, t.readline) + #t = _make_illegal_wrapper() + #self.assertRaises(TypeError, t.read) class CTextIOWrapperTest(TextIOWrapperTest): @@ -3002,9 +3031,11 @@ class CMiscIOTest(MiscIOTest): io = io + shutdown_error = "RuntimeError: could not find io module state" class PyMiscIOTest(MiscIOTest): io = pyio + shutdown_error = "LookupError: unknown encoding: ascii" @unittest.skipIf(os.name == 'nt', 'POSIX signals required for this test.') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #19543: encode() and decode() methods and constructors of str, + unicode and bytearray classes now emit deprecation warning for known + non-text encodings when Python is ran with the -3 option. + - Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. @@ -26,6 +30,10 @@ Library ------- +- Issue #19543: io.TextIOWrapper (and hence io.open()) now uses the internal + codec marking system added to emit deprecation warning for known non-text + encodings at stream construction time when Python is ran with the -3 option. + - Issue #24264: Fixed buffer overflow in the imageop module. - Issue #5633: Fixed timeit when the statement is a string and the setup is not. diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -826,7 +826,7 @@ char *kwlist[] = {"buffer", "encoding", "errors", "newline", "line_buffering", NULL}; - PyObject *buffer, *raw; + PyObject *buffer, *raw, *codec_info = NULL; char *encoding = NULL; char *errors = NULL; char *newline = NULL; @@ -909,6 +909,17 @@ "could not determine default encoding"); } + /* Check we have been asked for a real text encoding */ + codec_info = _PyCodec_LookupTextEncoding(encoding, "codecs.open()"); + if (codec_info == NULL) { + Py_CLEAR(self->encoding); + goto error; + } + + /* XXX: Failures beyond this point have the potential to leak elements + * of the partially constructed object (like self->encoding) + */ + if (errors == NULL) errors = "strict"; self->errors = PyBytes_FromString(errors); @@ -922,7 +933,7 @@ if (newline) { self->readnl = PyString_FromString(newline); if (self->readnl == NULL) - return -1; + goto error; } self->writetranslate = (newline == NULL || newline[0] != '\0'); if (!self->readuniversal && self->writetranslate) { @@ -944,8 +955,8 @@ if (r == -1) goto error; if (r == 1) { - self->decoder = PyCodec_IncrementalDecoder( - encoding, errors); + self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, + errors); if (self->decoder == NULL) goto error; @@ -969,17 +980,12 @@ if (r == -1) goto error; if (r == 1) { - PyObject *ci; - self->encoder = PyCodec_IncrementalEncoder( - encoding, errors); + self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, + errors); if (self->encoder == NULL) goto error; /* Get the normalized named of the codec */ - ci = _PyCodec_Lookup(encoding); - if (ci == NULL) - goto error; - res = PyObject_GetAttrString(ci, "name"); - Py_DECREF(ci); + res = PyObject_GetAttrString(codec_info, "name"); if (res == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); @@ -999,6 +1005,9 @@ Py_XDECREF(res); } + /* Finished sorting out the codec details */ + Py_DECREF(codec_info); + self->buffer = buffer; Py_INCREF(buffer); @@ -1059,6 +1068,7 @@ return 0; error: + Py_XDECREF(codec_info); return -1; } diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -783,7 +783,7 @@ if (PyBytes_Check(arg)) { PyObject *new, *encoded; if (encoding != NULL) { - encoded = PyCodec_Encode(arg, encoding, errors); + encoded = _PyCodec_EncodeText(arg, encoding, errors); if (encoded == NULL) return -1; assert(PyBytes_Check(encoded)); @@ -809,7 +809,7 @@ "unicode argument without an encoding"); return -1; } - encoded = PyCodec_Encode(arg, encoding, errors); + encoded = _PyCodec_EncodeText(arg, encoding, errors); if (encoded == NULL) return -1; assert(PyBytes_Check(encoded)); @@ -2567,7 +2567,7 @@ return NULL; #endif } - return PyCodec_Decode(self, encoding, errors); + return _PyCodec_DecodeText(self, encoding, errors); } PyDoc_STRVAR(alloc_doc, diff --git a/Objects/stringobject.c b/Objects/stringobject.c --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -449,7 +449,7 @@ } /* Decode via the codec registry */ - v = PyCodec_Decode(str, encoding, errors); + v = _PyCodec_DecodeText(str, encoding, errors); if (v == NULL) goto onError; @@ -529,7 +529,7 @@ } /* Encode via the codec registry */ - v = PyCodec_Encode(str, encoding, errors); + v = _PyCodec_EncodeText(str, encoding, errors); if (v == NULL) goto onError; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1259,7 +1259,7 @@ buffer = PyBuffer_FromMemory((void *)s, size); if (buffer == NULL) goto onError; - unicode = PyCodec_Decode(buffer, encoding, errors); + unicode = _PyCodec_DecodeText(buffer, encoding, errors); if (unicode == NULL) goto onError; if (!PyUnicode_Check(unicode)) { @@ -1292,7 +1292,7 @@ encoding = PyUnicode_GetDefaultEncoding(); /* Decode via the codec registry */ - v = PyCodec_Decode(unicode, encoding, errors); + v = _PyCodec_DecodeText(unicode, encoding, errors); if (v == NULL) goto onError; return v; @@ -1331,7 +1331,7 @@ encoding = PyUnicode_GetDefaultEncoding(); /* Encode via the codec registry */ - v = PyCodec_Encode(unicode, encoding, errors); + v = _PyCodec_EncodeText(unicode, encoding, errors); if (v == NULL) goto onError; return v; @@ -1369,7 +1369,7 @@ } /* Encode via the codec registry */ - v = PyCodec_Encode(unicode, encoding, errors); + v = _PyCodec_EncodeText(unicode, encoding, errors); if (v == NULL) goto onError; if (!PyString_Check(v)) { diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -217,20 +217,15 @@ return v; } -/* Helper function to create an incremental codec. */ +/* Helper functions to create an incremental codec. */ +static +PyObject *codec_makeincrementalcodec(PyObject *codec_info, + const char *errors, + const char *attrname) +{ + PyObject *ret, *inccodec; -static -PyObject *codec_getincrementalcodec(const char *encoding, - const char *errors, - const char *attrname) -{ - PyObject *codecs, *ret, *inccodec; - - codecs = _PyCodec_Lookup(encoding); - if (codecs == NULL) - return NULL; - inccodec = PyObject_GetAttrString(codecs, attrname); - Py_DECREF(codecs); + inccodec = PyObject_GetAttrString(codec_info, attrname); if (inccodec == NULL) return NULL; if (errors) @@ -241,6 +236,21 @@ return ret; } +static +PyObject *codec_getincrementalcodec(const char *encoding, + const char *errors, + const char *attrname) +{ + PyObject *codec_info, *ret; + + codec_info = _PyCodec_Lookup(encoding); + if (codec_info == NULL) + return NULL; + ret = codec_makeincrementalcodec(codec_info, errors, attrname); + Py_DECREF(codec_info); + return ret; +} + /* Helper function to create a stream codec. */ static @@ -264,6 +274,24 @@ return streamcodec; } +/* Helpers to work with the result of _PyCodec_Lookup + + */ +PyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info, + const char *errors) +{ + return codec_makeincrementalcodec(codec_info, errors, + "incrementaldecoder"); +} + +PyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info, + const char *errors) +{ + return codec_makeincrementalcodec(codec_info, errors, + "incrementalencoder"); +} + + /* Convenience APIs to query the Codec registry. All APIs return a codec object with incremented refcount. @@ -311,18 +339,15 @@ errors is passed to the encoder factory as argument if non-NULL. */ -PyObject *PyCodec_Encode(PyObject *object, - const char *encoding, - const char *errors) +static PyObject * +_PyCodec_EncodeInternal(PyObject *object, + PyObject *encoder, + const char *encoding, + const char *errors) { - PyObject *encoder = NULL; PyObject *args = NULL, *result = NULL; PyObject *v; - encoder = PyCodec_Encoder(encoding); - if (encoder == NULL) - goto onError; - args = args_tuple(object, errors); if (args == NULL) goto onError; @@ -358,18 +383,15 @@ errors is passed to the decoder factory as argument if non-NULL. */ -PyObject *PyCodec_Decode(PyObject *object, - const char *encoding, - const char *errors) +static PyObject * +_PyCodec_DecodeInternal(PyObject *object, + PyObject *decoder, + const char *encoding, + const char *errors) { - PyObject *decoder = NULL; PyObject *args = NULL, *result = NULL; PyObject *v; - decoder = PyCodec_Decoder(encoding); - if (decoder == NULL) - goto onError; - args = args_tuple(object, errors); if (args == NULL) goto onError; @@ -399,6 +421,139 @@ return NULL; } +/* Generic encoding/decoding API */ +PyObject *PyCodec_Encode(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *encoder; + + encoder = PyCodec_Encoder(encoding); + if (encoder == NULL) + return NULL; + + return _PyCodec_EncodeInternal(object, encoder, encoding, errors); +} + +PyObject *PyCodec_Decode(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *decoder; + + decoder = PyCodec_Decoder(encoding); + if (decoder == NULL) + return NULL; + + return _PyCodec_DecodeInternal(object, decoder, encoding, errors); +} + +/* Text encoding/decoding API */ +PyObject * _PyCodec_LookupTextEncoding(const char *encoding, + const char *alternate_command) +{ + PyObject *codec; + PyObject *attr; + int is_text_codec; + + codec = _PyCodec_Lookup(encoding); + if (codec == NULL) + return NULL; + + /* Backwards compatibility: assume any raw tuple describes a text + * encoding, and the same for anything lacking the private + * attribute. + */ + if (Py_Py3kWarningFlag && !PyTuple_CheckExact(codec)) { + attr = PyObject_GetAttrString(codec, "_is_text_encoding"); + if (attr == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + goto onError; + PyErr_Clear(); + } else { + is_text_codec = PyObject_IsTrue(attr); + Py_DECREF(attr); + if (is_text_codec < 0) + goto onError; + if (!is_text_codec) { + PyObject *msg = PyString_FromFormat( + "'%.400s' is not a text encoding; " + "use %s to handle arbitrary codecs", + encoding, alternate_command); + if (msg == NULL) + goto onError; + if (PyErr_WarnPy3k(PyString_AS_STRING(msg), 1) < 0) { + Py_DECREF(msg); + goto onError; + } + Py_DECREF(msg); + } + } + } + + /* This appears to be a valid text encoding */ + return codec; + + onError: + Py_DECREF(codec); + return NULL; +} + + +static +PyObject *codec_getitem_checked(const char *encoding, + const char *alternate_command, + int index) +{ + PyObject *codec; + PyObject *v; + + codec = _PyCodec_LookupTextEncoding(encoding, alternate_command); + if (codec == NULL) + return NULL; + + v = PyTuple_GET_ITEM(codec, index); + Py_INCREF(v); + Py_DECREF(codec); + return v; +} + +static PyObject * _PyCodec_TextEncoder(const char *encoding) +{ + return codec_getitem_checked(encoding, "codecs.encode()", 0); +} + +static PyObject * _PyCodec_TextDecoder(const char *encoding) +{ + return codec_getitem_checked(encoding, "codecs.decode()", 1); +} + +PyObject *_PyCodec_EncodeText(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *encoder; + + encoder = _PyCodec_TextEncoder(encoding); + if (encoder == NULL) + return NULL; + + return _PyCodec_EncodeInternal(object, encoder, encoding, errors); +} + +PyObject *_PyCodec_DecodeText(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *decoder; + + decoder = _PyCodec_TextDecoder(encoding); + if (decoder == NULL) + return NULL; + + return _PyCodec_DecodeInternal(object, decoder, encoding, errors); +} + /* Register the error handling callback function error under the name name. This function will be called by the codec when it encounters an unencodable characters/undecodable bytes and doesn't know the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 21:05:31 2015 From: python-checkins at python.org (tal.einat) Date: Sun, 31 May 2015 19:05:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE5NTQz?= =?utf-8?q?=3A_Implementation_of_isclose_as_per_PEP_485?= Message-ID: <20150531190530.18157.77742@psf.io> https://hg.python.org/cpython/rev/0347f6e14ad6 changeset: 96426:0347f6e14ad6 branch: 3.5 parent: 96423:8296f0119f20 user: Tal Einat date: Sun May 31 22:05:00 2015 +0300 summary: Issue #19543: Implementation of isclose as per PEP 485 For details, see: PEP 0485 -- A Function for testing approximate equality Functions added: math.isclose() and cmath.isclose(). Original code by Chris Barker. Patch by Tal Einat. files: Doc/library/cmath.rst | 32 +++++ Doc/library/math.rst | 32 +++++ Doc/whatsnew/3.5.rst | 21 +++ Lib/test/test_cmath.py | 42 +++++++ Lib/test/test_math.py | 121 +++++++++++++++++++++ Misc/NEWS | 3 + Modules/clinic/cmathmodule.c.h | 53 +++++++++- Modules/cmathmodule.c | 68 +++++++++++ Modules/mathmodule.c | 79 +++++++++++++ 9 files changed, 450 insertions(+), 1 deletions(-) diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst --- a/Doc/library/cmath.rst +++ b/Doc/library/cmath.rst @@ -207,6 +207,38 @@ and ``False`` otherwise. +.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) + + Return ``True`` if the values *a* and *b* are close to each other and + ``False`` otherwise. + + Whether or not two values are considered close is determined according to + given absolute and relative tolerances. + + *rel_tol* is the relative tolerance -- it is the maximum allowed difference + between *a* and *b*, relative to the larger absolute value of *a* or *b*. + For example, to set a tolerance of 5%, pass ``rel_tol=0.05``. The default + tolerance is ``1e-09``, which assures that the two values are the same + within about 9 decimal digits. *rel_tol* must be greater than zero. + + *abs_tol* is the minimum absolute tolerance -- useful for comparisons near + zero. *abs_tol* must be at least zero. + + If no errors occur, the result will be: + ``abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)``. + + The IEEE 754 special values of ``NaN``, ``inf``, and ``-inf`` will be + handled according to IEEE rules. Specifically, ``NaN`` is not considered + close to any other value, including ``NaN``. ``inf`` and ``-inf`` are only + considered close to themselves. + + .. versionadded:: 3.5 + + .. seealso:: + + :pep:`485` -- A function for testing approximate equality + + Constants --------- diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -110,6 +110,38 @@ .. versionadded:: 3.5 +.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) + + Return ``True`` if the values *a* and *b* are close to each other and + ``False`` otherwise. + + Whether or not two values are considered close is determined according to + given absolute and relative tolerances. + + *rel_tol* is the relative tolerance -- it is the maximum allowed difference + between *a* and *b*, relative to the larger absolute value of *a* or *b*. + For example, to set a tolerance of 5%, pass ``rel_tol=0.05``. The default + tolerance is ``1e-09``, which assures that the two values are the same + within about 9 decimal digits. *rel_tol* must be greater than zero. + + *abs_tol* is the minimum absolute tolerance -- useful for comparisons near + zero. *abs_tol* must be at least zero. + + If no errors occur, the result will be: + ``abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)``. + + The IEEE 754 special values of ``NaN``, ``inf``, and ``-inf`` will be + handled according to IEEE rules. Specifically, ``NaN`` is not considered + close to any other value, including ``NaN``. ``inf`` and ``-inf`` are only + considered close to themselves. + + .. versionadded:: 3.5 + + .. seealso:: + + :pep:`485` -- A function for testing approximate equality + + .. function:: isfinite(x) Return ``True`` if *x* is neither an infinity nor a NaN, and diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -285,6 +285,18 @@ :pep:`488` -- Multi-phase extension module initialization +PEP 485: A function for testing approximate equality +---------------------------------------------------- + +:pep:`485` adds the :func:`math.isclose` and :func:`cmath.isclose` +functions which tell whether two values are approximately equal or +"close" to each other. Whether or not two values are considered +close is determined according to given absolute and relative tolerances. + +.. seealso:: + + :pep:`485` -- A function for testing approximate equality + Other Language Changes ====================== @@ -346,6 +358,13 @@ * :class:`~cgi.FieldStorage` now supports the context management protocol. (Contributed by Berker Peksag in :issue:`20289`.) +cmath +----- + +* :func:`cmath.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) + + code ---- @@ -578,6 +597,8 @@ * :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark Dickinson in :issue:`23185`.) +* :func:`math.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) shutil ------ diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -1,5 +1,6 @@ from test.support import requires_IEEE_754 from test.test_math import parse_testfile, test_file +import test.test_math as test_math import unittest import cmath, math from cmath import phase, polar, rect, pi @@ -529,5 +530,46 @@ self.assertComplexIdentical(cmath.atanh(z), z) +class IsCloseTests(test_math.IsCloseTests): + isclose = cmath.isclose + + def test_reject_complex_tolerances(self): + with self.assertRaises(TypeError): + self.isclose(1j, 1j, rel_tol=1j) + + with self.assertRaises(TypeError): + self.isclose(1j, 1j, abs_tol=1j) + + with self.assertRaises(TypeError): + self.isclose(1j, 1j, rel_tol=1j, abs_tol=1j) + + def test_complex_values(self): + # test complex values that are close to within 12 decimal places + complex_examples = [(1.0+1.0j, 1.000000000001+1.0j), + (1.0+1.0j, 1.0+1.000000000001j), + (-1.0+1.0j, -1.000000000001+1.0j), + (1.0-1.0j, 1.0-0.999999999999j), + ] + + self.assertAllClose(complex_examples, rel_tol=1e-12) + self.assertAllNotClose(complex_examples, rel_tol=1e-13) + + def test_complex_near_zero(self): + # test values near zero that are near to within three decimal places + near_zero_examples = [(0.001j, 0), + (0.001, 0), + (0.001+0.001j, 0), + (-0.001+0.001j, 0), + (0.001-0.001j, 0), + (-0.001-0.001j, 0), + ] + + self.assertAllClose(near_zero_examples, abs_tol=1.5e-03) + self.assertAllNotClose(near_zero_examples, abs_tol=0.5e-03) + + self.assertIsClose(0.001-0.001j, 0.001+0.001j, abs_tol=2e-03) + self.assertIsNotClose(0.001-0.001j, 0.001+0.001j, abs_tol=1e-03) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1166,10 +1166,131 @@ '\n '.join(failures)) +class IsCloseTests(unittest.TestCase): + isclose = math.isclose # sublcasses should override this + + def assertIsClose(self, a, b, *args, **kwargs): + self.assertTrue(self.isclose(a, b, *args, **kwargs), + msg="%s and %s should be close!" % (a, b)) + + def assertIsNotClose(self, a, b, *args, **kwargs): + self.assertFalse(self.isclose(a, b, *args, **kwargs), + msg="%s and %s should not be close!" % (a, b)) + + def assertAllClose(self, examples, *args, **kwargs): + for a, b in examples: + self.assertIsClose(a, b, *args, **kwargs) + + def assertAllNotClose(self, examples, *args, **kwargs): + for a, b in examples: + self.assertIsNotClose(a, b, *args, **kwargs) + + def test_negative_tolerances(self): + # ValueError should be raised if either tolerance is less than zero + with self.assertRaises(ValueError): + self.assertIsClose(1, 1, rel_tol=-1e-100) + with self.assertRaises(ValueError): + self.assertIsClose(1, 1, rel_tol=1e-100, abs_tol=-1e10) + + def test_identical(self): + # identical values must test as close + identical_examples = [(2.0, 2.0), + (0.1e200, 0.1e200), + (1.123e-300, 1.123e-300), + (12345, 12345.0), + (0.0, -0.0), + (345678, 345678)] + self.assertAllClose(identical_examples, rel_tol=0.0, abs_tol=0.0) + + def test_eight_decimal_places(self): + # examples that are close to 1e-8, but not 1e-9 + eight_decimal_places_examples = [(1e8, 1e8 + 1), + (-1e-8, -1.000000009e-8), + (1.12345678, 1.12345679)] + self.assertAllClose(eight_decimal_places_examples, rel_tol=1e-8) + self.assertAllNotClose(eight_decimal_places_examples, rel_tol=1e-9) + + def test_near_zero(self): + # values close to zero + near_zero_examples = [(1e-9, 0.0), + (-1e-9, 0.0), + (-1e-150, 0.0)] + # these should not be close to any rel_tol + self.assertAllNotClose(near_zero_examples, rel_tol=0.9) + # these should be close to abs_tol=1e-8 + self.assertAllClose(near_zero_examples, abs_tol=1e-8) + + def test_identical_infinite(self): + # these are close regardless of tolerance -- i.e. they are equal + self.assertIsClose(INF, INF) + self.assertIsClose(INF, INF, abs_tol=0.0) + self.assertIsClose(NINF, NINF) + self.assertIsClose(NINF, NINF, abs_tol=0.0) + + def test_inf_ninf_nan(self): + # these should never be close (following IEEE 754 rules for equality) + not_close_examples = [(NAN, NAN), + (NAN, 1e-100), + (1e-100, NAN), + (INF, NAN), + (NAN, INF), + (INF, NINF), + (INF, 1.0), + (1.0, INF), + (INF, 1e308), + (1e308, INF)] + # use largest reasonable tolerance + self.assertAllNotClose(not_close_examples, abs_tol=0.999999999999999) + + def test_zero_tolerance(self): + # test with zero tolerance + zero_tolerance_close_examples = [(1.0, 1.0), + (-3.4, -3.4), + (-1e-300, -1e-300)] + self.assertAllClose(zero_tolerance_close_examples, rel_tol=0.0) + + zero_tolerance_not_close_examples = [(1.0, 1.000000000000001), + (0.99999999999999, 1.0), + (1.0e200, .999999999999999e200)] + self.assertAllNotClose(zero_tolerance_not_close_examples, rel_tol=0.0) + + def test_assymetry(self): + # test the assymetry example from PEP 485 + self.assertAllClose([(9, 10), (10, 9)], rel_tol=0.1) + + def test_integers(self): + # test with integer values + integer_examples = [(100000001, 100000000), + (123456789, 123456788)] + + self.assertAllClose(integer_examples, rel_tol=1e-8) + self.assertAllNotClose(integer_examples, rel_tol=1e-9) + + def test_decimals(self): + # test with Decimal values + from decimal import Decimal + + decimal_examples = [(Decimal('1.00000001'), Decimal('1.0')), + (Decimal('1.00000001e-20'), Decimal('1.0e-20')), + (Decimal('1.00000001e-100'), Decimal('1.0e-100'))] + self.assertAllClose(decimal_examples, rel_tol=1e-8) + self.assertAllNotClose(decimal_examples, rel_tol=1e-9) + + def test_fractions(self): + # test with Fraction values + from fractions import Fraction + + # could use some more examples here! + fraction_examples = [(Fraction(1, 100000000) + 1, Fraction(1))] + self.assertAllClose(fraction_examples, rel_tol=1e-8) + self.assertAllNotClose(fraction_examples, rel_tol=1e-9) + + def test_main(): from doctest import DocFileSuite suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(MathTests)) + suite.addTest(unittest.makeSuite(IsCloseTests)) suite.addTest(DocFileSuite("ieee754.txt")) run_unittest(suite) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -273,6 +273,9 @@ - Issue #24298: Fix inspect.signature() to correctly unwrap wrappers around bound methods. +- Issue #24270: Add math.isclose() and cmath.isclose() functions as per PEP 485. + Contributed by Chris Barker and Tal Einat. + IDLE ---- diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -806,4 +806,55 @@ exit: return return_value; } -/*[clinic end generated code: output=274f59792cf4f418 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(cmath_isclose__doc__, +"isclose($module, /, a, b, *, rel_tol=1e-09, abs_tol=0.0)\n" +"--\n" +"\n" +"Determine whether two complex numbers are close in value.\n" +"\n" +" rel_tol\n" +" maximum difference for being considered \"close\", relative to the\n" +" magnitude of the input values\n" +" abs_tol\n" +" maximum difference for being considered \"close\", regardless of the\n" +" magnitude of the input values\n" +"\n" +"Return True if a is close in value to b, and False otherwise.\n" +"\n" +"For the values to be considered close, the difference between them must be\n" +"smaller than at least one of the tolerances.\n" +"\n" +"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is\n" +"not close to anything, even itself. inf and -inf are only close to themselves."); + +#define CMATH_ISCLOSE_METHODDEF \ + {"isclose", (PyCFunction)cmath_isclose, METH_VARARGS|METH_KEYWORDS, cmath_isclose__doc__}, + +static int +cmath_isclose_impl(PyModuleDef *module, Py_complex a, Py_complex b, + double rel_tol, double abs_tol); + +static PyObject * +cmath_isclose(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; + Py_complex a; + Py_complex b; + double rel_tol = 1e-09; + double abs_tol = 0.0; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "DD|$dd:isclose", _keywords, + &a, &b, &rel_tol, &abs_tol)) + goto exit; + _return_value = cmath_isclose_impl(module, a, b, rel_tol, abs_tol); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=229e9c48c9d27362 input=a9049054013a1b77]*/ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -1114,6 +1114,73 @@ Py_IS_INFINITY(z.imag)); } +/*[clinic input] +cmath.isclose -> bool + + a: Py_complex + b: Py_complex + * + rel_tol: double = 1e-09 + maximum difference for being considered "close", relative to the + magnitude of the input values + abs_tol: double = 0.0 + maximum difference for being considered "close", regardless of the + magnitude of the input values + +Determine whether two complex numbers are close in value. + +Return True if a is close in value to b, and False otherwise. + +For the values to be considered close, the difference between them must be +smaller than at least one of the tolerances. + +-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is +not close to anything, even itself. inf and -inf are only close to themselves. +[clinic start generated code]*/ + +static int +cmath_isclose_impl(PyModuleDef *module, Py_complex a, Py_complex b, + double rel_tol, double abs_tol) +/*[clinic end generated code: output=da0c535fb54e2310 input=df9636d7de1d4ac3]*/ +{ + double diff; + + /* sanity check on the inputs */ + if (rel_tol < 0.0 || abs_tol < 0.0 ) { + PyErr_SetString(PyExc_ValueError, + "tolerances must be non-negative"); + return -1; + } + + if ( (a.real == b.real) && (a.imag == b.imag) ) { + /* short circuit exact equality -- needed to catch two infinities of + the same sign. And perhaps speeds things up a bit sometimes. + */ + return 1; + } + + /* This catches the case of two infinities of opposite sign, or + one infinity and one finite number. Two infinities of opposite + sign would otherwise have an infinite relative tolerance. + Two infinities of the same sign are caught by the equality check + above. + */ + + if (Py_IS_INFINITY(a.real) || Py_IS_INFINITY(a.imag) || + Py_IS_INFINITY(b.real) || Py_IS_INFINITY(b.imag)) { + return 0; + } + + /* now do the regular computation + this is essentially the "weak" test from the Boost library + */ + + diff = _Py_c_abs(_Py_c_diff(a, b)); + + return (((diff <= rel_tol * _Py_c_abs(b)) || + (diff <= rel_tol * _Py_c_abs(a))) || + (diff <= abs_tol)); +} PyDoc_STRVAR(module_doc, "This module is always available. It provides access to mathematical\n" @@ -1129,6 +1196,7 @@ CMATH_COS_METHODDEF CMATH_COSH_METHODDEF CMATH_EXP_METHODDEF + CMATH_ISCLOSE_METHODDEF CMATH_ISFINITE_METHODDEF CMATH_ISINF_METHODDEF CMATH_ISNAN_METHODDEF diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -1990,6 +1990,83 @@ "isinf(x) -> bool\n\n\ Return True if x is a positive or negative infinity, and False otherwise."); +static PyObject * +math_isclose(PyObject *self, PyObject *args, PyObject *kwargs) +{ + double a, b; + double rel_tol = 1e-9; + double abs_tol = 0.0; + double diff = 0.0; + long result = 0; + + static char *keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; + + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "dd|$dd:isclose", + keywords, + &a, &b, &rel_tol, &abs_tol + )) + return NULL; + + /* sanity check on the inputs */ + if (rel_tol < 0.0 || abs_tol < 0.0 ) { + PyErr_SetString(PyExc_ValueError, + "tolerances must be non-negative"); + return NULL; + } + + if ( a == b ) { + /* short circuit exact equality -- needed to catch two infinities of + the same sign. And perhaps speeds things up a bit sometimes. + */ + Py_RETURN_TRUE; + } + + /* This catches the case of two infinities of opposite sign, or + one infinity and one finite number. Two infinities of opposite + sign would otherwise have an infinite relative tolerance. + Two infinities of the same sign are caught by the equality check + above. + */ + + if (Py_IS_INFINITY(a) || Py_IS_INFINITY(b)) { + Py_RETURN_FALSE; + } + + /* now do the regular computation + this is essentially the "weak" test from the Boost library + */ + + diff = fabs(b - a); + + result = (((diff <= fabs(rel_tol * b)) || + (diff <= fabs(rel_tol * a))) || + (diff <= abs_tol)); + + return PyBool_FromLong(result); +} + +PyDoc_STRVAR(math_isclose_doc, +"is_close(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool\n" +"\n" +"Determine whether two floating point numbers are close in value.\n" +"\n" +" rel_tol\n" +" maximum difference for being considered \"close\", relative to the\n" +" magnitude of the input values\n" +" abs_tol\n" +" maximum difference for being considered \"close\", regardless of the\n" +" magnitude of the input values\n" +"\n" +"Return True if a is close in value to b, and False otherwise.\n" +"\n" +"For the values to be considered close, the difference between them\n" +"must be smaller than at least one of the tolerances.\n" +"\n" +"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That\n" +"is, NaN is not close to anything, even itself. inf and -inf are\n" +"only close to themselves."); + static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"acosh", math_acosh, METH_O, math_acosh_doc}, @@ -2016,6 +2093,8 @@ {"gamma", math_gamma, METH_O, math_gamma_doc}, {"gcd", math_gcd, METH_VARARGS, math_gcd_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, + {"isclose", (PyCFunction) math_isclose, METH_VARARGS | METH_KEYWORDS, + math_isclose_doc}, {"isfinite", math_isfinite, METH_O, math_isfinite_doc}, {"isinf", math_isinf, METH_O, math_isinf_doc}, {"isnan", math_isnan, METH_O, math_isnan_doc}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 21:16:35 2015 From: python-checkins at python.org (tal.einat) Date: Sun, 31 May 2015 19:16:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319543=3A_Implementation_of_isclose_as_per_PEP_4?= =?utf-8?q?85?= Message-ID: <20150531191635.27644.26952@psf.io> https://hg.python.org/cpython/rev/5c8c123943cf changeset: 96427:5c8c123943cf parent: 96424:60f5091cbfbf parent: 96426:0347f6e14ad6 user: Tal Einat date: Sun May 31 22:15:11 2015 +0300 summary: Issue #19543: Implementation of isclose as per PEP 485 For details, see: PEP 0485 -- A Function for testing approximate equality Functions added: math.isclose() and cmath.isclose(). Original code by Chris Barker. Patch by Tal Einat. (merge 3.5) files: Doc/library/cmath.rst | 32 +++++ Doc/library/math.rst | 32 +++++ Doc/whatsnew/3.5.rst | 21 +++ Lib/test/test_cmath.py | 42 +++++++ Lib/test/test_math.py | 121 +++++++++++++++++++++ Misc/NEWS | 3 + Modules/clinic/cmathmodule.c.h | 53 +++++++++- Modules/cmathmodule.c | 68 +++++++++++ Modules/mathmodule.c | 79 +++++++++++++ 9 files changed, 450 insertions(+), 1 deletions(-) diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst --- a/Doc/library/cmath.rst +++ b/Doc/library/cmath.rst @@ -207,6 +207,38 @@ and ``False`` otherwise. +.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) + + Return ``True`` if the values *a* and *b* are close to each other and + ``False`` otherwise. + + Whether or not two values are considered close is determined according to + given absolute and relative tolerances. + + *rel_tol* is the relative tolerance -- it is the maximum allowed difference + between *a* and *b*, relative to the larger absolute value of *a* or *b*. + For example, to set a tolerance of 5%, pass ``rel_tol=0.05``. The default + tolerance is ``1e-09``, which assures that the two values are the same + within about 9 decimal digits. *rel_tol* must be greater than zero. + + *abs_tol* is the minimum absolute tolerance -- useful for comparisons near + zero. *abs_tol* must be at least zero. + + If no errors occur, the result will be: + ``abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)``. + + The IEEE 754 special values of ``NaN``, ``inf``, and ``-inf`` will be + handled according to IEEE rules. Specifically, ``NaN`` is not considered + close to any other value, including ``NaN``. ``inf`` and ``-inf`` are only + considered close to themselves. + + .. versionadded:: 3.5 + + .. seealso:: + + :pep:`485` -- A function for testing approximate equality + + Constants --------- diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -110,6 +110,38 @@ .. versionadded:: 3.5 +.. function:: isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) + + Return ``True`` if the values *a* and *b* are close to each other and + ``False`` otherwise. + + Whether or not two values are considered close is determined according to + given absolute and relative tolerances. + + *rel_tol* is the relative tolerance -- it is the maximum allowed difference + between *a* and *b*, relative to the larger absolute value of *a* or *b*. + For example, to set a tolerance of 5%, pass ``rel_tol=0.05``. The default + tolerance is ``1e-09``, which assures that the two values are the same + within about 9 decimal digits. *rel_tol* must be greater than zero. + + *abs_tol* is the minimum absolute tolerance -- useful for comparisons near + zero. *abs_tol* must be at least zero. + + If no errors occur, the result will be: + ``abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)``. + + The IEEE 754 special values of ``NaN``, ``inf``, and ``-inf`` will be + handled according to IEEE rules. Specifically, ``NaN`` is not considered + close to any other value, including ``NaN``. ``inf`` and ``-inf`` are only + considered close to themselves. + + .. versionadded:: 3.5 + + .. seealso:: + + :pep:`485` -- A function for testing approximate equality + + .. function:: isfinite(x) Return ``True`` if *x* is neither an infinity nor a NaN, and diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -285,6 +285,18 @@ :pep:`488` -- Multi-phase extension module initialization +PEP 485: A function for testing approximate equality +---------------------------------------------------- + +:pep:`485` adds the :func:`math.isclose` and :func:`cmath.isclose` +functions which tell whether two values are approximately equal or +"close" to each other. Whether or not two values are considered +close is determined according to given absolute and relative tolerances. + +.. seealso:: + + :pep:`485` -- A function for testing approximate equality + Other Language Changes ====================== @@ -346,6 +358,13 @@ * :class:`~cgi.FieldStorage` now supports the context management protocol. (Contributed by Berker Peksag in :issue:`20289`.) +cmath +----- + +* :func:`cmath.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) + + code ---- @@ -578,6 +597,8 @@ * :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark Dickinson in :issue:`23185`.) +* :func:`math.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) shutil ------ diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -1,5 +1,6 @@ from test.support import requires_IEEE_754 from test.test_math import parse_testfile, test_file +import test.test_math as test_math import unittest import cmath, math from cmath import phase, polar, rect, pi @@ -529,5 +530,46 @@ self.assertComplexIdentical(cmath.atanh(z), z) +class IsCloseTests(test_math.IsCloseTests): + isclose = cmath.isclose + + def test_reject_complex_tolerances(self): + with self.assertRaises(TypeError): + self.isclose(1j, 1j, rel_tol=1j) + + with self.assertRaises(TypeError): + self.isclose(1j, 1j, abs_tol=1j) + + with self.assertRaises(TypeError): + self.isclose(1j, 1j, rel_tol=1j, abs_tol=1j) + + def test_complex_values(self): + # test complex values that are close to within 12 decimal places + complex_examples = [(1.0+1.0j, 1.000000000001+1.0j), + (1.0+1.0j, 1.0+1.000000000001j), + (-1.0+1.0j, -1.000000000001+1.0j), + (1.0-1.0j, 1.0-0.999999999999j), + ] + + self.assertAllClose(complex_examples, rel_tol=1e-12) + self.assertAllNotClose(complex_examples, rel_tol=1e-13) + + def test_complex_near_zero(self): + # test values near zero that are near to within three decimal places + near_zero_examples = [(0.001j, 0), + (0.001, 0), + (0.001+0.001j, 0), + (-0.001+0.001j, 0), + (0.001-0.001j, 0), + (-0.001-0.001j, 0), + ] + + self.assertAllClose(near_zero_examples, abs_tol=1.5e-03) + self.assertAllNotClose(near_zero_examples, abs_tol=0.5e-03) + + self.assertIsClose(0.001-0.001j, 0.001+0.001j, abs_tol=2e-03) + self.assertIsNotClose(0.001-0.001j, 0.001+0.001j, abs_tol=1e-03) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1166,10 +1166,131 @@ '\n '.join(failures)) +class IsCloseTests(unittest.TestCase): + isclose = math.isclose # sublcasses should override this + + def assertIsClose(self, a, b, *args, **kwargs): + self.assertTrue(self.isclose(a, b, *args, **kwargs), + msg="%s and %s should be close!" % (a, b)) + + def assertIsNotClose(self, a, b, *args, **kwargs): + self.assertFalse(self.isclose(a, b, *args, **kwargs), + msg="%s and %s should not be close!" % (a, b)) + + def assertAllClose(self, examples, *args, **kwargs): + for a, b in examples: + self.assertIsClose(a, b, *args, **kwargs) + + def assertAllNotClose(self, examples, *args, **kwargs): + for a, b in examples: + self.assertIsNotClose(a, b, *args, **kwargs) + + def test_negative_tolerances(self): + # ValueError should be raised if either tolerance is less than zero + with self.assertRaises(ValueError): + self.assertIsClose(1, 1, rel_tol=-1e-100) + with self.assertRaises(ValueError): + self.assertIsClose(1, 1, rel_tol=1e-100, abs_tol=-1e10) + + def test_identical(self): + # identical values must test as close + identical_examples = [(2.0, 2.0), + (0.1e200, 0.1e200), + (1.123e-300, 1.123e-300), + (12345, 12345.0), + (0.0, -0.0), + (345678, 345678)] + self.assertAllClose(identical_examples, rel_tol=0.0, abs_tol=0.0) + + def test_eight_decimal_places(self): + # examples that are close to 1e-8, but not 1e-9 + eight_decimal_places_examples = [(1e8, 1e8 + 1), + (-1e-8, -1.000000009e-8), + (1.12345678, 1.12345679)] + self.assertAllClose(eight_decimal_places_examples, rel_tol=1e-8) + self.assertAllNotClose(eight_decimal_places_examples, rel_tol=1e-9) + + def test_near_zero(self): + # values close to zero + near_zero_examples = [(1e-9, 0.0), + (-1e-9, 0.0), + (-1e-150, 0.0)] + # these should not be close to any rel_tol + self.assertAllNotClose(near_zero_examples, rel_tol=0.9) + # these should be close to abs_tol=1e-8 + self.assertAllClose(near_zero_examples, abs_tol=1e-8) + + def test_identical_infinite(self): + # these are close regardless of tolerance -- i.e. they are equal + self.assertIsClose(INF, INF) + self.assertIsClose(INF, INF, abs_tol=0.0) + self.assertIsClose(NINF, NINF) + self.assertIsClose(NINF, NINF, abs_tol=0.0) + + def test_inf_ninf_nan(self): + # these should never be close (following IEEE 754 rules for equality) + not_close_examples = [(NAN, NAN), + (NAN, 1e-100), + (1e-100, NAN), + (INF, NAN), + (NAN, INF), + (INF, NINF), + (INF, 1.0), + (1.0, INF), + (INF, 1e308), + (1e308, INF)] + # use largest reasonable tolerance + self.assertAllNotClose(not_close_examples, abs_tol=0.999999999999999) + + def test_zero_tolerance(self): + # test with zero tolerance + zero_tolerance_close_examples = [(1.0, 1.0), + (-3.4, -3.4), + (-1e-300, -1e-300)] + self.assertAllClose(zero_tolerance_close_examples, rel_tol=0.0) + + zero_tolerance_not_close_examples = [(1.0, 1.000000000000001), + (0.99999999999999, 1.0), + (1.0e200, .999999999999999e200)] + self.assertAllNotClose(zero_tolerance_not_close_examples, rel_tol=0.0) + + def test_assymetry(self): + # test the assymetry example from PEP 485 + self.assertAllClose([(9, 10), (10, 9)], rel_tol=0.1) + + def test_integers(self): + # test with integer values + integer_examples = [(100000001, 100000000), + (123456789, 123456788)] + + self.assertAllClose(integer_examples, rel_tol=1e-8) + self.assertAllNotClose(integer_examples, rel_tol=1e-9) + + def test_decimals(self): + # test with Decimal values + from decimal import Decimal + + decimal_examples = [(Decimal('1.00000001'), Decimal('1.0')), + (Decimal('1.00000001e-20'), Decimal('1.0e-20')), + (Decimal('1.00000001e-100'), Decimal('1.0e-100'))] + self.assertAllClose(decimal_examples, rel_tol=1e-8) + self.assertAllNotClose(decimal_examples, rel_tol=1e-9) + + def test_fractions(self): + # test with Fraction values + from fractions import Fraction + + # could use some more examples here! + fraction_examples = [(Fraction(1, 100000000) + 1, Fraction(1))] + self.assertAllClose(fraction_examples, rel_tol=1e-8) + self.assertAllNotClose(fraction_examples, rel_tol=1e-9) + + def test_main(): from doctest import DocFileSuite suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(MathTests)) + suite.addTest(unittest.makeSuite(IsCloseTests)) suite.addTest(DocFileSuite("ieee754.txt")) run_unittest(suite) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -288,6 +288,9 @@ - Issue #24298: Fix inspect.signature() to correctly unwrap wrappers around bound methods. +- Issue #24270: Add math.isclose() and cmath.isclose() functions as per PEP 485. + Contributed by Chris Barker and Tal Einat. + IDLE ---- diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -806,4 +806,55 @@ exit: return return_value; } -/*[clinic end generated code: output=274f59792cf4f418 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(cmath_isclose__doc__, +"isclose($module, /, a, b, *, rel_tol=1e-09, abs_tol=0.0)\n" +"--\n" +"\n" +"Determine whether two complex numbers are close in value.\n" +"\n" +" rel_tol\n" +" maximum difference for being considered \"close\", relative to the\n" +" magnitude of the input values\n" +" abs_tol\n" +" maximum difference for being considered \"close\", regardless of the\n" +" magnitude of the input values\n" +"\n" +"Return True if a is close in value to b, and False otherwise.\n" +"\n" +"For the values to be considered close, the difference between them must be\n" +"smaller than at least one of the tolerances.\n" +"\n" +"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is\n" +"not close to anything, even itself. inf and -inf are only close to themselves."); + +#define CMATH_ISCLOSE_METHODDEF \ + {"isclose", (PyCFunction)cmath_isclose, METH_VARARGS|METH_KEYWORDS, cmath_isclose__doc__}, + +static int +cmath_isclose_impl(PyModuleDef *module, Py_complex a, Py_complex b, + double rel_tol, double abs_tol); + +static PyObject * +cmath_isclose(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; + Py_complex a; + Py_complex b; + double rel_tol = 1e-09; + double abs_tol = 0.0; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "DD|$dd:isclose", _keywords, + &a, &b, &rel_tol, &abs_tol)) + goto exit; + _return_value = cmath_isclose_impl(module, a, b, rel_tol, abs_tol); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=229e9c48c9d27362 input=a9049054013a1b77]*/ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -1114,6 +1114,73 @@ Py_IS_INFINITY(z.imag)); } +/*[clinic input] +cmath.isclose -> bool + + a: Py_complex + b: Py_complex + * + rel_tol: double = 1e-09 + maximum difference for being considered "close", relative to the + magnitude of the input values + abs_tol: double = 0.0 + maximum difference for being considered "close", regardless of the + magnitude of the input values + +Determine whether two complex numbers are close in value. + +Return True if a is close in value to b, and False otherwise. + +For the values to be considered close, the difference between them must be +smaller than at least one of the tolerances. + +-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is +not close to anything, even itself. inf and -inf are only close to themselves. +[clinic start generated code]*/ + +static int +cmath_isclose_impl(PyModuleDef *module, Py_complex a, Py_complex b, + double rel_tol, double abs_tol) +/*[clinic end generated code: output=da0c535fb54e2310 input=df9636d7de1d4ac3]*/ +{ + double diff; + + /* sanity check on the inputs */ + if (rel_tol < 0.0 || abs_tol < 0.0 ) { + PyErr_SetString(PyExc_ValueError, + "tolerances must be non-negative"); + return -1; + } + + if ( (a.real == b.real) && (a.imag == b.imag) ) { + /* short circuit exact equality -- needed to catch two infinities of + the same sign. And perhaps speeds things up a bit sometimes. + */ + return 1; + } + + /* This catches the case of two infinities of opposite sign, or + one infinity and one finite number. Two infinities of opposite + sign would otherwise have an infinite relative tolerance. + Two infinities of the same sign are caught by the equality check + above. + */ + + if (Py_IS_INFINITY(a.real) || Py_IS_INFINITY(a.imag) || + Py_IS_INFINITY(b.real) || Py_IS_INFINITY(b.imag)) { + return 0; + } + + /* now do the regular computation + this is essentially the "weak" test from the Boost library + */ + + diff = _Py_c_abs(_Py_c_diff(a, b)); + + return (((diff <= rel_tol * _Py_c_abs(b)) || + (diff <= rel_tol * _Py_c_abs(a))) || + (diff <= abs_tol)); +} PyDoc_STRVAR(module_doc, "This module is always available. It provides access to mathematical\n" @@ -1129,6 +1196,7 @@ CMATH_COS_METHODDEF CMATH_COSH_METHODDEF CMATH_EXP_METHODDEF + CMATH_ISCLOSE_METHODDEF CMATH_ISFINITE_METHODDEF CMATH_ISINF_METHODDEF CMATH_ISNAN_METHODDEF diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -1990,6 +1990,83 @@ "isinf(x) -> bool\n\n\ Return True if x is a positive or negative infinity, and False otherwise."); +static PyObject * +math_isclose(PyObject *self, PyObject *args, PyObject *kwargs) +{ + double a, b; + double rel_tol = 1e-9; + double abs_tol = 0.0; + double diff = 0.0; + long result = 0; + + static char *keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL}; + + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "dd|$dd:isclose", + keywords, + &a, &b, &rel_tol, &abs_tol + )) + return NULL; + + /* sanity check on the inputs */ + if (rel_tol < 0.0 || abs_tol < 0.0 ) { + PyErr_SetString(PyExc_ValueError, + "tolerances must be non-negative"); + return NULL; + } + + if ( a == b ) { + /* short circuit exact equality -- needed to catch two infinities of + the same sign. And perhaps speeds things up a bit sometimes. + */ + Py_RETURN_TRUE; + } + + /* This catches the case of two infinities of opposite sign, or + one infinity and one finite number. Two infinities of opposite + sign would otherwise have an infinite relative tolerance. + Two infinities of the same sign are caught by the equality check + above. + */ + + if (Py_IS_INFINITY(a) || Py_IS_INFINITY(b)) { + Py_RETURN_FALSE; + } + + /* now do the regular computation + this is essentially the "weak" test from the Boost library + */ + + diff = fabs(b - a); + + result = (((diff <= fabs(rel_tol * b)) || + (diff <= fabs(rel_tol * a))) || + (diff <= abs_tol)); + + return PyBool_FromLong(result); +} + +PyDoc_STRVAR(math_isclose_doc, +"is_close(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool\n" +"\n" +"Determine whether two floating point numbers are close in value.\n" +"\n" +" rel_tol\n" +" maximum difference for being considered \"close\", relative to the\n" +" magnitude of the input values\n" +" abs_tol\n" +" maximum difference for being considered \"close\", regardless of the\n" +" magnitude of the input values\n" +"\n" +"Return True if a is close in value to b, and False otherwise.\n" +"\n" +"For the values to be considered close, the difference between them\n" +"must be smaller than at least one of the tolerances.\n" +"\n" +"-inf, inf and NaN behave similarly to the IEEE 754 Standard. That\n" +"is, NaN is not close to anything, even itself. inf and -inf are\n" +"only close to themselves."); + static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"acosh", math_acosh, METH_O, math_acosh_doc}, @@ -2016,6 +2093,8 @@ {"gamma", math_gamma, METH_O, math_gamma_doc}, {"gcd", math_gcd, METH_VARARGS, math_gcd_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, + {"isclose", (PyCFunction) math_isclose, METH_VARARGS | METH_KEYWORDS, + math_isclose_doc}, {"isfinite", math_isfinite, METH_O, math_isfinite_doc}, {"isinf", math_isinf, METH_O, math_isinf_doc}, {"isnan", math_isnan, METH_O, math_isnan_doc}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 21:18:38 2015 From: python-checkins at python.org (tal.einat) Date: Sun, 31 May 2015 19:18:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_minor_fix_of_m?= =?utf-8?q?odule_order_in_whatsnew/3=2E5?= Message-ID: <20150531191838.91789.22073@psf.io> https://hg.python.org/cpython/rev/d8deabc8d39a changeset: 96428:d8deabc8d39a branch: 3.5 parent: 96426:0347f6e14ad6 user: Tal Einat date: Sun May 31 22:18:31 2015 +0300 summary: minor fix of module order in whatsnew/3.5 files: Doc/whatsnew/3.5.rst | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -550,6 +550,14 @@ * JSON decoder now raises :exc:`json.JSONDecodeError` instead of :exc:`ValueError`. (Contributed by Serhiy Storchaka in :issue:`19361`.) +math +---- + +* :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark + Dickinson in :issue:`23185`.) +* :func:`math.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) + os -- @@ -592,14 +600,6 @@ * Now unmatched groups are replaced with empty strings in :func:`re.sub` and :func:`re.subn`. (Contributed by Serhiy Storchaka in :issue:`1519638`.) -math ----- - -* :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark - Dickinson in :issue:`23185`.) -* :func:`math.isclose` function added. - (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) - shutil ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 21:19:33 2015 From: python-checkins at python.org (tal.einat) Date: Sun, 31 May 2015 19:19:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_minor_fix_of_module_order_in_whatsnew/3=2E5?= Message-ID: <20150531191933.18690.37415@psf.io> https://hg.python.org/cpython/rev/7f9421c800d1 changeset: 96429:7f9421c800d1 parent: 96427:5c8c123943cf parent: 96428:d8deabc8d39a user: Tal Einat date: Sun May 31 22:19:27 2015 +0300 summary: minor fix of module order in whatsnew/3.5 (merge 3.5) files: Doc/whatsnew/3.5.rst | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -550,6 +550,14 @@ * JSON decoder now raises :exc:`json.JSONDecodeError` instead of :exc:`ValueError`. (Contributed by Serhiy Storchaka in :issue:`19361`.) +math +---- + +* :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark + Dickinson in :issue:`23185`.) +* :func:`math.isclose` function added. + (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) + os -- @@ -592,14 +600,6 @@ * Now unmatched groups are replaced with empty strings in :func:`re.sub` and :func:`re.subn`. (Contributed by Serhiy Storchaka in :issue:`1519638`.) -math ----- - -* :data:`math.inf` and :data:`math.nan` constants added. (Contributed by Mark - Dickinson in :issue:`23185`.) -* :func:`math.isclose` function added. - (Contributed by Chris Barker and Tal Einat in :issue:`24270`.) - shutil ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 23:13:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:13:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24180=3A_Document_sys=2E=28set=7Cget=29=5Fcoroutin?= =?utf-8?q?e=5Fwrapper?= Message-ID: <20150531211340.91771.61701@psf.io> https://hg.python.org/cpython/rev/ca489c50fbd1 changeset: 96431:ca489c50fbd1 parent: 96429:7f9421c800d1 parent: 96430:3eb817e19090 user: Yury Selivanov date: Sun May 31 17:13:27 2015 -0400 summary: Issue 24180: Document sys.(set|get)_coroutine_wrapper (Merge 3.5) files: Doc/library/sys.rst | 34 +++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -576,6 +576,18 @@ *service_pack_major*, *suite_mask*, and *product_type*. +.. function:: get_coroutine_wrapper() + + Returns ``None``, or a wrapper set by :func:`set_coroutine_wrapper`. + + .. versionadded:: 3.5 + See :pep:`492` for more details. + + .. note:: + This function has been added on a provisional basis (see :pep:`411` + for details.) Use it only for debug purposes. + + .. data:: hash_info A :term:`struct sequence` giving parameters of the numeric hash @@ -1061,6 +1073,28 @@ thus not likely to be implemented elsewhere. +.. function:: set_coroutine_wrapper(wrapper) + + Allows to intercept creation of :term:`coroutine` objects. + + *wrapper* must be either: + + * a callable that accepts one argument (a coroutine object); + * ``None``, to reset the wrapper. + + If called twice, the new wrapper replaces the previous one. The function + is thread-specific. + + See also :func:`get_coroutine_wrapper`. + + .. versionadded:: 3.5 + See :pep:`492` for more details. + + .. note:: + This function has been added on a provisional basis (see :pep:`411` + for details.) Use it only for debug purposes. + + .. data:: stdin stdout stderr -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 23:13:39 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:13:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQxODA6?= =?utf-8?q?_Document_sys=2E=28set=7Cget=29=5Fcoroutine=5Fwrapper?= Message-ID: <20150531211339.18149.55931@psf.io> https://hg.python.org/cpython/rev/3eb817e19090 changeset: 96430:3eb817e19090 branch: 3.5 parent: 96428:d8deabc8d39a user: Yury Selivanov date: Sun May 31 17:13:08 2015 -0400 summary: Issue 24180: Document sys.(set|get)_coroutine_wrapper files: Doc/library/sys.rst | 34 +++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -576,6 +576,18 @@ *service_pack_major*, *suite_mask*, and *product_type*. +.. function:: get_coroutine_wrapper() + + Returns ``None``, or a wrapper set by :func:`set_coroutine_wrapper`. + + .. versionadded:: 3.5 + See :pep:`492` for more details. + + .. note:: + This function has been added on a provisional basis (see :pep:`411` + for details.) Use it only for debug purposes. + + .. data:: hash_info A :term:`struct sequence` giving parameters of the numeric hash @@ -1061,6 +1073,28 @@ thus not likely to be implemented elsewhere. +.. function:: set_coroutine_wrapper(wrapper) + + Allows to intercept creation of :term:`coroutine` objects. + + *wrapper* must be either: + + * a callable that accepts one argument (a coroutine object); + * ``None``, to reset the wrapper. + + If called twice, the new wrapper replaces the previous one. The function + is thread-specific. + + See also :func:`get_coroutine_wrapper`. + + .. versionadded:: 3.5 + See :pep:`492` for more details. + + .. note:: + This function has been added on a provisional basis (see :pep:`411` + for details.) Use it only for debug purposes. + + .. data:: stdin stdout stderr -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 23:15:37 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:15:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_pep_485_status=3B_upda?= =?utf-8?q?te_pep_478?= Message-ID: <20150531211537.25413.21280@psf.io> https://hg.python.org/peps/rev/168b42214ff6 changeset: 5884:168b42214ff6 user: Yury Selivanov date: Sun May 31 17:15:34 2015 -0400 summary: Update pep 485 status; update pep 478 files: pep-0478.txt | 4 +--- pep-0485.txt | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -70,10 +70,8 @@ * PEP 488, elimination of PYO files * PEP 484, type hints * PEP 489, redesigning extension module loading +* PEP 485, math.isclose(), a function for testing approximate equality -Accepted PEPs: - -* PEP 485, math.isclose(), a function for testing approximate equality Proposed changes for 3.5: diff --git a/pep-0485.txt b/pep-0485.txt --- a/pep-0485.txt +++ b/pep-0485.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Christopher Barker -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 20-Jan-2015 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 31 23:17:36 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:17:36 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Update_doc_on_set?= =?utf-8?q?=5Fcoroutine=5Fwrapper?= Message-ID: <20150531211736.24099.33282@psf.io> https://hg.python.org/peps/rev/76847ca52a62 changeset: 5885:76847ca52a62 user: Yury Selivanov date: Sun May 31 17:17:34 2015 -0400 summary: pep-492: Update doc on set_coroutine_wrapper files: pep-0492.txt | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -684,12 +684,12 @@ * ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` can be used in ``await`` expression. See `Await Expression`_ for details. -* ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation - of *coroutine* objects. ``wrapper`` must be a callable that accepts - one argument: a *coroutine* object or ``None``. ``None`` resets the - wrapper. If called twice, the new wrapper replaces the previous one. - The function is thread-specific. See `Debugging Features`_ for more - details. +* ``sys.set_coroutine_wrapper(wrapper)`` allows to intercept creation of + *coroutine* objects. ``wrapper`` must be either a callable that + accepts one argument (a *coroutine* object), or ``None``. ``None`` + resets the wrapper. If called twice, the new wrapper replaces the + previous one. The function is thread-specific. See `Debugging + Features`_ for more details. * ``sys.get_coroutine_wrapper()`` returns the current wrapper object. Returns ``None`` if no wrapper was set. The function is -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun May 31 23:21:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:21:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24180=3A_Mention_sys=2E=28get=7Cset=29=5Fcoroutine?= =?utf-8?q?=5Fwrapper_in_whatsnew?= Message-ID: <20150531212154.27640.27376@psf.io> https://hg.python.org/cpython/rev/10f92b4d55ed changeset: 96433:10f92b4d55ed parent: 96431:ca489c50fbd1 parent: 96432:8a185bb62a25 user: Yury Selivanov date: Sun May 31 17:21:49 2015 -0400 summary: Issue 24180: Mention sys.(get|set)_coroutine_wrapper in whatsnew files: Doc/whatsnew/3.5.rst | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -689,6 +689,12 @@ API than :func:`~subprocess.call`, :func:`~subprocess.check_call` and :func:`~subprocess.check_output`. +sys +--- + +* New :func:`~sys.set_coroutine_wrapper` and :func:`~sys.get_coroutine_wrapper` + functions. (Contributed by Yury Selivanov in :issue:`24017`.) + sysconfig --------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun May 31 23:21:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 31 May 2015 21:21:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgMjQxODA6?= =?utf-8?q?_Mention_sys=2E=28get=7Cset=29=5Fcoroutine=5Fwrapper_in_whatsne?= =?utf-8?q?w?= Message-ID: <20150531212154.89793.51837@psf.io> https://hg.python.org/cpython/rev/8a185bb62a25 changeset: 96432:8a185bb62a25 branch: 3.5 parent: 96430:3eb817e19090 user: Yury Selivanov date: Sun May 31 17:21:38 2015 -0400 summary: Issue 24180: Mention sys.(get|set)_coroutine_wrapper in whatsnew files: Doc/whatsnew/3.5.rst | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -689,6 +689,12 @@ API than :func:`~subprocess.call`, :func:`~subprocess.check_call` and :func:`~subprocess.check_output`. +sys +--- + +* New :func:`~sys.set_coroutine_wrapper` and :func:`~sys.get_coroutine_wrapper` + functions. (Contributed by Yury Selivanov in :issue:`24017`.) + sysconfig --------- -- Repository URL: https://hg.python.org/cpython